mirror of https://github.com/CGAL/cgal
Degenerate vertices now internally handled correctly rather than filtered out
This commit is contained in:
parent
ff49cdcd3c
commit
ea7962413c
|
|
@ -502,7 +502,14 @@ void Straight_skeleton_builder_2<Gt,SS>::CreateContourBisectors()
|
||||||
Vertex_handle lPrev = GetPrevInLAV(v) ;
|
Vertex_handle lPrev = GetPrevInLAV(v) ;
|
||||||
Vertex_handle lNext = GetNextInLAV(v) ;
|
Vertex_handle lNext = GetNextInLAV(v) ;
|
||||||
|
|
||||||
if ( lOrientation == RIGHT_TURN )
|
Orientation lOrientation = CGAL::orientation(lPrev->point(),v->point(),lNext->point());
|
||||||
|
if ( lOrientation == COLLINEAR )
|
||||||
|
{
|
||||||
|
SetIsDegenerate(v);
|
||||||
|
CGAL_STSKEL_BUILDER_TRACE(1, "COLLINEAR vertex: N" << v->id() );
|
||||||
|
CGAL_STSKEL_STATS_CODE(++sDegenerateVertexCount);
|
||||||
|
}
|
||||||
|
else if ( lOrientation == RIGHT_TURN )
|
||||||
{
|
{
|
||||||
mReflexVertices.push_back(v);
|
mReflexVertices.push_back(v);
|
||||||
SetIsReflex(v);
|
SetIsReflex(v);
|
||||||
|
|
@ -606,7 +613,7 @@ Straight_skeleton_builder_2<Gt,SS>::LookupOnSLAV ( Halfedge_handle aBorder, Even
|
||||||
{
|
{
|
||||||
Vertex_handle rResult ;
|
Vertex_handle rResult ;
|
||||||
|
|
||||||
CGAL_STSKEL_BUILDER_TRACE ( 3, "ALT Looking up for E" << aBorder->id() << " on SLAV. P=" << aEvent->point() ) ;
|
CGAL_STSKEL_BUILDER_TRACE ( 3, "Looking up for E" << aBorder->id() << " on SLAV. P=" << aEvent->point() ) ;
|
||||||
|
|
||||||
CGAL_STSKEL_DEBUG_CODE( bool lFound = false ; )
|
CGAL_STSKEL_DEBUG_CODE( bool lFound = false ; )
|
||||||
|
|
||||||
|
|
@ -622,19 +629,23 @@ Straight_skeleton_builder_2<Gt,SS>::LookupOnSLAV ( Halfedge_handle aBorder, Even
|
||||||
CGAL_STSKEL_DEBUG_CODE( lFound = true ; )
|
CGAL_STSKEL_DEBUG_CODE( lFound = true ; )
|
||||||
|
|
||||||
Vertex_handle lPrev = GetPrevInLAV(v);
|
Vertex_handle lPrev = GetPrevInLAV(v);
|
||||||
|
Vertex_handle lNext = GetNextInLAV(v);
|
||||||
|
|
||||||
Halfedge_handle lPrevBorder = GetDefiningBorderA(lPrev);
|
Halfedge_handle lPrevBorder = GetDefiningBorderA(lPrev);
|
||||||
Halfedge_handle lNextBorder = GetDefiningBorderB(v);
|
Halfedge_handle lNextBorder = GetDefiningBorderA(lNext);
|
||||||
|
|
||||||
CGAL_assertion(handle_assigned(lPrevBorder));
|
CGAL_assertion(handle_assigned(lPrevBorder));
|
||||||
CGAL_assertion(handle_assigned(lNextBorder));
|
CGAL_assertion(handle_assigned(lNextBorder));
|
||||||
|
|
||||||
if ( IsEventInsideOffsetZone( aEvent->border_a(), aEvent->border_b(), aBorder, lPrevBorder, lNextBorder ) )
|
CGAL_STSKEL_BUILDER_TRACE ( 3
|
||||||
{
|
, "Subedge found in SLAV: N" << lPrev->id() << "->N" << v->id()
|
||||||
rResult = v ;
|
|
||||||
CGAL_STSKEL_BUILDER_TRACE ( 2
|
|
||||||
, "ALT E" << aBorder->id() << " found in SLAV: N" << lPrev->id() << "->N" << v->id()
|
|
||||||
<< " (E" << lPrevBorder->id() << "->E" << aBorder->id() << "->E" << lNextBorder->id() << ")"
|
<< " (E" << lPrevBorder->id() << "->E" << aBorder->id() << "->E" << lNextBorder->id() << ")"
|
||||||
) ;
|
) ;
|
||||||
|
|
||||||
|
if ( IsEventInsideOffsetZone( aEvent->border_a(), aEvent->border_b(), lPrevBorder, aBorder, lNextBorder ) )
|
||||||
|
{
|
||||||
|
rResult = v ;
|
||||||
|
CGAL_STSKEL_BUILDER_TRACE ( 3, "That's the correct subedge. Found") ;
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -645,11 +656,11 @@ Straight_skeleton_builder_2<Gt,SS>::LookupOnSLAV ( Halfedge_handle aBorder, Even
|
||||||
{
|
{
|
||||||
if ( !lFound )
|
if ( !lFound )
|
||||||
{
|
{
|
||||||
CGAL_STSKEL_BUILDER_TRACE(1,"ALT Split event is no longer valid. Opposite edge vanished.");
|
CGAL_STSKEL_BUILDER_TRACE(1,"Split event is no longer valid. Opposite edge vanished.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CGAL_STSKEL_BUILDER_TRACE(1,"ALT Split event is no longer valid. Not inside the opposite edge offset zone.");
|
CGAL_STSKEL_BUILDER_TRACE(1,"Split event is no longer valid. Not inside the opposite edge offset zone.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1002,13 +1013,11 @@ void Straight_skeleton_builder_2<Gt,SS>::HandleSplitEvent( EventPtr aEvent, Vert
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Gt, class SS>
|
template<class Gt, class SS>
|
||||||
bool Straight_skeleton_builder_2<Gt,SS>::SetupPseudoSplitEventNode( Vertex_handle aNode
|
void Straight_skeleton_builder_2<Gt,SS>::SetupPseudoSplitEventNode( Vertex_handle aNode
|
||||||
, Halfedge_handle aDefiningBorderA
|
, Halfedge_handle aDefiningBorderA
|
||||||
, Halfedge_handle aDefiningBorderB
|
, Halfedge_handle aDefiningBorderB
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
bool rR = false ;
|
|
||||||
|
|
||||||
Point_2 p = aDefiningBorderA->opposite()->vertex()->point() ;
|
Point_2 p = aDefiningBorderA->opposite()->vertex()->point() ;
|
||||||
Point_2 q = aDefiningBorderA->opposite()->prev()->vertex()->point() ;
|
Point_2 q = aDefiningBorderA->opposite()->prev()->vertex()->point() ;
|
||||||
Point_2 r = aDefiningBorderB->opposite()->prev()->vertex()->point() ;
|
Point_2 r = aDefiningBorderB->opposite()->prev()->vertex()->point() ;
|
||||||
|
|
@ -1020,16 +1029,12 @@ bool Straight_skeleton_builder_2<Gt,SS>::SetupPseudoSplitEventNode( Vertex_handl
|
||||||
CGAL_STSKEL_BUILDER_TRACE(1, "COLLINEAR *NEW* vertex: N" << aNode->id() );
|
CGAL_STSKEL_BUILDER_TRACE(1, "COLLINEAR *NEW* vertex: N" << aNode->id() );
|
||||||
CGAL_STSKEL_STATS_CODE(++sDegenerateVertexCount);
|
CGAL_STSKEL_STATS_CODE(++sDegenerateVertexCount);
|
||||||
}
|
}
|
||||||
|
else if ( lOrientation == RIGHT_TURN )
|
||||||
if ( lOrientation == RIGHT_TURN )
|
|
||||||
{
|
{
|
||||||
rR = true ;
|
|
||||||
mReflexVertices.push_back(aNode);
|
mReflexVertices.push_back(aNode);
|
||||||
SetIsReflex(aNode);
|
SetIsReflex(aNode);
|
||||||
CGAL_STSKEL_BUILDER_TRACE(1, "Reflex *NEW* vertex: N" << aNode->id() );
|
CGAL_STSKEL_BUILDER_TRACE(1, "Reflex *NEW* vertex: N" << aNode->id() );
|
||||||
}
|
}
|
||||||
|
|
||||||
return rR ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Gt, class SS>
|
template<class Gt, class SS>
|
||||||
|
|
@ -1122,8 +1127,7 @@ void Straight_skeleton_builder_2<Gt,SS>::HandlePseudoSplitEvent( EventPtr aEvent
|
||||||
<< " primary bisector: B" << lNewNode_R->primary_bisector()->id()
|
<< " primary bisector: B" << lNewNode_R->primary_bisector()->id()
|
||||||
) ;
|
) ;
|
||||||
|
|
||||||
bool lNodeLIsNonConvex = SetupPseudoSplitEventNode(lNewNode_L,lNewNodeLDefiningBorderA,lNewNodeLDefiningBorderB) ;
|
SetupPseudoSplitEventNode(lNewNode_L,lNewNodeLDefiningBorderA,lNewNodeLDefiningBorderB) ;
|
||||||
if ( !lNodeLIsNonConvex )
|
|
||||||
SetupPseudoSplitEventNode(lNewNode_R,lNewNodeRDefiningBorderA,lNewNodeRDefiningBorderB) ;
|
SetupPseudoSplitEventNode(lNewNode_R,lNewNodeRDefiningBorderA,lNewNodeRDefiningBorderB) ;
|
||||||
|
|
||||||
UpdatePQ(lNewNode_L);
|
UpdatePQ(lNewNode_L);
|
||||||
|
|
@ -1136,7 +1140,7 @@ void Straight_skeleton_builder_2<Gt,SS>::HandleSplitOrPseudoSplitEvent( EventPtr
|
||||||
Vertex_handle lOppR = LookupOnSLAV(aEvent->border_c(),aEvent);
|
Vertex_handle lOppR = LookupOnSLAV(aEvent->border_c(),aEvent);
|
||||||
if ( handle_assigned(lOppR) )
|
if ( handle_assigned(lOppR) )
|
||||||
{
|
{
|
||||||
EventPtr lPseudoSplitEvent ; //= IsPseudoSplitEvent(aEvent,lOppR);
|
EventPtr lPseudoSplitEvent = IsPseudoSplitEvent(aEvent,lOppR);
|
||||||
if ( lPseudoSplitEvent )
|
if ( lPseudoSplitEvent )
|
||||||
HandlePseudoSplitEvent(lPseudoSplitEvent);
|
HandlePseudoSplitEvent(lPseudoSplitEvent);
|
||||||
else HandleSplitEvent (aEvent,lOppR);
|
else HandleSplitEvent (aEvent,lOppR);
|
||||||
|
|
@ -1570,7 +1574,6 @@ std::cerr << "EXCEPTION THROWN (" << e.what() << ") during straight skeleton con
|
||||||
mSSkel = SSkelPtr() ;
|
mSSkel = SSkelPtr() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( !!mSSkel && !CGAL::HalfedgeDS_const_decorator<SSkel>(*mSSkel).is_valid(false,3) )
|
if ( !!mSSkel && !CGAL::HalfedgeDS_const_decorator<SSkel>(*mSSkel).is_valid(false,3) )
|
||||||
{
|
{
|
||||||
CGAL_STSKEL_BUILDER_TRACE(0,"Result inconsistent.");
|
CGAL_STSKEL_BUILDER_TRACE(0,"Result inconsistent.");
|
||||||
|
|
@ -1582,6 +1585,7 @@ std::cerr << "Result incosistent." << std::endl ;
|
||||||
mSSkel = SSkelPtr() ;
|
mSSkel = SSkelPtr() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CGAL_STRAIGHT_SKELETON_STATS
|
#ifdef CGAL_STRAIGHT_SKELETON_STATS
|
||||||
|
|
||||||
std::cerr << "sVertexCount =" << sVertexCount << std::endl
|
std::cerr << "sVertexCount =" << sVertexCount << std::endl
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,12 @@ private :
|
||||||
if ( !handle_assigned(aB->opposite()) )
|
if ( !handle_assigned(aB->opposite()) )
|
||||||
throw straight_skeleton_exception("opposite() missing!");
|
throw straight_skeleton_exception("opposite() missing!");
|
||||||
|
|
||||||
|
if ( !handle_assigned(aA->opposite()->vertex()) )
|
||||||
|
throw straight_skeleton_exception("opposite()->vertex() missing!");
|
||||||
|
|
||||||
|
if ( !handle_assigned(aB->opposite()->vertex()) )
|
||||||
|
throw straight_skeleton_exception("opposite()->vertex() missing!");
|
||||||
|
|
||||||
Point_2 o = aA->vertex()->point();
|
Point_2 o = aA->vertex()->point();
|
||||||
Point_2 a = aA->opposite()->vertex()->point();
|
Point_2 a = aA->opposite()->vertex()->point();
|
||||||
Point_2 b = aB->opposite()->vertex()->point();
|
Point_2 b = aB->opposite()->vertex()->point();
|
||||||
|
|
@ -495,8 +501,8 @@ private :
|
||||||
|
|
||||||
bool IsEventInsideOffsetZone( Halfedge_const_handle aReflexL
|
bool IsEventInsideOffsetZone( Halfedge_const_handle aReflexL
|
||||||
, Halfedge_const_handle aReflexR
|
, Halfedge_const_handle aReflexR
|
||||||
, Halfedge_const_handle aOpposite
|
|
||||||
, Halfedge_const_handle aOppositePrev
|
, Halfedge_const_handle aOppositePrev
|
||||||
|
, Halfedge_const_handle aOpposite
|
||||||
, Halfedge_const_handle aOppositeNext
|
, Halfedge_const_handle aOppositeNext
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
|
|
@ -654,7 +660,7 @@ private :
|
||||||
void CreateContourBisectors();
|
void CreateContourBisectors();
|
||||||
void InitPhase();
|
void InitPhase();
|
||||||
|
|
||||||
bool SetupPseudoSplitEventNode( Vertex_handle aNode
|
void SetupPseudoSplitEventNode( Vertex_handle aNode
|
||||||
, Halfedge_handle aDefiningBorderA
|
, Halfedge_handle aDefiningBorderA
|
||||||
, Halfedge_handle aDefiningBorderB
|
, Halfedge_handle aDefiningBorderB
|
||||||
);
|
);
|
||||||
|
|
@ -924,7 +930,7 @@ public:
|
||||||
for ( Point_iterator curr = begin ; curr != end ; ++ curr )
|
for ( Point_iterator curr = begin ; curr != end ; ++ curr )
|
||||||
{
|
{
|
||||||
Point_iterator next = ( curr == last ? begin : CGAL::successor(curr) ) ;
|
Point_iterator next = ( curr == last ? begin : CGAL::successor(curr) ) ;
|
||||||
if ( !CGAL::collinear(*prev,*curr,*next) )
|
//if ( !CGAL::collinear(*prev,*curr,*next) )
|
||||||
lList1.push_back(*curr);
|
lList1.push_back(*curr);
|
||||||
prev = curr ;
|
prev = curr ;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -218,8 +218,8 @@ struct Construct_ss_event_time_and_point_2 : Functor_base_2<K>
|
||||||
|
|
||||||
Sorted_triedge_2 sorted = collinear_sort(triedge);
|
Sorted_triedge_2 sorted = collinear_sort(triedge);
|
||||||
|
|
||||||
if ( !sorted.is_indeterminate() )
|
//if ( !sorted.is_indeterminate() )
|
||||||
{
|
//{
|
||||||
CGAL_assertion(sorted.collinear_count() < 3) ;
|
CGAL_assertion(sorted.collinear_count() < 3) ;
|
||||||
|
|
||||||
optional< Rational<FT> > qt = compute_offset_lines_isec_timeC2(sorted);
|
optional< Rational<FT> > qt = compute_offset_lines_isec_timeC2(sorted);
|
||||||
|
|
@ -228,7 +228,7 @@ struct Construct_ss_event_time_and_point_2 : Functor_base_2<K>
|
||||||
|
|
||||||
if ( qt )
|
if ( qt )
|
||||||
t = cgal_make_optional(qt->n() / qt->d()) ;
|
t = cgal_make_optional(qt->n() / qt->d()) ;
|
||||||
}
|
//}
|
||||||
|
|
||||||
if ( !t )
|
if ( !t )
|
||||||
t = cgal_make_optional( FT(0) );
|
t = cgal_make_optional( FT(0) );
|
||||||
|
|
@ -382,7 +382,6 @@ public:
|
||||||
>
|
>
|
||||||
Are_ss_edges_collinear_2 ;
|
Are_ss_edges_collinear_2 ;
|
||||||
|
|
||||||
/*
|
|
||||||
typedef Filtered_construction< typename Unfiltering::Construct_ss_event_time_and_point_2
|
typedef Filtered_construction< typename Unfiltering::Construct_ss_event_time_and_point_2
|
||||||
, typename Exact ::Construct_ss_event_time_and_point_2
|
, typename Exact ::Construct_ss_event_time_and_point_2
|
||||||
, typename Filtering ::Construct_ss_event_time_and_point_2
|
, typename Filtering ::Construct_ss_event_time_and_point_2
|
||||||
|
|
@ -392,9 +391,8 @@ public:
|
||||||
, F2C
|
, F2C
|
||||||
>
|
>
|
||||||
Construct_ss_event_time_and_point_2 ; // This uses internally a predicate so must be filtered
|
Construct_ss_event_time_and_point_2 ; // This uses internally a predicate so must be filtered
|
||||||
*/
|
|
||||||
|
|
||||||
typedef typename Unfiltering::Construct_ss_event_time_and_point_2 Construct_ss_event_time_and_point_2 ;
|
//typedef typename Unfiltering::Construct_ss_event_time_and_point_2 Construct_ss_event_time_and_point_2 ;
|
||||||
|
|
||||||
typedef typename Unfiltering::Construct_ss_triedge_2 Construct_ss_triedge_2 ;
|
typedef typename Unfiltering::Construct_ss_triedge_2 Construct_ss_triedge_2 ;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,16 @@
|
||||||
|
|
||||||
CGAL_BEGIN_NAMESPACE
|
CGAL_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
inline bool certainly( bool c ) { return c ; }
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool certainly( Uncertain<bool> const& c )
|
||||||
|
{
|
||||||
|
if ( CGAL_NTS is_indeterminate(c) )
|
||||||
|
return false ;
|
||||||
|
else return static_cast<bool>(c) ;
|
||||||
|
}
|
||||||
|
|
||||||
inline Uncertain<bool> logical_or ( Uncertain<bool> a, Uncertain<bool> b ) { return a | b ; }
|
inline Uncertain<bool> logical_or ( Uncertain<bool> a, Uncertain<bool> b ) { return a | b ; }
|
||||||
inline Uncertain<bool> logical_and( Uncertain<bool> a, Uncertain<bool> b ) { return a & b ; }
|
inline Uncertain<bool> logical_and( Uncertain<bool> a, Uncertain<bool> b ) { return a & b ; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ optional< Line_2<K> > compute_normalized_line_ceoffC2( Segment_2<K> const& e )
|
||||||
|
|
||||||
CGAL_STSKEL_TRAITS_TRACE("Line coefficients for line:\npx=" << e.source().x() << "\npy=" << e.source().y() << "\nqx="
|
CGAL_STSKEL_TRAITS_TRACE("Line coefficients for line:\npx=" << e.source().x() << "\npy=" << e.source().y() << "\nqx="
|
||||||
<< e.target().x() << "\nqy=" << e.target().y()
|
<< e.target().x() << "\nqy=" << e.target().y()
|
||||||
<< "\na="<< a << "\nb=" << b << "\nc=" << c << "\nl:" << l
|
<< "\na="<< a << "\nb=" << b << "\nc=" << c << "\nl2:" << l2
|
||||||
) ;
|
) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ CGAL_BEGIN_NAMESPACE
|
||||||
namespace CGAL_SS_i
|
namespace CGAL_SS_i
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Just like the uncertified collinear() returns true IFF r lies in the line p->q
|
||||||
|
// NOTE: r might be in the ray from p or q containing q or p, that is, there is no ordering implied, just that
|
||||||
|
// the three points are along the same line, in any order.
|
||||||
template<class K>
|
template<class K>
|
||||||
Uncertain<bool> certified_collinearC2( Point_2<K> const& p
|
Uncertain<bool> certified_collinearC2( Point_2<K> const& p
|
||||||
, Point_2<K> const& q
|
, Point_2<K> const& q
|
||||||
|
|
@ -39,23 +42,62 @@ Uncertain<bool> certified_collinearC2( Point_2<K> const& p
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Just like the uncertified collinear_are_ordered_along_lineC2() returns true IFF, given p,q,r along the same line,
|
||||||
|
// q in the closed segment [p,r].
|
||||||
template<class K>
|
template<class K>
|
||||||
Uncertain<bool> are_edges_collinearC2( Segment_2<K> const& e0, Segment_2<K> const& e1 )
|
Uncertain<bool> certified_collinear_are_ordered_along_lineC2( Point_2<K> const& p
|
||||||
|
, Point_2<K> const& q
|
||||||
|
, Point_2<K> const& r
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return CGAL_NTS logical_and( certified_collinearC2(e0.source(),e0.target(),e1.source())
|
if ( CGAL_NTS certainly(p.x() < q.x()) ) return !(r.x() < q.x());
|
||||||
, certified_collinearC2(e0.source(),e0.target(),e1.target())
|
if ( CGAL_NTS certainly(q.x() < p.x()) ) return !(q.x() < r.x());
|
||||||
|
if ( CGAL_NTS certainly(p.y() < q.y()) ) return !(r.y() < q.y());
|
||||||
|
if ( CGAL_NTS certainly(q.y() < p.y()) ) return !(q.y() < r.y());
|
||||||
|
|
||||||
|
if ( CGAL_NTS certainly(p.x() == q.x()) && CGAL_NTS certainly(p.y() == q.y()) ) return make_uncertain(true);
|
||||||
|
|
||||||
|
return Uncertain<bool>::indeterminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true IFF segments e0,e1 share the same supporting line, do not overlap except at the vetices, and have the same orientation.
|
||||||
|
// NOTE: If e1 goes back over e0 (a degenerate antenna or alley) this returns false.
|
||||||
|
template<class K>
|
||||||
|
Uncertain<bool> are_edges_orderly_collinearC2( Segment_2<K> const& e0, Segment_2<K> const& e1 )
|
||||||
|
{
|
||||||
|
return certified_collinearC2(e0.source(),e0.target(),e1.source())
|
||||||
|
&
|
||||||
|
( certified_collinear_are_ordered_along_lineC2(e0.source(),e0.target(),e1.source())
|
||||||
|
| certified_collinear_are_ordered_along_lineC2(e1.source(),e0.source(),e0.target())
|
||||||
|
)
|
||||||
|
& certified_collinearC2(e0.source(),e0.target(),e1.target())
|
||||||
|
&
|
||||||
|
( certified_collinear_are_ordered_along_lineC2(e0.source(),e0.target(),e1.target())
|
||||||
|
| certified_collinear_are_ordered_along_lineC2(e1.target(),e0.source(),e0.target())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true IFF segments e0,e1 do not share the same supporting line but are parallel, or share the
|
||||||
|
// supporting line but are not orderly collinear (that is, one doesn't follow the other)
|
||||||
template<class K>
|
template<class K>
|
||||||
Uncertain<bool> are_edges_parallelC2( Segment_2<K> const& e0, Segment_2<K> const& e1 )
|
Uncertain<bool> are_edges_parallel_but_not_orderly_collinearC2( Segment_2<K> const& e0, Segment_2<K> const& e1 )
|
||||||
{
|
{
|
||||||
Uncertain<Sign> s = certified_sign_of_determinant2x2(e0.target().x() - e0.source().x()
|
Uncertain<Sign> s = certified_sign_of_determinant2x2(e0.target().x() - e0.source().x()
|
||||||
,e0.target().y() - e0.source().y()
|
,e0.target().y() - e0.source().y()
|
||||||
,e1.target().x() - e1.source().x()
|
,e1.target().x() - e1.source().x()
|
||||||
,e1.target().y() - e1.source().y()
|
,e1.target().y() - e1.source().y()
|
||||||
) ;
|
) ;
|
||||||
return s == Uncertain<Sign>(ZERO);
|
|
||||||
|
Uncertain<bool> parallel = ( s == Uncertain<Sign>(ZERO) ) ;
|
||||||
|
|
||||||
|
return parallel & !are_edges_orderly_collinearC2(e0,e1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class FT>
|
||||||
|
inline
|
||||||
|
Uncertain<Sign> certified_side_of_oriented_lineC2(const FT &a, const FT &b, const FT &c, const FT &x, const FT &y)
|
||||||
|
{
|
||||||
|
return CGAL_NTS certified_sign(a*x+b*y+c);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -74,13 +116,13 @@ Sorted_triedge_2<K> collinear_sort ( Triedge_2<K> const& triedge )
|
||||||
|
|
||||||
int idx0=0, idx1=1, idx2=2 ;
|
int idx0=0, idx1=1, idx2=2 ;
|
||||||
|
|
||||||
Uncertain<bool> is_01 = are_edges_collinearC2(triedge.e0(),triedge.e1());
|
Uncertain<bool> is_01 = are_edges_orderly_collinearC2(triedge.e0(),triedge.e1());
|
||||||
if ( !CGAL_NTS is_indeterminate(is_01) )
|
if ( !CGAL_NTS is_indeterminate(is_01) )
|
||||||
{
|
{
|
||||||
Uncertain<bool> is_02 = are_edges_collinearC2(triedge.e0(),triedge.e2());
|
Uncertain<bool> is_02 = are_edges_orderly_collinearC2(triedge.e0(),triedge.e2());
|
||||||
if ( !CGAL_NTS is_indeterminate(is_02) )
|
if ( !CGAL_NTS is_indeterminate(is_02) )
|
||||||
{
|
{
|
||||||
Uncertain<bool> is_12 = are_edges_collinearC2(triedge.e1(),triedge.e2());
|
Uncertain<bool> is_12 = are_edges_orderly_collinearC2(triedge.e1(),triedge.e2());
|
||||||
if ( !CGAL_NTS is_indeterminate(is_12) )
|
if ( !CGAL_NTS is_indeterminate(is_12) )
|
||||||
{
|
{
|
||||||
if ( CGAL_NTS logical_and(is_01 , !is_02 , !is_12 ) )
|
if ( CGAL_NTS logical_and(is_01 , !is_02 , !is_12 ) )
|
||||||
|
|
@ -120,21 +162,6 @@ Sorted_triedge_2<K> collinear_sort ( Triedge_2<K> const& triedge )
|
||||||
return Sorted_triedge_2<K>(triedge.e(idx0),triedge.e(idx1),triedge.e(idx2),lCollinearCount);
|
return Sorted_triedge_2<K>(triedge.e(idx0),triedge.e(idx1),triedge.e(idx2),lCollinearCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the offset-zone for the triedge 'zone' is degenerate.
|
|
||||||
//
|
|
||||||
// Since an offset zone [e0->e1->e2] is the region inside the polygon where the three edges remain connected as they
|
|
||||||
// move inward, if e0 and/or e2 is parallel to e1 then the zone is degenerate (collapsed to the bisecting line of the parallel edges)
|
|
||||||
//
|
|
||||||
// (that is, the parallel zone edges, since they share a vertex, have already collide and can't move any further)
|
|
||||||
//
|
|
||||||
template<class K>
|
|
||||||
Uncertain<bool> is_offset_zone_degenerate ( Triedge_2<K> const& zone )
|
|
||||||
{
|
|
||||||
Uncertain<bool> is_01 = are_edges_parallelC2(zone.e0(),zone.e1());
|
|
||||||
Uncertain<bool> is_12 = are_edges_parallelC2(zone.e1(),zone.e2());
|
|
||||||
|
|
||||||
return CGAL_NTS logical_or(is_01,is_12);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given 3 oriented straight line segments: e0, e1, e2
|
// Given 3 oriented straight line segments: e0, e1, e2
|
||||||
// returns true if there exist some positive offset distance 't' for which the
|
// returns true if there exist some positive offset distance 't' for which the
|
||||||
|
|
@ -313,31 +340,62 @@ compare_offset_lines_isec_dist_to_pointC2 ( Triedge_2<K> const& s
|
||||||
return rResult ;
|
return rResult ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if the offset-zone for the triedge 'zone' is degenerate.
|
||||||
|
//
|
||||||
|
// Since an offset zone [e0->e1->e2] is the region inside the polygon where the three edges remain connected as they
|
||||||
|
// move inward, if e0 and/or e2 is parallel to e1 then the zone is degenerate (collapsed to the bisecting line of the parallel edges)
|
||||||
|
//
|
||||||
|
// (that is, the parallel zone edges, since they share a vertex, have already collide and can't move any further)
|
||||||
|
//
|
||||||
|
template<class K>
|
||||||
|
Uncertain<bool> is_offset_zone_degenerate ( Triedge_2<K> const& zone )
|
||||||
|
{
|
||||||
|
return are_edges_parallel_but_not_orderly_collinearC2(zone.e0(),zone.e1())
|
||||||
|
| are_edges_parallel_but_not_orderly_collinearC2(zone.e1(),zone.e2()) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Given a triple of oriented straight line segments: (e0,e1,e2) such that their offsets
|
// Given a triple of oriented straight line segments: (e0,e1,e2) such that their offsets
|
||||||
// at some distance intersects in a point (x,y), returns true if (x,y) is inside the passed offset zone.
|
// at some distance intersects in a point (x,y), returns true if (x,y) is inside the passed offset zone.
|
||||||
//
|
//
|
||||||
// An offset zone [z0->z1->z2] is a region where the offset edges z0',z1',z2' remain connected in the absence of topological changes.
|
// An offset zone [z0,z1,z2], where zi is a line, is a region where the corresponding offset edges (oriented segment)
|
||||||
|
// Z0'->Z1'->Z2' remain connected in the absence of topological changes.
|
||||||
// It is the area (bounded or not) to the left of z1, to the right of the angular bisector (z0,z1)
|
// It is the area (bounded or not) to the left of z1, to the right of the angular bisector (z0,z1)
|
||||||
// and to the left of the angular bisector (z1,z2).
|
// and to the left of the angular bisector (z1,z2).
|
||||||
// This area represents all the possible offset edges z1'.
|
// This area represents all the possible offset edges Z1'.
|
||||||
// If the event involves z1' (that is, z1 is one of (e0,e1,e2)) then a neccesary condition for the event to exist is
|
|
||||||
// that the point of coallision hits z1' as bounded by the vertices shared with z0' and z2',
|
|
||||||
// and not just the line supporting z1'.
|
|
||||||
// This condition is equivalent to the condition that (x,y) be in the offset zone [z0->z1->z2] as described above
|
|
||||||
// (which refers to the input edges and not the offset edges).
|
|
||||||
//
|
//
|
||||||
// This condition is neccesary but not sufficient becasue z1' might end up connected with edges other than z0' and z2'
|
// This predicate tells whether a split event, at (x,y), against z1, is effectively splitting the segment Z1'
|
||||||
|
// instead of hitting the supporting offseted line z1' but outside the segment.
|
||||||
|
//
|
||||||
|
// Events are defined in term of intersecting offset _lines_, not segments, thus if the event involves z1'
|
||||||
|
// (that is, z1 is one of (e0,e1,e2)) then a neccesary condition for the event to actually exist is
|
||||||
|
// that the point of coallision hits a segment of z1' as bounded by the vertices shared with z0' and z2',
|
||||||
|
// and not just the line z1'.
|
||||||
|
// This condition is equivalent to the condition that (x,y) be in the offset zone [z0,z1,z2] as described above
|
||||||
|
// (which refers to the input _lines_ and not the offset edges).
|
||||||
|
//
|
||||||
|
// This condition is neccesary but not sufficient becasue z1' might end up connected with lines other than z0' and z2'
|
||||||
// after some further event, so this predicate is valid only in the context of an event at a known time 't' such
|
// after some further event, so this predicate is valid only in the context of an event at a known time 't' such
|
||||||
// that it is known that at time t, z1' is indeed connected to z0' and z2'.
|
// that it is known that at time t, z1' is indeed connected to z0' and z2'.
|
||||||
//
|
//
|
||||||
// If z0 and/or z2 are parallel to z1 then the offset zone is "degenerate" and the event is conventionally considered
|
// During the shrinking process, edges can anihiliate one another; that is, collide not in a single point
|
||||||
// NOT inside the zone, so this predicate returns false in that case.
|
// but along a line segment (reach a common supporting line simultaneously).
|
||||||
|
// This is possible if and only if the edges are parallel but not collinear.
|
||||||
|
// Exactly at the time when such an anhiliation event ocurrs, the two initially parallel edges become connected
|
||||||
|
// in the offset polygon and form a degenerate alley or anntenna. Right after that the degenerate edges
|
||||||
|
// collapse and dissapears from the offset polygon and the rest of the process continues normally
|
||||||
|
// (or not if this is the very last event).
|
||||||
|
// Since Z0'->Z1'->Z2' are 3 edges _known_ to be connected at the time of the event defined by (e0,e1,e2),
|
||||||
|
// it might very well happen that z0 or z2 (or both) are parallel to z1. If that happens they never share
|
||||||
|
// a vertex except when they collapse in a common line, which is only an instant in the sense that
|
||||||
|
// right after that both edges dissappears from the wavefront.
|
||||||
|
// If z0 and/or z2 are parallel but not collinear to z1 they are connected in the offset polygons only when
|
||||||
|
// they collapsed into each other and in that instant Z1' is not (cannot) split by any opposite edge, thus,
|
||||||
|
// if z0 and/or z2 are parallel but not collinear to z2 the offset zone is "degenerate" and no split event is inside.
|
||||||
//
|
//
|
||||||
// PRECONDITIONS:
|
// PRECONDITIONS:
|
||||||
// There exist a single point at which the offset lines for e0,e1,e2 at 't' intersect.
|
// There exist a single point at which the offset lines for e0,e1,e2 at 't' intersect.
|
||||||
// 'z1' must be one of (e0,e1,e2); that is, (x,y) must be exactly over the offseted 'z1' at time 't'.
|
// 'z1' must be one of (e0,e1,e2); that is, (x,y) must be exactly over the offseted z1' at time 't'.
|
||||||
//
|
//
|
||||||
template<class K>
|
template<class K>
|
||||||
Uncertain<bool>
|
Uncertain<bool>
|
||||||
|
|
@ -372,56 +430,75 @@ is_offset_lines_isec_inside_offset_zoneC2 ( Triedge_2<K> const& event, Triedge_2
|
||||||
// Construct intersection point (x,y)
|
// Construct intersection point (x,y)
|
||||||
Optional_point_2 i = construct_offset_lines_isecC2(e_sorted);
|
Optional_point_2 i = construct_offset_lines_isecC2(e_sorted);
|
||||||
|
|
||||||
if ( zl && zc && zr && i)
|
if ( zl && zc && zr && i ) // all properly computed
|
||||||
{
|
{
|
||||||
// Calculate scaled (signed) distance from (x,y) to 'zc'
|
// Let L and R be the vertices formed by zl',zc' and zc',zr' resp.
|
||||||
|
// Let ZC1 be the oriented segment of zc' bounded first by L then by R.
|
||||||
|
// Let ZC0 be the ray of zc' before L, and ZC2 the ray of zc' after R.
|
||||||
|
// Let ZL0 be tha ray of zl' before L and ZL1 the ray of zl' after R
|
||||||
|
// Let ZR0 be tha ray of zl' before L and ZR1 the ray of zl' after R
|
||||||
|
|
||||||
|
// At the time of the event, each offseted edge zl', zc' and zr' are made of :
|
||||||
|
//
|
||||||
|
// zl': ZL0->L->ZL1
|
||||||
|
// zc': ZC0->L->ZC1->R->ZC2
|
||||||
|
// zr': ZR0->R->ZR1
|
||||||
|
|
||||||
|
// Here we need to determine if "i", known to be along zc', is inside ZC1 instead of ZC0 (and instead of ZC2)
|
||||||
|
|
||||||
|
// Since all edges move at the same speed, there are 3 cases to consider:
|
||||||
|
|
||||||
|
// (1) If L is convex, ZL1 is "behind" ZC1 while ZL0 is "before" ZC0.
|
||||||
|
// (2) If L is reflex, ZL1 is "before" ZC1 while ZL0 is "behind" ZC0.
|
||||||
|
// (3) If L is degenerate, that is, zl and zc are collinear, none if behind or before any other
|
||||||
|
|
||||||
|
// If L is case (1) then "i" is inside ZC1 and not ZC0 if the signed distance to zc is smaller than to zl
|
||||||
|
// If L is case (2) then "i" is inside ZC1 and not ZC0 if the signed distance to zc is larger than to zl
|
||||||
|
// If L is case (3) then "i" is inside ZC1 if its to the right of a line perpendicular to zc passing through L*
|
||||||
|
// where L* is a pseudo-vertex between collinear edges (the oriented midpoint between them)
|
||||||
|
|
||||||
|
// (likewise for R)
|
||||||
|
|
||||||
|
// sdc : scaled (signed) distance from (x,y) to 'zc'
|
||||||
FT sdc = zc->a() * i->x() + zc->b() * i->y() + zc->c() ;
|
FT sdc = zc->a() * i->x() + zc->b() * i->y() + zc->c() ;
|
||||||
|
|
||||||
CGAL_STSKEL_TRAITS_TRACE("\nsdc=" << sdc ) ;
|
CGAL_STSKEL_TRAITS_TRACE("\nsdc=" << sdc ) ;
|
||||||
|
|
||||||
// NOTE:
|
// NOTE:
|
||||||
// if (x,y) is not on the positive side of 'ec' it isn't on it's offset zone.
|
// if "i" is not on the positive side of 'zc' it isn't on it's offset zone.
|
||||||
// Also, if (x,y) is over 'ec' (its signed distance to ec is not certainly positive) then by definition is not on its _offset_
|
// Also, if "i" is _over_ 'zc' (its signed distance to ec is not certainly positive) then by definition is not on its _offset_
|
||||||
// zone either.
|
// zone either.
|
||||||
Uncertain<bool> cok = CGAL_NTS is_finite(sdc) ? CGAL_NTS certified_is_positive(sdc) : Uncertain<bool>::indeterminate() ;
|
Uncertain<bool> cok = CGAL_NTS is_finite(sdc) ? CGAL_NTS certified_is_positive(sdc) : Uncertain<bool>::indeterminate() ;
|
||||||
if ( ! CGAL_NTS is_indeterminate(cok) )
|
if ( ! CGAL_NTS is_indeterminate(cok) )
|
||||||
{
|
{
|
||||||
if ( cok == true )
|
if ( cok == true )
|
||||||
{
|
{
|
||||||
CGAL_STSKEL_TRAITS_TRACE("\nright side of ec." ) ;
|
CGAL_STSKEL_TRAITS_TRACE("\ncorrect side of zc." ) ;
|
||||||
|
|
||||||
// Determine if the vertices (el,ec) and (ec,er) are reflex.
|
Uncertain<bool> lc_collinear = are_edges_orderly_collinearC2(zone.e0(),zone.e1());
|
||||||
Uncertain<bool> lcx = CGAL_NTS certified_is_smaller(zl->a()*zc->b(),zc->a()*zl->b());
|
Uncertain<bool> cr_collinear = are_edges_orderly_collinearC2(zone.e1(),zone.e2());
|
||||||
Uncertain<bool> crx = CGAL_NTS certified_is_smaller(zc->a()*zr->b(),zr->a()*zc->b());
|
|
||||||
|
|
||||||
if ( ! CGAL_NTS is_indeterminate(lcx) && ! CGAL_NTS is_indeterminate(crx) )
|
if ( ! CGAL_NTS is_indeterminate(lc_collinear) && ! CGAL_NTS is_indeterminate(cr_collinear) )
|
||||||
{
|
{
|
||||||
CGAL_STSKEL_TRAITS_TRACE("\n(el,ec) reflex:" << lcx ) ;
|
Uncertain<bool> lok, rok ;
|
||||||
CGAL_STSKEL_TRAITS_TRACE("\n(ec,er) reflex:" << crx ) ;
|
|
||||||
|
|
||||||
// Calculate scaled (signed) distances from (x,y) to 'el' and 'er'
|
if ( !lc_collinear )
|
||||||
|
{
|
||||||
|
CGAL_STSKEL_TRAITS_TRACE("\nl:(zl,zc) is " << ( lc_reflex == SMALLER ? "reflex" : "non-reflex") ) ;
|
||||||
|
|
||||||
|
// sld: scaled (signed) distances from "i" to 'zl'
|
||||||
FT sdl = zl->a() * i->x() + zl->b() * i->y() + zl->c() ;
|
FT sdl = zl->a() * i->x() + zl->b() * i->y() + zl->c() ;
|
||||||
FT sdr = zr->a() * i->x() + zr->b() * i->y() + zr->c() ;
|
|
||||||
|
|
||||||
if ( CGAL_NTS is_finite(sdl) && CGAL_NTS is_finite(sdc) )
|
if ( CGAL_NTS is_finite(sdl) )
|
||||||
{
|
{
|
||||||
CGAL_STSKEL_TRAITS_TRACE("\nsdl=" << sdl ) ;
|
CGAL_STSKEL_TRAITS_TRACE("\nsdl=" << sdl ) ;
|
||||||
CGAL_STSKEL_TRAITS_TRACE("\nsdr=" << sdr ) ;
|
|
||||||
|
|
||||||
// Is (x,y) to the right|left of the bisectors (el,ec) and (ec,er)?
|
Uncertain<bool> lc_reflex = CGAL_NTS certified_is_smaller(zl->a()*zc->b(),zc->a()*zl->b());
|
||||||
// It depends on whether the vertex ((el,ec) and (ec,er)) is relfex or not.
|
|
||||||
// If it is reflex, then (x,y) is to the right|left of the bisector if sdl|sdr <= sdc; otherwise, if sdc <= sdl|srd
|
|
||||||
|
|
||||||
Uncertain<bool> lok = lcx ? CGAL_NTS certified_is_smaller_or_equal(sdl,sdc)
|
if ( ! CGAL_NTS is_indeterminate(lc_reflex) )
|
||||||
: CGAL_NTS certified_is_smaller_or_equal(sdc,sdl) ;
|
lok = ( lc_reflex ? CGAL_NTS certified_is_smaller_or_equal(sdl,sdc)
|
||||||
|
: CGAL_NTS certified_is_larger_or_equal (sdl,sdc)
|
||||||
Uncertain<bool> rok = crx ? CGAL_NTS certified_is_smaller_or_equal(sdr,sdc)
|
) ;
|
||||||
: CGAL_NTS certified_is_smaller_or_equal(sdc,sdr) ;
|
|
||||||
|
|
||||||
CGAL_STSKEL_TRAITS_TRACE("\nlok:" << lok) ;
|
|
||||||
CGAL_STSKEL_TRAITS_TRACE("\nrok:" << rok) ;
|
|
||||||
|
|
||||||
r = CGAL_NTS logical_and(lok , rok) ;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -430,12 +507,72 @@ is_offset_lines_isec_inside_offset_zoneC2 ( Triedge_2<K> const& event, Triedge_2
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CGAL_STSKEL_TRAITS_TRACE("\nUnable to reliably determine side-of-line." ) ;
|
CGAL_STSKEL_TRAITS_TRACE("\nl:(zl,zc) is DEGENERATE") ;
|
||||||
|
Optional_point_2 l = compute_oriented_midpoint(zone.e0(),zone.e1());
|
||||||
|
if ( l )
|
||||||
|
{
|
||||||
|
FT na, nb, nc ;
|
||||||
|
perpendicular_through_pointC2(zc->a(),zc->b(),l->x(),l->y(),na, nb, nc);
|
||||||
|
lok = certified_side_of_oriented_lineC2(na,nb,nc,i->x(),i->y()) != make_uncertain(POSITIVE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CGAL_STSKEL_TRAITS_TRACE("\nOverflow detected." ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !cr_collinear )
|
||||||
|
{
|
||||||
|
CGAL_STSKEL_TRAITS_TRACE("\nr:(zc,zr) is " << ( cr_reflex == SMALLER ? "reflex" : "non-reflex") ) ;
|
||||||
|
|
||||||
|
// slr: scaled (signed) distances from "i" to 'zr'
|
||||||
|
FT sdr = zr->a() * i->x() + zr->b() * i->y() + zr->c() ;
|
||||||
|
|
||||||
|
if ( CGAL_NTS is_finite(sdr) )
|
||||||
|
{
|
||||||
|
CGAL_STSKEL_TRAITS_TRACE("\nsdr=" << sdr ) ;
|
||||||
|
|
||||||
|
Uncertain<bool> cr_reflex = CGAL_NTS certified_is_smaller(zc->a()*zr->b(),zr->a()*zc->b());
|
||||||
|
|
||||||
|
if ( ! CGAL_NTS is_indeterminate(cr_reflex) )
|
||||||
|
rok = ( cr_reflex ? CGAL_NTS certified_is_smaller_or_equal(sdr,sdc)
|
||||||
|
: CGAL_NTS certified_is_larger_or_equal (sdr,sdc)
|
||||||
|
) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CGAL_STSKEL_TRAITS_TRACE("\nOverflow detected." ) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CGAL_STSKEL_TRAITS_TRACE("\nWRONG side of ec." ) ;
|
CGAL_STSKEL_TRAITS_TRACE("\nr:(zc,zr) is DEGENERATE") ;
|
||||||
|
Optional_point_2 r = compute_oriented_midpoint(zone.e1(),zone.e2());
|
||||||
|
if ( r )
|
||||||
|
{
|
||||||
|
FT na, nb, nc ;
|
||||||
|
perpendicular_through_pointC2(zc->a(),zc->b(),r->x(),r->y(),na, nb, nc);
|
||||||
|
rok = certified_side_of_oriented_lineC2(na,nb,nc,i->x(),i->y()) != make_uncertain(NEGATIVE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CGAL_STSKEL_TRAITS_TRACE("\nOverflow detected." ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CGAL_STSKEL_TRAITS_TRACE("\nlok:" << lok) ;
|
||||||
|
CGAL_STSKEL_TRAITS_TRACE("\nrok:" << rok) ;
|
||||||
|
|
||||||
|
r = CGAL_NTS logical_and(lok , rok) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CGAL_STSKEL_TRAITS_TRACE("\nUnable to reliably determine reflexivity of zone vertices." ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CGAL_STSKEL_TRAITS_TRACE("\nWRONG side of zc." ) ;
|
||||||
r = make_uncertain(false);
|
r = make_uncertain(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue