BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Straight_skeleton_builder_2.h
Go to the documentation of this file.
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 //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines