diff --git a/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h b/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h index f87e17f1670..54388f8b9fb 100644 --- a/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h +++ b/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_2_impl.h @@ -96,12 +96,66 @@ Straight_skeleton_builder_2::FindEdgeEvent( Vertex_handle aLNode, Verte { EventPtr rResult ; + CGAL_STSKEL_BUILDER_TRACE(4, "FindEdgeEvent(), Left/Right Nodes: N" << aLNode->id() << " N" << aRNode->id() ) ; + Triedge lTriedge = GetVertexTriedge(aLNode) & GetVertexTriedge(aRNode) ; - if ( lTriedge.is_valid() && lTriedge != aPrevEventTriedge ) + if ( lTriedge.is_valid() && lTriedge != aPrevEventTriedge ) { Trisegment_2_ptr lTrisegment = CreateTrisegment(lTriedge,aLNode,aRNode); + // The 02 collinearity configuration is problematic: 01 or 12 collinearity has a seed position + // giving the point through which the bissector passes. However, for 02, it is not a given. + // + // If the seed exists, the information is passed to the traits as the "third" child of the trisegment. + // Otherwise, ignore this as it should re-appear when the seed of 02 is created. + if ( lTrisegment->collinearity() == TRISEGMENT_COLLINEARITY_02 ) + { + // Check in the SLAV if the seed corresponding to 02 exists + + std::cout << "EdgeEvent 02" << std::endl ; + + // Note that this is only for edge events; (pseudo-)split events are not concerned. + Vertex_handle lPrevNode = GetPrevInLAV(aLNode) ; + CGAL_assertion( GetEdgeStartingAt(lPrevNode) == lTriedge.e0() ) ; + + if ( GetEdgeEndingAt(lPrevNode) == lTriedge.e2() ) + { + // Note that this can be a contour node and in that case GetTrisegment is null and we get + // the middle point, but in that case e2 and e0 are consecutive in the input + // and the middle point is the common extremity and things are fine. + lTrisegment->set_child_t( GetTrisegment(lPrevNode) ) ; + } + else + { + Orientation lOrientationS = CGAL::orientation( lTrisegment->e0().source(), lTrisegment->e0().target(), lTrisegment->e1().source() ) ; + Orientation lOrientationT = CGAL::orientation( lTrisegment->e0().source(), lTrisegment->e0().target(), lTrisegment->e1().target() ) ; + if ( lOrientationS != LEFT_TURN && lOrientationT != LEFT_TURN ) + { + // Reasonning is: if the middle halfedge (e1) is "below" e0 and e2, then there is some + // kind of concavity in between e0 and e2. This concavity will resolve itself and either: + // - e0 and e2 will never meet, but in that case we would not be here + // - e0 and e2 will meet. In that case, we can ignore all the details of the concavity + // and simply consider that in the end, all that matters is the e0, e2, next(e0), + // and prev(e2). In that case, we get two bisectors issued from e0 and e2, and one + // bissector issued from some seed S and splitting next(e0) and prev(e2). This can also + // be seen as two exterior bissectors and one interior bissector of a triangle + // target(e0) -- S - source(e2). It is a known result that these three bissectors + // meet in a single point. Thus, when we get here e0-e1-e2, we know that + // these will meet in a single, existing point, either the left or the right child (the oldest). + + if ( CompareEvents(aLNode, aRNode) == SMALLER ) + lTrisegment->set_child_t( GetTrisegment(aRNode) ) ; + else + lTrisegment->set_child_t( GetTrisegment(aLNode) ) ; + } + else + { + return rResult; + } + } + } + if ( ExistEvent(lTrisegment) ) { Comparison_result lLNodeD = CompareEvents(lTrisegment,aLNode) ; diff --git a/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_traits_2_aux.h b/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_traits_2_aux.h index 653f71af568..4b11a217440 100644 --- a/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_traits_2_aux.h +++ b/Straight_skeleton_2/include/CGAL/Straight_skeleton_2/Straight_skeleton_builder_traits_2_aux.h @@ -403,6 +403,9 @@ struct SS_converter : Converter if ( tri->child_r() ) res->set_child_r( cvt_trisegment(tri->child_r() ) ) ; + + if ( tri->child_t() ) + res->set_child_t( cvt_trisegment(tri->child_t() ) ) ; } return res ; diff --git a/Straight_skeleton_2/include/CGAL/Straight_skeleton_builder_2.h b/Straight_skeleton_2/include/CGAL/Straight_skeleton_builder_2.h index c286724a39c..3873a6c54c4 100644 --- a/Straight_skeleton_2/include/CGAL/Straight_skeleton_builder_2.h +++ b/Straight_skeleton_2/include/CGAL/Straight_skeleton_builder_2.h @@ -899,6 +899,35 @@ private : : LARGER ; } + Comparison_result CompareEvents( Vertex_handle aLNode, Vertex_handle aRNode ) const + { + if ( aLNode->is_skeleton() ) + { + if ( aRNode->is_skeleton() ) + { + if ( aLNode->has_infinite_time() && aRNode->has_infinite_time() ) + return EQUAL ; + else if ( aLNode->has_infinite_time() ) + return LARGER ; + else if ( aRNode->has_infinite_time() ) + return SMALLER ; + else + return CompareEvents ( GetTrisegment(aLNode), GetTrisegment(aRNode) ) ; + } + else // left skeleton, right not skeleton + { + return LARGER ; + } + } + else // left not skeleton + { + if ( aRNode->is_skeleton() ) + return SMALLER ; + else // both not skeleton + return EQUAL ; + } + } + bool AreEventsSimultaneous( Trisegment_2_ptr const& x, Trisegment_2_ptr const& y ) const { return Are_ss_events_simultaneous_2(mTraits)(x,y) ; diff --git a/Straight_skeleton_2/include/CGAL/Trisegment_2.h b/Straight_skeleton_2/include/CGAL/Trisegment_2.h index 64748658cb0..3c4470e715d 100644 --- a/Straight_skeleton_2/include/CGAL/Trisegment_2.h +++ b/Straight_skeleton_2/include/CGAL/Trisegment_2.h @@ -137,11 +137,13 @@ public: Self_ptr child_l() const { return mChildL ; } Self_ptr child_r() const { return mChildR ; } + Self_ptr child_t() const { return mChildT ; } void set_child_l( Self_ptr const& aChild ) { mChildL = aChild ; } void set_child_r( Self_ptr const& aChild ) { mChildR = aChild ; } + void set_child_t( Self_ptr const& aChild ) { mChildT = aChild ; } - enum SEED_ID { LEFT, RIGHT, UNKNOWN } ; + enum SEED_ID { LEFT, RIGHT, THIRD } ; // Indicates which of the seeds is collinear for a normal collinearity case. // PRECONDITION: The collinearity is normal. @@ -149,7 +151,7 @@ public: { Trisegment_collinearity c = collinearity(); - return c == TRISEGMENT_COLLINEARITY_01 ? LEFT : c == TRISEGMENT_COLLINEARITY_12 ? RIGHT : UNKNOWN ; + return c == TRISEGMENT_COLLINEARITY_01 ? LEFT : c == TRISEGMENT_COLLINEARITY_12 ? RIGHT : THIRD ; } friend std::ostream& operator << ( std::ostream& os, Self const& aTrisegment ) @@ -198,6 +200,11 @@ private : Self_ptr mChildL ; Self_ptr mChildR ; + + // this is the potential child of e2-e0, if it exists. It is used only in the configuration + // of e0 and e2 collinear as the common child gives where the bissector starts (as it is not + // necessarily the middle of the gap between e2 and e0). + Self_ptr mChildT ; } ; } // end namespace CGAL diff --git a/Straight_skeleton_2/include/CGAL/constructions/Straight_skeleton_cons_ftC2.h b/Straight_skeleton_2/include/CGAL/constructions/Straight_skeleton_cons_ftC2.h index e901dbcecd0..4f872f6a779 100644 --- a/Straight_skeleton_2/include/CGAL/constructions/Straight_skeleton_cons_ftC2.h +++ b/Straight_skeleton_2/include/CGAL/constructions/Straight_skeleton_cons_ftC2.h @@ -414,9 +414,10 @@ compute_seed_pointC2 ( boost::intrusive_ptr< Trisegment_2e1(),tri->e2()) ; break ; - case Trisegment_2::UNKNOWN : + case Trisegment_2::THIRD : - p = compute_oriented_midpoint(tri->e0(),tri->e2()); + p = tri->child_t() ? construct_offset_lines_isecC2(tri->child_t(), aCoeff_cache) // this can recurse + : compute_oriented_midpoint(tri->e0(),tri->e2()) ; break ; }