|
BWAPI
|
00001 // Copyright (c) 2006-2008 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 00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Straight_skeleton_2/include/CGAL/Straight_skeleton_builder_2.h $ 00015 // $Id: Straight_skeleton_builder_2.h 43050 2008-04-28 17:03:23Z fcacciola $ 00016 // 00017 // Author(s) : Fernando Cacciola <fernando_cacciola@ciudad.com.ar> 00018 // 00019 #ifndef CGAL_STRAIGHT_SKELETON_BUILDER_2_H 00020 #define CGAL_STRAIGHT_SKELETON_BUILDER_2_H 1 00021 00022 #include <list> 00023 #include <queue> 00024 #include <exception> 00025 #include <string> 00026 #include <map> 00027 00028 #include <boost/tuple/tuple.hpp> 00029 #include <boost/intrusive_ptr.hpp> 00030 #include <boost/shared_ptr.hpp> 00031 #include <boost/scoped_ptr.hpp> 00032 00033 #include <CGAL/algorithm.h> 00034 #include <CGAL/Straight_skeleton_2/Straight_skeleton_aux.h> 00035 #include <CGAL/Straight_skeleton_2/Straight_skeleton_builder_events_2.h> 00036 #include <CGAL/Straight_skeleton_2.h> 00037 #include <CGAL/Straight_skeleton_builder_traits_2.h> 00038 #include <CGAL/HalfedgeDS_const_decorator.h> 00039 #include <CGAL/enum.h> 00040 00041 CGAL_BEGIN_NAMESPACE 00042 00043 template<class SSkel_> 00044 struct Dummy_straight_skeleton_builder_2_visitor 00045 { 00046 typedef SSkel_ SSkel ; 00047 00048 typedef typename SSkel::Halfedge_const_handle Halfedge_const_handle ; 00049 typedef typename SSkel::Vertex_const_handle Vertex_const_handle ; 00050 00051 void on_contour_edge_entered ( Halfedge_const_handle const& ) const {} 00052 00053 void on_initialization_started( std::size_t /* size_of_vertices */ ) const {} 00054 00055 void on_initial_events_collected( Vertex_const_handle const& , bool /* is_reflex */, bool /*is_degenerate*/ ) const {} 00056 00057 void on_edge_event_created( Vertex_const_handle const& /* lnode */ 00058 , Vertex_const_handle const& /* rnode */ 00059 ) const {} 00060 00061 void on_split_event_created( Vertex_const_handle const& ) const {} 00062 00063 void on_pseudo_split_event_created( Vertex_const_handle const& /* lnode */ 00064 , Vertex_const_handle const& /* rnode */ 00065 ) const {} 00066 00067 void on_initialization_finished() const {} 00068 00069 void on_propagation_started() const {} 00070 00071 void on_anihiliation_event_processed ( Vertex_const_handle const& /* node0 */ 00072 , Vertex_const_handle const& /* node1 */ 00073 ) const {} 00074 00075 00076 void on_edge_event_processed( Vertex_const_handle const& /* lseed */ 00077 , Vertex_const_handle const& /* rseed */ 00078 , Vertex_const_handle const& /* node */ 00079 ) const {} 00080 00081 void on_split_event_processed( Vertex_const_handle const& /* seed */ 00082 , Vertex_const_handle const& /* node0 */ 00083 , Vertex_const_handle const& /* node1 */ 00084 ) const {} 00085 00086 void on_pseudo_split_event_processed( Vertex_const_handle const& /* lseed */ 00087 , Vertex_const_handle const& /* rseed */ 00088 , Vertex_const_handle const& /* node0 */ 00089 , Vertex_const_handle const& /* node1 */ 00090 ) const {} 00091 00092 void on_vertex_processed( Vertex_const_handle const& ) const {} 00093 00094 void on_propagation_finished() const {} 00095 00096 void on_cleanup_started() const {} 00097 00098 void on_cleanup_finished() const {} 00099 00100 void on_algorithm_finished ( bool /* finished_ok */ ) const {} 00101 00102 void on_error( char const* ) const {} 00103 } ; 00104 00105 template<class Traits_, class SSkel_, class Visitor_ = Dummy_straight_skeleton_builder_2_visitor<SSkel_> > 00106 class Straight_skeleton_builder_2 00107 { 00108 public: 00109 00110 typedef Traits_ Traits ; 00111 typedef SSkel_ SSkel ; 00112 typedef Visitor_ Visitor ; 00113 00114 typedef boost::shared_ptr<SSkel> SSkelPtr ; 00115 00116 private : 00117 00118 typedef typename Traits::Kernel K ; 00119 00120 typedef typename Traits::FT FT ; 00121 typedef typename Traits::Point_2 Point_2 ; 00122 typedef typename Traits::Vector_2 Vector_2 ; 00123 typedef typename Traits::Direction_2 Direction_2 ; 00124 typedef typename Traits::Segment_2 Segment_2 ; 00125 typedef typename Traits::Trisegment_2 Trisegment_2 ; 00126 typedef typename Traits::Trisegment_2_ptr Trisegment_2_ptr ; 00127 00128 typedef typename SSkel::Vertex Vertex ; 00129 typedef typename SSkel::Halfedge Halfedge ; 00130 typedef typename SSkel::Face Face ; 00131 00132 typedef typename SSkel::Vertex_const_handle Vertex_const_handle ; 00133 typedef typename SSkel::Halfedge_const_handle Halfedge_const_handle ; 00134 typedef typename SSkel::Face_const_handle Face_const_handle ; 00135 00136 typedef typename SSkel::Vertex_const_iterator Vertex_const_iterator ; 00137 typedef typename SSkel::Halfedge_const_iterator Halfedge_const_iterator ; 00138 typedef typename SSkel::Face_const_iterator Face_const_iterator ; 00139 00140 typedef typename SSkel::Vertex_handle Vertex_handle ; 00141 typedef typename SSkel::Halfedge_handle Halfedge_handle ; 00142 typedef typename SSkel::Face_handle Face_handle ; 00143 00144 typedef typename SSkel::Vertex_iterator Vertex_iterator ; 00145 typedef typename SSkel::Halfedge_iterator Halfedge_iterator ; 00146 typedef typename SSkel::Face_iterator Face_iterator ; 00147 00148 typedef typename Vertex::Halfedge_around_vertex_circulator Halfedge_around_vertex_circulator ; 00149 00150 typedef typename SSkel::size_type size_type ; 00151 00152 typedef CGAL_SS_i::Triedge<Halfedge_handle> Triedge ; 00153 00154 typedef CGAL_SS_i::Event_2 <SSkel,Traits> Event ; 00155 typedef CGAL_SS_i::Edge_event_2 <SSkel,Traits> EdgeEvent ; 00156 typedef CGAL_SS_i::Split_event_2 <SSkel,Traits> SplitEvent ; 00157 typedef CGAL_SS_i::Pseudo_split_event_2<SSkel,Traits> PseudoSplitEvent ; 00158 00159 typedef boost::intrusive_ptr<Event> EventPtr ; 00160 00161 typedef std::pair<Vertex_handle,Vertex_handle> Vertex_handle_pair ; 00162 00163 typedef std::vector<EventPtr> EventPtr_Vector ; 00164 typedef std::vector<Halfedge_handle> Halfedge_handle_vector ; 00165 typedef std::vector<Vertex_handle> Vertex_handle_vector ; 00166 typedef std::vector<Vertex_handle_pair> Vertex_handle_pair_vector ; 00167 00168 typedef typename Halfedge_handle_vector ::iterator Halfedge_handle_vector_iterator ; 00169 typedef typename Vertex_handle_vector ::iterator Vertex_handle_vector_iterator ; 00170 typedef typename Vertex_handle_pair_vector::iterator Vertex_handle_pair_vector_iterator ; 00171 00172 typedef typename EventPtr_Vector::const_iterator event_const_iterator ; 00173 00174 typedef Straight_skeleton_builder_2<Traits,SSkel,Visitor> Self ; 00175 00176 typedef typename Halfedge::Base_base HBase_base ; 00177 typedef typename Halfedge::Base HBase ; 00178 typedef typename Vertex::Base VBase ; 00179 typedef typename Face::Base FBase ; 00180 00181 enum Site { AT_SOURCE = -1 , INSIDE = 0, AT_TARGET = +1 } ; 00182 00183 struct Multinode : public Ref_counted_base 00184 { 00185 Multinode ( Halfedge_handle b, Halfedge_handle e ) 00186 : 00187 begin(b) 00188 ,end (e) 00189 ,v (b->vertex()) 00190 ,size (0) 00191 {} 00192 00193 Halfedge_handle begin ; 00194 Halfedge_handle end ; 00195 Vertex_handle v ; 00196 std::size_t size ; 00197 Halfedge_handle_vector bisectors_to_relink ; 00198 Halfedge_handle_vector bisectors_to_remove ; 00199 Vertex_handle_vector nodes_to_remove ; 00200 } ; 00201 00202 typedef boost::intrusive_ptr<Multinode> MultinodePtr ; 00203 00204 struct MultinodeComparer 00205 { 00206 bool operator() ( MultinodePtr const& x, MultinodePtr const& y ) { return x->size > y->size ; } 00207 } ; 00208 00209 typedef std::vector<MultinodePtr> MultinodeVector ; 00210 00211 struct Halfedge_ID_compare : std::binary_function<bool,Halfedge_handle,Halfedge_handle> 00212 { 00213 bool operator() ( Halfedge_handle const& aA, Halfedge_handle const& aB ) const 00214 { 00215 return aA->id() < aB->id() ; 00216 } 00217 } ; 00218 00219 public: 00220 00221 Straight_skeleton_builder_2 ( boost::optional<FT> aMaxTime = boost::none, Traits const& = Traits(), Visitor const& aVisitor = Visitor() ) ; 00222 00223 SSkelPtr construct_skeleton( bool aNull_if_failed = true ) ; 00224 00225 private : 00226 00227 00228 class Event_compare : public std::binary_function<bool,EventPtr,EventPtr> 00229 { 00230 public: 00231 00232 Event_compare ( Self const* aBuilder ) : mBuilder(aBuilder) {} 00233 00234 bool operator() ( EventPtr const& aA, EventPtr const& aB ) const 00235 { 00236 return mBuilder->CompareEvents(aA,aB) == LARGER ; 00237 } 00238 00239 private: 00240 00241 Self const* mBuilder ; 00242 } ; 00243 00244 typedef std::priority_queue<EventPtr,std::vector<EventPtr>,Event_compare> PQ ; 00245 00246 00247 struct Vertex_data : public Ref_counted_base 00248 { 00249 Vertex_data ( Vertex_handle aVertex, Event_compare const& aComparer ) 00250 : 00251 mVertex(aVertex) 00252 , mIsReflex(false) 00253 , mIsDegenerate(false) 00254 , mIsProcessed(false) 00255 , mIsExcluded(false) 00256 , mPrevInLAV(-1) 00257 , mNextInLAV(-1) 00258 , mNextSplitEventInMainPQ(false) 00259 , mSplitEvents(aComparer) 00260 {} 00261 00262 Vertex_handle mVertex ; 00263 bool mIsReflex ; 00264 bool mIsDegenerate ; 00265 bool mIsProcessed ; 00266 bool mIsExcluded ; 00267 int mPrevInLAV ; 00268 int mNextInLAV ; 00269 bool mNextSplitEventInMainPQ; 00270 PQ mSplitEvents ; 00271 Triedge mTriedge ; // Here, E0,E1 corresponds to the vertex (unlike *event* triedges) 00272 Trisegment_2_ptr mTrisegment ; // Skeleton nodes cache the full trisegment tree that defines the originating event 00273 } ; 00274 00275 typedef boost::intrusive_ptr<Vertex_data> Vertex_data_ptr ; 00276 00277 private : 00278 00279 Halfedge_handle validate( Halfedge_handle aH ) const ; 00280 Vertex_handle validate( Vertex_handle aH ) const ; 00281 00282 void InitVertexData( Vertex_handle aV ) 00283 { 00284 mVertexData.push_back( Vertex_data_ptr( new Vertex_data(aV,mEventCompare) ) ) ; 00285 } 00286 00287 Vertex_data const& GetVertexData( Vertex_const_handle aV ) const 00288 { 00289 CGAL_precondition( handle_assigned(aV) ) ; 00290 return *mVertexData[aV->id()]; 00291 } 00292 00293 Vertex_data& GetVertexData( Vertex_const_handle aV ) 00294 { 00295 CGAL_precondition( handle_assigned(aV) ) ; 00296 return *mVertexData[aV->id()]; 00297 } 00298 00299 Vertex_handle GetVertex ( int aIdx ) 00300 { 00301 CGAL_precondition(aIdx>=0); 00302 return mVertexData[aIdx]->mVertex ; 00303 } 00304 00305 // Null if aV is a contour or infinite node 00306 Trisegment_2_ptr const& GetTrisegment ( Vertex_handle aV ) const 00307 { 00308 return GetVertexData(aV).mTrisegment ; 00309 } 00310 00311 void SetTrisegment ( Vertex_handle aV, Trisegment_2_ptr const& aTrisegment ) 00312 { 00313 GetVertexData(aV).mTrisegment = aTrisegment ; 00314 } 00315 00316 // Null if aV is a contour node 00317 Triedge const& GetVertexTriedge ( Vertex_handle aV ) const 00318 { 00319 return GetVertexData(aV).mTriedge ; 00320 } 00321 00322 void SetVertexTriedge ( Vertex_handle aV, Triedge const& aTriedge ) 00323 { 00324 GetVertexData(aV).mTriedge = aTriedge ; 00325 } 00326 00327 Segment_2 CreateSegment ( Halfedge_const_handle aH ) const 00328 { 00329 Point_2 s = aH->opposite()->vertex()->point() ; 00330 Point_2 t = aH->vertex()->point() ; 00331 return K().construct_segment_2_object()(s,t); 00332 } 00333 00334 Vector_2 CreateVector ( Halfedge_const_handle aH ) const 00335 { 00336 Point_2 s = aH->opposite()->vertex()->point() ; 00337 Point_2 t = aH->vertex()->point() ; 00338 return K().construct_vector_2_object()(s,t); 00339 } 00340 00341 Direction_2 CreateDirection ( Halfedge_const_handle aH ) const 00342 { 00343 return K().construct_direction_2_object()( CreateVector(aH) ); 00344 } 00345 00346 Trisegment_2_ptr CreateTrisegment ( Triedge const& aTriedge ) const 00347 { 00348 CGAL_precondition(aTriedge.is_valid() && aTriedge.is_skeleton()); 00349 00350 Trisegment_2_ptr r = Construct_ss_trisegment_2(mTraits)(CreateSegment(aTriedge.e0()) 00351 ,CreateSegment(aTriedge.e1()) 00352 ,CreateSegment(aTriedge.e2()) 00353 ); 00354 00355 CGAL_STSKEL_BUILDER_TRACE(5,"Trisegment for " << aTriedge << ":" << r ) ; 00356 00357 CGAL_postcondition_msg(r, "Unable to determine edges collinearity"); 00358 00359 return r ; 00360 } 00361 00362 Trisegment_2_ptr CreateTrisegment ( Triedge const& aTriedge, Vertex_handle aLSeed ) const 00363 { 00364 Trisegment_2_ptr r = CreateTrisegment( aTriedge ) ; 00365 r->set_child_l( GetTrisegment(aLSeed) ) ; 00366 return r ; 00367 } 00368 00369 Trisegment_2_ptr CreateTrisegment ( Triedge const& aTriedge, Vertex_handle aLSeed, Vertex_handle aRSeed ) const 00370 { 00371 Trisegment_2_ptr r = CreateTrisegment( aTriedge ) ; 00372 r->set_child_l( GetTrisegment(aLSeed) ) ; 00373 r->set_child_r( GetTrisegment(aRSeed) ) ; 00374 return r ; 00375 } 00376 00377 Vertex_handle GetPrevInLAV ( Vertex_handle aV ) 00378 { 00379 return GetVertex ( GetVertexData(aV).mPrevInLAV ) ; 00380 } 00381 00382 Vertex_handle GetNextInLAV ( Vertex_handle aV ) 00383 { 00384 return GetVertex ( GetVertexData(aV).mNextInLAV ) ; 00385 } 00386 00387 void SetPrevInLAV ( Vertex_handle aV, Vertex_handle aPrev ) 00388 { 00389 GetVertexData(aV).mPrevInLAV = aPrev->id(); 00390 } 00391 00392 void SetNextInLAV ( Vertex_handle aV, Vertex_handle aPrev ) 00393 { 00394 GetVertexData(aV).mNextInLAV = aPrev->id(); 00395 } 00396 00397 Halfedge_handle GetEdgeEndingAt ( Vertex_handle aV ) 00398 { 00399 return GetVertexTriedge(aV).e0(); 00400 } 00401 00402 Halfedge_handle GetEdgeStartingAt ( Vertex_handle aV ) 00403 { 00404 return GetEdgeEndingAt( GetNextInLAV(aV) ) ; 00405 } 00406 00407 void Exclude ( Vertex_handle aV ) 00408 { 00409 GetVertexData(aV).mIsExcluded = true ; 00410 } 00411 bool IsExcluded ( Vertex_const_handle aV ) const 00412 { 00413 return GetVertexData(aV).mIsExcluded ; 00414 } 00415 00416 void SetIsReflex ( Vertex_handle aV ) 00417 { 00418 GetVertexData(aV).mIsReflex = true ; 00419 } 00420 00421 bool IsReflex ( Vertex_handle aV ) 00422 { 00423 return GetVertexData(aV).mIsReflex ; 00424 } 00425 00426 void SetIsDegenerate ( Vertex_handle aV ) 00427 { 00428 GetVertexData(aV).mIsDegenerate = true ; 00429 } 00430 00431 bool IsDegenerate ( Vertex_handle aV ) 00432 { 00433 return GetVertexData(aV).mIsDegenerate ; 00434 } 00435 00436 void SetIsProcessed ( Vertex_handle aV ) 00437 { 00438 GetVertexData(aV).mIsProcessed = true ; 00439 00440 mVisitor.on_vertex_processed(aV); 00441 } 00442 00443 bool IsConvex ( Vertex_handle aV ) 00444 { 00445 Vertex_data const& lData = GetVertexData(aV) ; 00446 return !lData.mIsReflex && !lData.mIsDegenerate ; 00447 } 00448 00449 bool IsProcessed ( Vertex_handle aV ) 00450 { 00451 return GetVertexData(aV).mIsProcessed ; 00452 } 00453 00454 void AddSplitEvent ( Vertex_handle aV, EventPtr aEvent ) 00455 { 00456 CGAL_STSKEL_BUILDER_TRACE(2, "V" << aV->id() << " PQ: " << *aEvent); 00457 GetVertexData(aV).mSplitEvents.push(aEvent); 00458 } 00459 00460 EventPtr PopNextSplitEvent ( Vertex_handle aV ) 00461 { 00462 EventPtr rEvent ; 00463 Vertex_data& lData = GetVertexData(aV) ; 00464 if ( !lData.mNextSplitEventInMainPQ ) 00465 { 00466 PQ& lPQ = lData.mSplitEvents ; 00467 if ( !lPQ.empty() ) 00468 { 00469 rEvent = lPQ.top(); 00470 lPQ.pop(); 00471 lData.mNextSplitEventInMainPQ = true ; 00472 } 00473 } 00474 return rEvent ; 00475 } 00476 00477 void AllowNextSplitEvent ( Vertex_handle aV ) 00478 { 00479 GetVertexData(aV).mNextSplitEventInMainPQ = false ; 00480 } 00481 00482 void InsertEventInPQ( EventPtr aEvent ) ; 00483 00484 EventPtr PopEventFromPQ() ; 00485 00486 bool ExistEvent ( Trisegment_2_ptr const& aS ) 00487 { 00488 return Do_ss_event_exist_2(mTraits)(aS,mMaxTime); 00489 } 00490 00491 bool IsOppositeEdgeFacingTheSplitSeed( Vertex_handle aSeed, Halfedge_handle aOpposite ) const 00492 { 00493 if ( aSeed->is_skeleton() ) 00494 return Is_edge_facing_ss_node_2(mTraits)( GetTrisegment(aSeed), CreateSegment(aOpposite) ) ; 00495 else return Is_edge_facing_ss_node_2(mTraits)( aSeed->point() , CreateSegment(aOpposite) ) ; 00496 } 00497 00498 Oriented_side EventPointOrientedSide( Event const& aEvent 00499 , Halfedge_const_handle aE0 00500 , Halfedge_const_handle aE1 00501 , Vertex_handle aV01 00502 , bool aE0isPrimary 00503 ) const 00504 { 00505 return Oriented_side_of_event_point_wrt_bisector_2(mTraits)( aEvent.trisegment() 00506 , CreateSegment(aE0) 00507 , CreateSegment(aE1) 00508 , GetTrisegment(aV01) // Can be null 00509 , aE0isPrimary 00510 ) ; 00511 } 00512 00513 Comparison_result CompareEvents ( Trisegment_2_ptr const& aA, Trisegment_2_ptr const& aB ) const 00514 { 00515 return Compare_ss_event_times_2(mTraits)(aA,aB) ; 00516 } 00517 00518 Comparison_result CompareEvents ( EventPtr const& aA, EventPtr const& aB ) const 00519 { 00520 return aA->triedge() != aB->triedge() ? CompareEvents( aA->trisegment(), aB->trisegment() ) : EQUAL ; 00521 } 00522 00523 bool AreEventsSimultaneous( Trisegment_2_ptr const& x, Trisegment_2_ptr const& y ) const 00524 { 00525 return Are_ss_events_simultaneous_2(mTraits)(x,y) ; 00526 } 00527 00528 bool AreEventsSimultaneous( EventPtr const& x, EventPtr const& y ) const 00529 { 00530 return AreEventsSimultaneous(x->trisegment(),y->trisegment()); 00531 } 00532 00533 bool AreContourNodesCoincident( Vertex_handle aX, Vertex_handle aY ) const 00534 { 00535 CGAL_precondition( aX->is_contour() ); 00536 CGAL_precondition( aY->is_contour() ); 00537 00538 return CGAL::compare_xy(aX->point(),aY->point()) == EQUAL ; 00539 } 00540 00541 bool AreSkeletonNodesCoincident( Vertex_handle aX, Vertex_handle aY ) const 00542 { 00543 CGAL_precondition( aX->is_skeleton() ); 00544 CGAL_precondition( aY->is_skeleton() ); 00545 CGAL_precondition( !aX->has_infinite_time() ); 00546 CGAL_precondition( !aY->has_infinite_time() ); 00547 00548 return AreEventsSimultaneous( GetTrisegment(aX), GetTrisegment(aY) ) ; 00549 } 00550 00551 Comparison_result CompareEvents( Trisegment_2_ptr const& aTrisegment, Vertex_handle aSeedNode ) const 00552 { 00553 return aSeedNode->is_skeleton() ? aSeedNode->has_infinite_time() ? SMALLER 00554 : CompareEvents( aTrisegment, GetTrisegment(aSeedNode) ) 00555 : LARGER ; 00556 } 00557 00558 void SetBisectorSlope ( Halfedge_handle aBisector, Sign aSlope ) 00559 { 00560 aBisector->HBase_base::set_slope(aSlope); 00561 } 00562 00563 void SetBisectorSlope ( Vertex_handle aA, Vertex_handle aB ) 00564 { 00565 Halfedge_handle lOBisector = aA->primary_bisector(); 00566 Halfedge_handle lIBisector = lOBisector->opposite(); 00567 00568 CGAL_precondition( !aA->is_contour() || !aB->is_contour() ) ; 00569 00570 if ( aA->is_contour() ) 00571 { 00572 SetBisectorSlope(lOBisector,POSITIVE); 00573 SetBisectorSlope(lIBisector,NEGATIVE); 00574 } 00575 else if ( aB->is_contour()) 00576 { 00577 SetBisectorSlope(lOBisector,NEGATIVE); 00578 SetBisectorSlope(lIBisector,POSITIVE); 00579 } 00580 else 00581 { 00582 if ( aA->has_infinite_time() ) 00583 { 00584 CGAL_precondition( !aB->has_infinite_time()); 00585 00586 SetBisectorSlope(lOBisector,NEGATIVE); 00587 SetBisectorSlope(lIBisector,POSITIVE); 00588 } 00589 else if ( aB->has_infinite_time()) 00590 { 00591 CGAL_precondition( !aA->has_infinite_time()); 00592 00593 SetBisectorSlope(lOBisector,NEGATIVE); 00594 SetBisectorSlope(lIBisector,POSITIVE); 00595 } 00596 else 00597 { 00598 CGAL_precondition( !aA->has_infinite_time()); 00599 CGAL_precondition( !aB->has_infinite_time()); 00600 00601 Sign lSlope = CompareEvents(GetTrisegment(aB),GetTrisegment(aA)); 00602 SetBisectorSlope(lOBisector,lSlope); 00603 SetBisectorSlope(lIBisector,opposite(lSlope)); 00604 } 00605 } 00606 } 00607 00608 boost::tuple<FT,Point_2> ConstructEventTimeAndPoint( Trisegment_2_ptr const& aS ) const 00609 { 00610 boost::optional< boost::tuple<FT,Point_2> > r = Construct_ss_event_time_and_point_2(mTraits)(aS); 00611 CGAL_postcondition_msg(!!r, "Unable to compute skeleton node coordinates"); 00612 return *r ; 00613 } 00614 00615 void SetEventTimeAndPoint( Event& aE ) 00616 { 00617 FT lTime ; 00618 Point_2 lP ; 00619 boost::tie(lTime,lP) = ConstructEventTimeAndPoint(aE.trisegment()); 00620 00621 aE.SetTimeAndPoint(lTime,lP); 00622 } 00623 00624 00625 void EraseBisector( Halfedge_handle aB ) 00626 { 00627 CGAL_STSKEL_BUILDER_TRACE(1,"Dangling B" << aB->id() << " and B" << aB->opposite()->id() << " removed."); 00628 00629 mSSkel->SSkel::Base::edges_erase(aB); 00630 } 00631 00632 #ifdef CGAL_STSKEL_TRACE_ON 00633 std::string wavefront2str( Vertex_handle v ) 00634 { 00635 std::ostringstream ss ; 00636 00637 ss << "N" << GetPrevInLAV(v)->id() << "->N" << v->id() << "->N" << GetNextInLAV(v)->id() 00638 << " E" << GetVertexTriedge(v).e0()->id() << "->E" << GetVertexTriedge(v).e1()->id() ; 00639 00640 return ss.str() ; 00641 00642 } 00643 #endif 00644 00645 void Link( Halfedge_handle aH, Face_handle aF ) 00646 { 00647 aH->HBase_base::set_face(aF); 00648 } 00649 00650 void Link( Halfedge_handle aH, Vertex_handle aV ) 00651 { 00652 aH->HBase_base::set_vertex(aV); 00653 } 00654 00655 void Link( Vertex_handle aV, Halfedge_handle aH ) 00656 { 00657 aV->VBase::set_halfedge(aH); 00658 } 00659 00660 void CrossLinkFwd( Halfedge_handle aPrev, Halfedge_handle aNext ) 00661 { 00662 aPrev->HBase_base::set_next(aNext); 00663 aNext->HBase_base::set_prev(aPrev); 00664 } 00665 00666 void CrossLink( Halfedge_handle aH, Vertex_handle aV ) 00667 { 00668 Link(aH,aV); 00669 Link(aV,aH); 00670 } 00671 00672 Triedge GetCommonTriedge( Vertex_handle aA, Vertex_handle aB ) ; 00673 00674 bool AreBisectorsCoincident ( Halfedge_const_handle aA, Halfedge_const_handle aB ) const ; 00675 00676 EventPtr IsPseudoSplitEvent( EventPtr const& aEvent, Vertex_handle_pair aOpp, Site const& aSite ) ; 00677 00678 void CollectSplitEvent( Vertex_handle aNode, Triedge const& aTriedge ) ; 00679 00680 void CollectSplitEvents( Vertex_handle aNode ) ; 00681 00682 EventPtr FindEdgeEvent( Vertex_handle aLNode, Vertex_handle aRNode ) ; 00683 00684 void HandleSimultaneousEdgeEvent( Vertex_handle aA, Vertex_handle aB ) ; 00685 00686 void CollectNewEvents( Vertex_handle aNode ) ; 00687 void UpdatePQ( Vertex_handle aV ) ; 00688 void CreateInitialEvents(); 00689 void CreateContourBisectors(); 00690 void InitPhase(); 00691 00692 void SetupNewNode( Vertex_handle aNode ); 00693 00694 Vertex_handle_pair LookupOnSLAV ( Halfedge_handle aOBorder, EventPtr const& aEvent, Site& rSite ) ; 00695 00696 Vertex_handle ConstructEdgeEventNode ( EdgeEvent& aEvent ) ; 00697 Vertex_handle_pair ConstructSplitEventNodes ( SplitEvent& aEvent, Vertex_handle aOppR ) ; 00698 Vertex_handle_pair ConstructPseudoSplitEventNodes ( PseudoSplitEvent& aEvent ) ; 00699 00700 bool IsValidEdgeEvent ( EdgeEvent const& aEvent ) ; 00701 bool IsValidSplitEvent ( SplitEvent const& aEvent ) ; 00702 bool IsValidPseudoSplitEvent ( PseudoSplitEvent const& aEvent ) ; 00703 00704 void HandleEdgeEvent ( EventPtr aEvent ) ; 00705 void HandleSplitEvent ( EventPtr aEvent, Vertex_handle_pair aOpp ) ; 00706 void HandlePseudoSplitEvent ( EventPtr aEvent ) ; 00707 void HandleSplitOrPseudoSplitEvent ( EventPtr aEvent ) ; 00708 00709 void InsertNextSplitEventInPQ( Vertex_handle v ) ; 00710 void InsertNextSplitEventsInPQ() ; 00711 00712 bool IsProcessed( EventPtr aEvent ) ; 00713 00714 void Propagate(); 00715 00716 void EraseNode ( Vertex_handle aNode ) ; 00717 00718 void MergeSplitNodes ( Vertex_handle_pair aSplitNodes ) ; 00719 00720 void RelinkBisectorsAroundMultinode( Vertex_handle const& v0, Halfedge_handle_vector& aLinks ) ; 00721 00722 void PreprocessMultinode( Multinode& aMN ) ; 00723 00724 void ProcessMultinode( Multinode& aMN, Halfedge_handle_vector& rHalfedgesToRemove , Vertex_handle_vector& rNodesToRemove ) ; 00725 00726 MultinodePtr CreateMultinode( Halfedge_handle begin, Halfedge_handle end ) ; 00727 00728 void MergeCoincidentNodes() ; 00729 00730 bool FinishUp(); 00731 00732 bool Run(); 00733 00734 private: 00735 00736 //Input 00737 Traits mTraits ; 00738 00739 Visitor const& mVisitor ; 00740 00741 std::vector<Vertex_data_ptr> mVertexData ; 00742 00743 Vertex_handle_vector mReflexVertices ; 00744 Halfedge_handle_vector mDanglingBisectors ; 00745 Halfedge_handle_vector mContourHalfedges ; 00746 00747 std::list<Vertex_handle> mGLAV ; 00748 00749 Vertex_handle_pair_vector mSplitNodes ; 00750 00751 Event_compare mEventCompare ; 00752 00753 int mVertexID ; 00754 int mEdgeID ; 00755 int mFaceID ; 00756 int mEventID ; 00757 int mStepID ; 00758 00759 boost::optional<FT> mMaxTime ; 00760 00761 PQ mPQ ; 00762 00763 //Output 00764 SSkelPtr mSSkel ; 00765 00766 private : 00767 00768 template<class InputPointIterator, class Converter> 00769 void enter_valid_contour ( InputPointIterator aBegin, InputPointIterator aEnd, Converter const& cvt ) 00770 { 00771 CGAL_STSKEL_BUILDER_TRACE(0,"Inserting Connected Component of the Boundary...."); 00772 00773 Halfedge_handle lFirstCCWBorder ; 00774 Halfedge_handle lPrevCCWBorder ; 00775 Halfedge_handle lNextCWBorder ; 00776 Vertex_handle lFirstVertex ; 00777 Vertex_handle lPrevVertex ; 00778 00779 InputPointIterator lCurr = aBegin ; 00780 InputPointIterator lPrev = aBegin ; 00781 00782 int c = 0 ; 00783 00784 while ( lCurr != aEnd ) 00785 { 00786 Halfedge_handle lCCWBorder = mSSkel->SSkel::Base::edges_push_back ( Halfedge(mEdgeID),Halfedge(mEdgeID+1) ); 00787 Halfedge_handle lCWBorder = lCCWBorder->opposite(); 00788 mEdgeID += 2 ; 00789 00790 mContourHalfedges.push_back(lCCWBorder); 00791 00792 Vertex_handle lVertex = mSSkel->SSkel::Base::vertices_push_back( Vertex(mVertexID++,cvt(*lCurr)) ) ; 00793 CGAL_STSKEL_BUILDER_TRACE(1,"Vertex: V" << lVertex->id() << " at " << lVertex->point() ); 00794 InitVertexData(lVertex); 00795 00796 Face_handle lFace = mSSkel->SSkel::Base::faces_push_back( Face(mFaceID++) ) ; 00797 00798 ++ c ; 00799 00800 lCCWBorder->HBase_base::set_face(lFace); 00801 lFace ->FBase ::set_halfedge(lCCWBorder); 00802 00803 lVertex ->VBase ::set_halfedge(lCCWBorder); 00804 lCCWBorder->HBase_base::set_vertex(lVertex); 00805 00806 if ( lCurr == aBegin ) 00807 { 00808 lFirstVertex = lVertex ; 00809 lFirstCCWBorder = lCCWBorder ; 00810 } 00811 else 00812 { 00813 SetPrevInLAV(lVertex ,lPrevVertex); 00814 SetNextInLAV(lPrevVertex,lVertex ); 00815 00816 SetVertexTriedge(lPrevVertex, Triedge(lPrevCCWBorder,lCCWBorder) ) ; 00817 00818 lCWBorder->HBase_base::set_vertex(lPrevVertex); 00819 00820 lCCWBorder ->HBase_base::set_prev(lPrevCCWBorder); 00821 lPrevCCWBorder->HBase_base::set_next(lCCWBorder); 00822 00823 lNextCWBorder->HBase_base::set_prev(lCWBorder); 00824 lCWBorder ->HBase_base::set_next(lNextCWBorder); 00825 00826 CGAL_STSKEL_BUILDER_TRACE(1,"CCW Border: E" << lCCWBorder->id() << ' ' << lPrevVertex->point() << " -> " << lVertex ->point()); 00827 CGAL_STSKEL_BUILDER_TRACE(1,"CW Border: E" << lCWBorder ->id() << ' ' << lVertex ->point() << " -> " << lPrevVertex->point() ); 00828 00829 mVisitor.on_contour_edge_entered(lCCWBorder); 00830 00831 } 00832 00833 lPrev = lCurr ; 00834 00835 ++ lCurr ; 00836 00837 lPrevVertex = lVertex ; 00838 lPrevCCWBorder = lCCWBorder ; 00839 lNextCWBorder = lCWBorder ; 00840 } 00841 00842 SetPrevInLAV(lFirstVertex,lPrevVertex ); 00843 SetNextInLAV(lPrevVertex ,lFirstVertex); 00844 00845 SetVertexTriedge( lPrevVertex, Triedge(lPrevCCWBorder,lFirstCCWBorder) ) ; 00846 00847 lFirstCCWBorder->opposite()->HBase_base::set_vertex(lPrevVertex); 00848 00849 lFirstCCWBorder->HBase_base::set_prev(lPrevCCWBorder); 00850 lPrevCCWBorder ->HBase_base::set_next(lFirstCCWBorder); 00851 00852 lPrevCCWBorder ->opposite()->HBase_base::set_prev(lFirstCCWBorder->opposite()); 00853 lFirstCCWBorder->opposite()->HBase_base::set_next(lPrevCCWBorder ->opposite()); 00854 00855 CGAL_precondition_msg(c >=3, "The contour must have at least 3 _distinct_ vertices" ) ; 00856 00857 CGAL_STSKEL_BUILDER_TRACE(1 00858 , "CCW Border: E" << lFirstCCWBorder->id() 00859 << ' ' << lPrevVertex ->point() << " -> " << lFirstVertex->point() << '\n' 00860 << "CW Border: E" << lFirstCCWBorder->opposite()->id() 00861 << ' ' << lFirstVertex->point() << " -> " << lPrevVertex ->point() 00862 ); 00863 00864 mVisitor.on_contour_edge_entered(lFirstCCWBorder); 00865 } 00866 00867 public: 00868 00869 // This compares INPUT vertices so there is no need to filter it. 00870 struct AreVerticesEqual 00871 { 00872 template<class P> 00873 bool operator() ( P const&x, P const& y ) const 00874 { 00875 return CGAL::compare_xy(x,y) == EQUAL ; 00876 } 00877 } ; 00878 00879 template<class InputPointIterator, class Converter> 00880 Straight_skeleton_builder_2& enter_contour ( InputPointIterator aBegin 00881 , InputPointIterator aEnd 00882 , Converter const& cvt 00883 , bool aCheckValidity = true 00884 ) 00885 { 00886 if ( aCheckValidity ) 00887 { 00888 typedef typename std::iterator_traits<InputPointIterator>::value_type Input_point; 00889 00890 typedef std::vector<Input_point> Input_point_vector ; 00891 typedef typename Input_point_vector::iterator Input_point_iterator ; 00892 00893 // Remove coincident consecutive vertices 00894 Input_point_vector lList; 00895 std::unique_copy(aBegin,aEnd,std::back_inserter(lList),AreVerticesEqual()); 00896 00897 while ( lList.size() > 0 && CGAL::compare_xy(lList.front(),lList.back()) == EQUAL ) 00898 lList.pop_back(); 00899 00900 if ( lList.size() >= 3 ) 00901 { 00902 enter_valid_contour(lList.begin(),lList.end(),cvt); 00903 } 00904 else 00905 { 00906 CGAL_STSKEL_BUILDER_TRACE(0,"Degenerate contour (less than 3 non-degenerate vertices)."); 00907 } 00908 } 00909 else 00910 { 00911 enter_valid_contour(aBegin,aEnd,cvt); 00912 } 00913 00914 return *this ; 00915 } 00916 00917 template<class InputPointIterator> 00918 Straight_skeleton_builder_2& enter_contour ( InputPointIterator aBegin 00919 , InputPointIterator aEnd 00920 , bool aCheckValidity = true 00921 ) 00922 { 00923 return enter_contour(aBegin, aEnd, Cartesian_converter<K,K>(), aCheckValidity); 00924 } 00925 00926 } ; 00927 00928 CGAL_END_NAMESPACE 00929 00930 #include <CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h> 00931 00932 00933 #endif // CGAL_STRAIGHT_SKELETON_BUILDER_2_H // 00934 // EOF //
1.7.6.1