BWAPI
|
00001 // Copyright (c) 2006 Fernando Luis Cacciola Carballal. All rights reserved. 00002 // 00003 // This file is part of CGAL (www.cgal.org); you may redistribute it under 00004 // the terms of the Q Public License version 1.0. 00005 // See the file LICENSE.QPL distributed with CGAL. 00006 // 00007 // Licensees holding a valid commercial license may use this file in 00008 // accordance with the commercial license agreement provided with the software. 00009 // 00010 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00011 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00012 // 00013 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_traits_2_aux.h $ 00014 // $Id: Straight_skeleton_builder_traits_2_aux.h 44674 2008-07-31 13:31:26Z spion $ 00015 // 00016 // Author(s) : Fernando Cacciola <fernando_cacciola@ciudad.com.ar> 00017 // 00018 #ifndef CGAL_STRAIGHT_SKELETON_BUILDER_TRAITS_2_AUX_H 00019 #define CGAL_STRAIGHT_SKELETON_BUILDER_TRAITS_2_AUX_H 1 00020 00021 #include <CGAL/tags.h> 00022 #include <CGAL/Handle.h> 00023 #include <CGAL/Uncertain.h> 00024 #include <CGAL/certified_numeric_predicates.h> 00025 #include <CGAL/Quotient.h> 00026 #include <CGAL/certified_quotient_predicates.h> 00027 #include <CGAL/Unfiltered_predicate_adaptor.h> 00028 #include <CGAL/Filtered_predicate.h> 00029 #include <CGAL/Exact_predicates_inexact_constructions_kernel.h> 00030 00031 #include <boost/tuple/tuple.hpp> 00032 #include <boost/intrusive_ptr.hpp> 00033 #include <boost/optional/optional.hpp> 00034 #include <boost/none.hpp> 00035 00036 00037 #ifdef CGAL_USE_CORE 00038 # include <CGAL/CORE_BigFloat.h> 00039 #endif 00040 00041 CGAL_BEGIN_NAMESPACE 00042 00043 namespace CGAL_SS_i { 00044 00045 using boost::optional ; 00046 using boost::intrusive_ptr ; 00047 00048 template<class T> 00049 T const& validate ( boost::optional<T> const& o ) 00050 { 00051 if ( !o ) 00052 throw std::overflow_error("Arithmetic overflow"); 00053 return *o ; 00054 } 00055 00056 template<class NT> 00057 NT const& validate( NT const& n ) 00058 { 00059 if ( !CGAL_NTS is_finite(n) ) 00060 throw std::overflow_error("Arithmetic overflow"); 00061 return n ; 00062 } 00063 00064 // boost::make_optional is provided in Boost >= 1.34, but not before, so we define our own versions here. 00065 template<class T> optional<T> cgal_make_optional( T const& v ) { return optional<T>(v) ; } 00066 template<class T> optional<T> cgal_make_optional( bool cond, T const& v ) { return cond ? optional<T>(v) : optional<T>() ; } 00067 00068 template<class K> 00069 struct Is_filtering_kernel 00070 { 00071 typedef Tag_false type ; 00072 } ; 00073 00074 template<> 00075 struct Is_filtering_kernel< Exact_predicates_inexact_constructions_kernel > 00076 { 00077 typedef Tag_true type ; 00078 } ; 00079 00080 // 00081 // This is the same as Filtered_construction but uses optional<result> instead of exceptions. 00082 // 00083 template <class AC 00084 ,class EC 00085 ,class FC 00086 ,class C2E 00087 ,class C2F 00088 ,class E2C 00089 ,class F2C 00090 ,bool Protection = true 00091 > 00092 class Exceptionless_filtered_construction 00093 { 00094 private: 00095 EC Exact_construction; 00096 FC Filter_construction; 00097 C2E To_Exact; 00098 C2F To_Filtered; 00099 E2C From_Exact; 00100 F2C From_Filtered; 00101 00102 typedef typename AC::result_type AC_result_type; 00103 typedef typename FC::result_type FC_result_type; 00104 typedef typename EC::result_type EC_result_type; 00105 00106 public: 00107 typedef AC_result_type result_type; 00108 00109 public: 00110 00111 Exceptionless_filtered_construction() {} 00112 00113 template <class A1> 00114 result_type 00115 operator()(const A1 &a1) const 00116 { 00117 try 00118 { 00119 Protect_FPU_rounding<Protection> P; 00120 FC_result_type fr = Filter_construction(To_Filtered(a1)); 00121 if ( fr ) 00122 return From_Filtered(fr); 00123 } 00124 catch (Uncertain_conversion_exception) {} 00125 00126 Protect_FPU_rounding<!Protection> P(CGAL_FE_TONEAREST); 00127 EC_result_type er = Exact_construction(To_Exact(a1)) ; 00128 return From_Exact(er); 00129 } 00130 00131 template <class A1, class A2> 00132 result_type 00133 operator()(const A1 &a1, const A2 &a2) const 00134 { 00135 try 00136 { 00137 Protect_FPU_rounding<Protection> P; 00138 FC_result_type fr = Filter_construction(To_Filtered(a1),To_Filtered(a2)); 00139 if ( fr ) 00140 return From_Filtered(fr); 00141 } 00142 catch (Uncertain_conversion_exception) {} 00143 00144 Protect_FPU_rounding<!Protection> P(CGAL_FE_TONEAREST); 00145 EC_result_type er = Exact_construction(To_Exact(a1), To_Exact(a2)) ; 00146 return From_Exact(er); 00147 } 00148 00149 template <class A1, class A2, class A3> 00150 result_type 00151 operator()(const A1 &a1, const A2 &a2, const A3 &a3) const 00152 { 00153 try 00154 { 00155 Protect_FPU_rounding<Protection> P; 00156 FC_result_type fr = Filter_construction(To_Filtered(a1),To_Filtered(a2),To_Filtered(a3)); 00157 if ( fr ) 00158 return From_Filtered(fr); 00159 } 00160 catch (Uncertain_conversion_exception) {} 00161 00162 Protect_FPU_rounding<!Protection> P(CGAL_FE_TONEAREST); 00163 EC_result_type er = Exact_construction(To_Exact(a1), To_Exact(a2), To_Exact(a3)) ; 00164 return From_Exact(er); 00165 00166 } 00167 00168 template <class A1, class A2, class A3, class A4> 00169 result_type 00170 operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) const 00171 { 00172 try 00173 { 00174 Protect_FPU_rounding<Protection> P; 00175 FC_result_type fr = Filter_construction(To_Filtered(a1),To_Filtered(a2),To_Filtered(a3),To_Filtered(a4)); 00176 if ( fr ) 00177 return From_Filtered(fr); 00178 } 00179 catch (Uncertain_conversion_exception) {} 00180 00181 Protect_FPU_rounding<!Protection> P(CGAL_FE_TONEAREST); 00182 EC_result_type er = Exact_construction(To_Exact(a1), To_Exact(a2), To_Exact(a3), To_Exact(a4)) ; 00183 return From_Exact(er); 00184 00185 } 00186 00187 template <class A1, class A2, class A3, class A4, class A5> 00188 result_type 00189 operator()(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5) const 00190 { 00191 try 00192 { 00193 Protect_FPU_rounding<Protection> P; 00194 FC_result_type fr = Filter_construction(To_Filtered(a1),To_Filtered(a2),To_Filtered(a3),To_Filtered(a4),To_Filtered(a5)); 00195 if ( fr ) 00196 return From_Filtered(fr); 00197 } 00198 catch (Uncertain_conversion_exception) {} 00199 00200 Protect_FPU_rounding<!Protection> P(CGAL_FE_TONEAREST); 00201 EC_result_type er = Exact_construction(To_Exact(a1), To_Exact(a2), To_Exact(a3), To_Exact(a4), To_Exact(a5)) ; 00202 return From_Exact(er); 00203 00204 } 00205 }; 00206 00207 00208 // 00209 // This number type is provided because unlike Quotient<> is allows you to create it 00210 // with a zero denominator. Of course you can't evaluate it in that case, but is convenient because it allows client code 00211 // to handle the "error" itself, which in this context is useful. 00212 // 00213 template<class NT> 00214 class Rational 00215 { 00216 public: 00217 00218 Rational( NT aN, NT aD ) : mN(aN), mD(aD) {} 00219 00220 NT n() const { return mN ; } 00221 NT d() const { return mD ; } 00222 00223 CGAL::Quotient<NT> to_quotient() const { return CGAL::Quotient<NT>(mN,mD) ; } 00224 00225 NT to_nt() const { return mN / mD ; } 00226 00227 friend std::ostream& operator << ( std::ostream& os, Rational<NT> const& rat ) 00228 { 00229 if ( ! CGAL_NTS is_zero(rat.d()) ) 00230 return os << n2str(rat.n()/rat.d()); 00231 else return os << "INF_RATIONAL" ; 00232 } 00233 00234 private: 00235 00236 NT mN, mD ; 00237 } ; 00238 00239 00240 // 00241 // A straight skeleton event is the simultaneous coallision of 3 ore ffseted oriented straight line segments 00242 // e0*,e1*,e2* [e* denotes an _offseted_ edge]. 00243 // 00244 // A straight skeleton event is the simultaneous coallision of 3 ore 00245 // 00246 // This record stores the segments corresponding to the INPUT edges (e0,e1,e2) whose offsets intersect 00247 // at the event along with their collinearity. 00248 // 00249 // If the event is a an edge-event, then e0*->e1*->e2* must be consecutive right before the event so that 00250 // after the event e0* and e2* become consecutive. Thus, there are _offset_ vertices (e0*,e1*) and (e1*,e2*) 00251 // in the offset polygon which not neccesarily exist in the original polygon. 00252 // 00253 // If the event is a split-event, e0*->e1* must be consecutive right before the event so that after the event 00254 // e0*->right(e2*) and left(e2*)->e1* become consecutive. Thus, there is an offset vertex (e0*,e1*) in the 00255 // offset polygon which not neccesarily exist in the original polygon. 00256 // 00257 // The offset vertices (e0*,e1*) and (e1*,e2*) are called the left and right seeds for the event. 00258 // A seed is a contour node if the vertex is already present in the input polygon, otherwise is a skeleton node. 00259 // If a seed is a skeleton node is produced by a previous event so it is itself defined as a trisegment, thus, 00260 // a trisegment is actually a node in a binary tree. 00261 // Since trisegments are tree nodes they must always be handled via the nested smart pointer type: Self_ptr. 00262 // 00263 template<class K> 00264 class Trisegment_2 : public Ref_counted_base 00265 { 00266 public: 00267 00268 typedef typename K::Segment_2 Segment_2 ; 00269 00270 typedef intrusive_ptr<Trisegment_2> Self_ptr ; 00271 00272 public: 00273 00274 Trisegment_2 ( Segment_2 const& aE0 00275 , Segment_2 const& aE1 00276 , Segment_2 const& aE2 00277 , Trisegment_collinearity aCollinearity 00278 ) 00279 { 00280 mCollinearity = aCollinearity ; 00281 00282 mE[0] = aE0 ; 00283 mE[1] = aE1 ; 00284 mE[2] = aE2 ; 00285 00286 switch ( mCollinearity ) 00287 { 00288 case TRISEGMENT_COLLINEARITY_01: 00289 mCSIdx=0; mNCSIdx=2; break ; 00290 00291 case TRISEGMENT_COLLINEARITY_12: 00292 mCSIdx=1; mNCSIdx=0; break ; 00293 00294 case TRISEGMENT_COLLINEARITY_02: 00295 mCSIdx=0; mNCSIdx=1; break ; 00296 00297 case TRISEGMENT_COLLINEARITY_ALL: 00298 mCSIdx=-1; mNCSIdx=-1; break ; 00299 00300 case TRISEGMENT_COLLINEARITY_NONE: 00301 mCSIdx=-1; mNCSIdx=-1; break ; 00302 } 00303 } 00304 00305 static Trisegment_2 null() { return Self_ptr() ; } 00306 00307 Trisegment_collinearity collinearity() const { return mCollinearity ; } 00308 00309 Segment_2 const& e( unsigned idx ) const { CGAL_precondition(idx<3) ; return mE[idx] ; } 00310 00311 Segment_2 const& e0() const { return e(0) ; } 00312 Segment_2 const& e1() const { return e(1) ; } 00313 Segment_2 const& e2() const { return e(2) ; } 00314 00315 // If 2 out of the 3 edges are collinear they can be reclassified as 1 collinear edge (any of the 2) and 1 non-collinear. 00316 // These methods returns the edges according to that classification. 00317 // PRECONDITION: Exactly 2 out of 3 edges are collinear 00318 Segment_2 const& collinear_edge () const { return e(mCSIdx) ; } 00319 Segment_2 const& non_collinear_edge() const { return e(mNCSIdx) ; } 00320 00321 Self_ptr child_l() const { return mChildL ; } 00322 Self_ptr child_r() const { return mChildR ; } 00323 00324 void set_child_l( Self_ptr const& aChild ) { mChildL = aChild ; } 00325 void set_child_r( Self_ptr const& aChild ) { mChildR = aChild ; } 00326 00327 enum SEED_ID { LEFT, RIGHT, UNKNOWN } ; 00328 00329 // Indicates which of the seeds is collinear for a normal collinearity case. 00330 // PRECONDITION: The collinearity is normal. 00331 SEED_ID degenerate_seed_id() const 00332 { 00333 Trisegment_collinearity c = collinearity(); 00334 00335 return c == TRISEGMENT_COLLINEARITY_01 ? LEFT : c == TRISEGMENT_COLLINEARITY_12 ? RIGHT : UNKNOWN ; 00336 } 00337 00338 friend std::ostream& operator << ( std::ostream& os, Trisegment_2<K> const& aTrisegment ) 00339 { 00340 return os << "[" << s2str(aTrisegment.e0()) 00341 << " " << s2str(aTrisegment.e1()) 00342 << " " << s2str(aTrisegment.e2()) 00343 << " " << trisegment_collinearity_to_string(aTrisegment.collinearity()) 00344 << "]"; 00345 } 00346 00347 friend std::ostream& operator << ( std::ostream& os, Self_ptr const& aPtr ) 00348 { 00349 recursive_print(os,aPtr,0); 00350 return os ; 00351 } 00352 00353 static void recursive_print ( std::ostream& os, Self_ptr const& aTriPtr, int aDepth ) 00354 { 00355 os << "\n" ; 00356 00357 for ( int i = 0 ; i < aDepth ; ++ i ) 00358 os << " " ; 00359 00360 if ( aTriPtr ) 00361 os << *aTriPtr ; 00362 else os << "{null}" ; 00363 00364 if ( aTriPtr->child_l() ) 00365 recursive_print(os,aTriPtr->child_l(),aDepth+1); 00366 00367 if ( aTriPtr->child_r() ) 00368 recursive_print(os,aTriPtr->child_r(),aDepth+1); 00369 } 00370 00371 private : 00372 00373 Segment_2 mE[3]; 00374 Trisegment_collinearity mCollinearity ; 00375 unsigned mCSIdx, mNCSIdx ; 00376 00377 Self_ptr mChildL ; 00378 Self_ptr mChildR ; 00379 } ; 00380 00381 template<class K> 00382 struct Functor_base_2 00383 { 00384 typedef typename K::FT FT ; 00385 typedef typename K::Point_2 Point_2 ; 00386 typedef typename K::Segment_2 Segment_2 ; 00387 00388 typedef CGAL_SS_i::Trisegment_2<K> Trisegment_2 ; 00389 00390 typedef typename Trisegment_2::Self_ptr Trisegment_2_ptr ; 00391 }; 00392 00393 template<class Converter> 00394 struct SS_converter : Converter 00395 { 00396 typedef typename Converter::Source_kernel Source_kernel; 00397 typedef typename Converter::Target_kernel Target_kernel; 00398 00399 typedef typename Source_kernel::FT Source_FT ; 00400 typedef typename Target_kernel::FT Target_FT ; 00401 00402 typedef typename Source_kernel::Point_2 Source_point_2 ; 00403 typedef typename Target_kernel::Point_2 Target_point_2 ; 00404 00405 typedef typename Source_kernel::Segment_2 Source_segment_2 ; 00406 typedef typename Target_kernel::Segment_2 Target_segment_2 ; 00407 00408 typedef Trisegment_2<Source_kernel> Source_trisegment_2 ; 00409 typedef Trisegment_2<Target_kernel> Target_trisegment_2 ; 00410 00411 typedef boost::tuple<Source_FT,Source_point_2> Source_time_and_point_2 ; 00412 typedef boost::tuple<Target_FT,Target_point_2> Target_time_and_point_2 ; 00413 00414 typedef boost::optional<Source_FT> Source_opt_FT ; 00415 typedef boost::optional<Target_FT> Target_opt_FT ; 00416 00417 typedef boost::optional<Source_point_2> Source_opt_point_2 ; 00418 typedef boost::optional<Target_point_2> Target_opt_point_2 ; 00419 00420 typedef boost::optional<Source_time_and_point_2> Source_opt_time_and_point_2 ; 00421 typedef boost::optional<Target_time_and_point_2> Target_opt_time_and_point_2 ; 00422 00423 typedef boost::optional<Source_segment_2> Source_opt_segment_2 ; 00424 typedef boost::optional<Target_segment_2> Target_opt_segment_2 ; 00425 00426 typedef typename Source_trisegment_2::Self_ptr Source_trisegment_2_ptr ; 00427 typedef typename Target_trisegment_2::Self_ptr Target_trisegment_2_ptr ; 00428 00429 00430 Target_FT cvt_n(Source_FT const& n) const { return this->Converter::operator()(n); } 00431 00432 Target_opt_FT cvt_n(Source_opt_FT const& n) const 00433 { 00434 Target_opt_FT r ; 00435 if ( n ) 00436 r = cvt_n(*n); 00437 return r ; 00438 } 00439 00440 Target_point_2 cvt_p(Source_point_2 const& p) const { return this->Converter::operator()(p); } 00441 00442 Target_segment_2 cvt_s( Source_segment_2 const& e) const { return Target_segment_2(cvt_p(e.source()), cvt_p(e.target()) ) ; } 00443 00444 Target_time_and_point_2 cvt_t_p( Source_time_and_point_2 const& v ) const 00445 { 00446 Source_FT t ; 00447 Source_point_2 p ; 00448 boost::tie(t,p) = v ; 00449 return Target_time_and_point_2(cvt_n(t),cvt_p(p)); 00450 } 00451 00452 Target_trisegment_2_ptr cvt_single_trisegment( Source_trisegment_2_ptr const& tri ) const 00453 { 00454 CGAL_precondition( tri ) ; 00455 00456 return Target_trisegment_2_ptr ( new Target_trisegment_2(cvt_s(tri->e0()) 00457 ,cvt_s(tri->e1()) 00458 ,cvt_s(tri->e2()) 00459 ,tri->collinearity() 00460 ) 00461 ) ; 00462 } 00463 00464 Target_trisegment_2_ptr cvt_trisegment( Source_trisegment_2_ptr const& tri ) const 00465 { 00466 Target_trisegment_2_ptr res ; 00467 00468 if ( tri ) 00469 { 00470 res = cvt_single_trisegment(tri) ; 00471 00472 if ( tri->child_l() ) 00473 res->set_child_l( cvt_trisegment(tri->child_l()) ) ; 00474 00475 if ( tri->child_r() ) 00476 res->set_child_r( cvt_trisegment(tri->child_r() ) ) ; 00477 } 00478 00479 return res ; 00480 } 00481 00482 bool operator()( bool v ) const { return v ; } 00483 00484 Trisegment_collinearity operator()(Trisegment_collinearity c) const { return c ; } 00485 00486 Oriented_side operator()(Oriented_side s) const { return s ; } 00487 00488 Target_FT operator()(Source_FT const& n) const { return cvt_n(n) ; } 00489 00490 Target_opt_FT operator()(Source_opt_FT const& n) const { return cvt_n(n) ; } 00491 00492 Target_point_2 operator()( Source_point_2 const& p) const { return cvt_p(p) ; } 00493 00494 Target_segment_2 operator()( Source_segment_2 const& s) const { return cvt_s(s); } 00495 00496 Target_trisegment_2_ptr operator()( Source_trisegment_2_ptr const& tri ) const 00497 { 00498 return cvt_trisegment(tri); 00499 } 00500 00501 Target_time_and_point_2 operator() ( Source_time_and_point_2 const& v ) const 00502 { 00503 return cvt_t_p(v); 00504 } 00505 00506 Target_opt_point_2 operator()( Source_opt_point_2 const& p) const 00507 { 00508 if ( p ) 00509 return Target_opt_point_2(cvt_p(*p)); 00510 else return Target_opt_point_2(); 00511 } 00512 00513 Target_opt_segment_2 operator()( Source_opt_segment_2 const& s) const 00514 { 00515 if ( s ) 00516 return Target_opt_segment_2(cvt_s(*s)); 00517 else return Target_opt_segment_2(); 00518 } 00519 00520 Target_opt_time_and_point_2 operator()( Source_opt_time_and_point_2 const& v) const 00521 { 00522 if ( v ) 00523 return Target_opt_time_and_point_2(cvt_t_p(*v)); 00524 else return Target_opt_time_and_point_2(); 00525 } 00526 00527 }; 00528 00529 } // namespace CGAL_SS_i 00530 00531 00532 // 00533 // This macro defines a global functor adapter which allows users to use it in the followig ways: 00534 // 00535 // Given a 'Functor' provided by a given 'Traits' (or Kernel): 00536 // 00537 // typedef typename CGAL::Functor<Traits>::type Functor ; 00538 // result r = CGAL::Functor<Traits>(traits)(a,b,c); 00539 // 00540 #define CGAL_STRAIGHT_SKELETON_CREATE_FUNCTOR_ADAPTER(functor) \ 00541 template<class K> \ 00542 typename K :: functor functor ( K const& aK ) \ 00543 { \ 00544 return aK.get((typename K :: functor const*)0); \ 00545 } 00546 00547 00548 CGAL_END_NAMESPACE 00549 00550 00551 #endif // CGAL_STRAIGHT_SKELETON_BUILDER_TRAITS_2_AUX_H // 00552 00553 // EOF //