// ====================================================================== // // Copyright (c) 1999 The CGAL Consortium // // This software and related documentation is part of an INTERNAL release // of the Computational Geometry Algorithms Library (CGAL). It is not // intended for general use. // // ---------------------------------------------------------------------- // // release : $CGAL_Revision: CGAL-2.3-I-44 $ // release_date : $CGAL_Date: 2001/03/09 $ // // file : include/CGAL/Arr_polyline_traits.h // package : Arrangement (1.77) // maintainer : Eyal Flato // author(s) : Iddo Hanniel // coordinator : Tel-Aviv University (Dan Halperin ) // // ====================================================================== #ifndef CGAL_ARR_POLYLINE_TRAITS_H #define CGAL_ARR_POLYLINE_TRAITS_H #include #include #include #include #include #include #include #include #include #include #include #include CGAL_BEGIN_NAMESPACE template > class Arr_polyline_traits : public Kernel_ { public: typedef Tag_false Has_left_category; typedef Kernel_ Kernel; typedef Arr_polyline_traits Self; typedef typename Kernel::Point_2 Point_2; typedef Container Curve_2; typedef Container X_curve_2; typedef typename Kernel::Vector_2 Vector_2; typedef typename Kernel::Line_2 Line_2; // Obsolete, for backward compatibility typedef Point_2 Point; typedef Vector_2 Vector; typedef X_curve_2 X_curve; typedef Curve_2 Curve; protected: typedef typename Kernel::Segment_2 Segment_2; protected: // Functors: typedef typename Kernel::Is_vertical_2 Is_vertical_2; typedef typename Kernel::Construct_vertex_2 Construct_vertex_2; typedef typename Kernel::Less_x_2 Less_x_2; typedef typename Kernel::Equal_2 Equal_2; public: Arr_polyline_traits() { } /*! compare_x() compares the x-coordinates of two given points * \param p1 the first point * \param p2 the second point * \return LARGER if x(p1) > x(p2), SMALLER if x(p1) < x(p2), or else EQUAL * * \todo replace indirect use compare_x() with compare_x_2() */ Comparison_result compare_x(const Point_2 & p1, const Point_2 & p2) const { return compare_x_2_object()(p1, p2); } /*! compare_xy() compares the two given points by x, then by y * \param p1 the first point * \param p2 the second point * \return LARGER if x(p1) > x(p2) or if x(p1) = x(p2) and y(p1) > y(p2); * SMALLER if x(p1) < x(p2) or if x(p1) = x(p2) and y(p1) < y(p2); * or else EQUAL * * \todo replace indirect use compare_xy() with compare_xy_2() */ Comparison_result compare_xy(const Point_2 & p1, const Point_2 & p2) const { return compare_xy_2_object()(p1, p2);; } /*! curve_is_vertical * on X_curve only - not Curve! */ bool curve_is_vertical(const X_curve_2 & cv) const { CGAL_assertion(is_x_monotone(cv)); return compare_x(curve_source(cv), curve_target(cv)) == EQUAL; } /*! curve_is_in_x_range */ bool curve_is_in_x_range(const X_curve_2 & cv, const Point_2 & p) const { CGAL_assertion(is_x_monotone(cv)); Construct_vertex_2 construct_vertex = construct_vertex_2_object(); const Point_2 & source = curve_source(cv); const Point_2 & target = curve_target(cv); Less_x_2 less_x = less_x_2_object(); return !((less_x(source, p) && less_x(target, p)) || (less_x(p, source) && less_x(p, target))); } Comparison_result curve_compare_at_x(const X_curve_2 & cv1, const X_curve_2 & cv2, const Point_2 & p) const { CGAL_assertion(is_x_monotone(cv1)); CGAL_assertion(is_x_monotone(cv2)); CGAL_precondition(curve_is_in_x_range(cv1,p)); CGAL_precondition(curve_is_in_x_range(cv2,p)); typename X_curve_2::const_iterator pit_1 = cv1.begin(), pit_2 = cv2.begin(); typename X_curve_2::const_iterator after_1 = pit_1, after_2 = pit_2; ++after_1; ++after_2; // read: as long as both *pit and *after are on the same // side of p for( ; (compare_x(*pit_1,p) * compare_x(*after_1,p)) /*<=*/ >0 ; ++pit_1,++after_1) {} for( ; (compare_x(*pit_2,p) * compare_x(*after_2,p)) > 0 ; ++pit_2,++after_2) {} // the R here is the template parameter (see class def. above) Pm_segment_traits_2 segment_traits; const typename Pm_segment_traits_2::X_curve_2 seg1(*pit_1, *after_1), seg2(*pit_2, *after_2); // bug fix, shai 19/03/2000: // the polylines may contain vertical segments return (segment_traits.curve_compare_at_x(seg1, seg2, p)); } // precondition - x-monotone Comparison_result curve_compare_at_x_left(const X_curve_2 & cv1, const X_curve_2 & cv2, const Point_2 & p) const { CGAL_assertion(is_x_monotone(cv1)); CGAL_assertion(is_x_monotone(cv2)); // Check preconditions. CGAL_precondition(curve_is_in_x_range(cv1,p)); CGAL_precondition(curve_is_in_x_range(cv2,p)); CGAL_precondition(! curve_is_vertical(cv1)); CGAL_precondition(! curve_is_vertical(cv2)); CGAL_precondition_code( Point_2 leftmost1 = (compare_x(curve_source(cv1),curve_target(cv1))==LARGER) ? curve_target(cv1) : curve_source(cv1); Point_2 leftmost2 = (compare_x(curve_source(cv2),curve_target(cv2))==LARGER) ? curve_target(cv2) : curve_source(cv2); ); CGAL_precondition(compare_x(leftmost1,p) == SMALLER); CGAL_precondition(compare_x(leftmost2,p) == SMALLER); // Compare. typename X_curve_2::const_iterator pit = cv1.begin(); typename X_curve_2::const_iterator after = pit; ++after; for( ; (compare_x(*pit,p) * compare_x(*after,p)) > 0 ; ++pit,++after) {} Line_2 l1(*pit,*after); pit=cv2.begin(); after=pit; ++after; for( ; (compare_x(*pit,p) * compare_x(*after,p)) > 0 ; ++pit,++after) {} Line_2 l2(*pit,*after); CGAL_precondition (CGAL::compare_y_at_x(p,l1,l2) == EQUAL); // check if they are right endpoints (and compare to the one from // the left) otherwise - // //! \todo This is incorrect! we should probably return EQUAL. return (CGAL::compare_y_at_x(point_to_left(p),l1,l2)); } Comparison_result curve_compare_at_x_right(const X_curve_2& cv1, const X_curve_2& cv2, const Point_2& p) const { CGAL_assertion(is_x_monotone(cv1)); CGAL_assertion(is_x_monotone(cv2)); // Check preconditions. CGAL_precondition(curve_is_in_x_range(cv1,p)); CGAL_precondition(curve_is_in_x_range(cv2,p)); CGAL_precondition(! curve_is_vertical(cv1)); CGAL_precondition(! curve_is_vertical(cv2)); CGAL_precondition_code( Point_2 rightmost1 = (compare_x(curve_source(cv1),curve_target(cv1))==SMALLER) ? curve_target(cv1) : curve_source(cv1); Point_2 rightmost2 = (compare_x(curve_source(cv2),curve_target(cv2))==SMALLER) ? curve_target(cv2) : curve_source(cv2); ); CGAL_precondition(compare_x(rightmost1,p) == LARGER); CGAL_precondition(compare_x(rightmost2,p) == LARGER); // Compare. typename X_curve_2::const_iterator pit=cv1.begin(); typename X_curve_2::const_iterator after=pit; ++after; for( ; (compare_x(*pit,p) * compare_x(*after,p)) > 0 ; ++pit,++after) {} Line_2 l1(*pit,*after); pit=cv2.begin(); after=pit; ++after; for( ; (compare_x(*pit,p) * compare_x(*after,p)) > 0 ; ++pit,++after) {} Line_2 l2(*pit,*after); CGAL_precondition (CGAL::compare_y_at_x(p,l1,l2) == EQUAL); // check if they are left endpoints (and compare to the one from the // right) otherwise - //! \todo This is incorrect! we should probably return EQUAL. return (CGAL::compare_y_at_x(point_to_right(p),l1,l2)); } Comparison_result curve_get_point_status (const X_curve_2 &cv, const Point_2& p) const { CGAL_assertion(is_x_monotone(cv)); CGAL_precondition(curve_is_in_x_range(cv, p)); if (curve_is_vertical(cv)) { if (CGAL::compare_y(curve_source(cv),p)* CGAL::compare_y(curve_target(cv),p)<=0) return EQUAL; else return (CGAL::compare_y(curve_source(cv),p)); } typename X_curve_2::const_iterator pit = cv.begin(),after=pit; ++after; while ( (compare_x(*pit,p) * compare_x(*after,p)) > 0 ) { ++pit; ++after; } Line_2 l(*pit,*after); Comparison_result res = CGAL::compare_y_at_x(p, l); if (res == SMALLER) return LARGER; if (res == LARGER) return SMALLER; return EQUAL; } /*! \todo replace indirect use point_is_same() with equal_2() */ bool point_is_same(const Point_2 & p1, const Point_2 & p2) const { return equal_2_object()(p1, p2); } /*! \todo replace indirect use curve_is_same() with equal_2() */ bool curve_is_same(const X_curve_2 & cv1, const X_curve_2 & cv2) const { CGAL_assertion(is_x_monotone(cv1)); CGAL_assertion(is_x_monotone(cv2)); if (cv1.size() != cv2.size()) return false; typename X_curve_2::const_iterator it1 = cv1.begin(); typename X_curve_2::const_iterator it2 = cv2.begin(); Equal_2 equal = equal_2_object(); bool is_equal = true; while (it1 != cv1.end()) { if (!equal(*it1++, *it2++)) { is_equal = false; break; } } if (is_equal) return true; // Reverse order: it1 = cv1.begin(); it2 = cv2.end(); while (it1 != cv1.end()) { if (!equal(*it1++, *--it2)) return false; } return true; } /*! */ Point_2 curve_source(const X_curve_2 & cv) const { return *(cv.begin()); } /*! */ Point_2 curve_target(const X_curve_2 & cv) const { typename X_curve_2::const_iterator it = cv.end(); return *--it; } /////////////////////////////////////////////////////// // ARRANGEMENT FUNCS X_curve_2 curve_flip(const X_curve_2 & cv) const { X_curve_2 cv1(cv); std::reverse(cv1.begin(),cv1.end()); return cv1; } bool is_x_monotone(const Curve_2& cv) const { CGAL_assertion(cv.size()>=2); //one point is not a curve if (cv.size()==2) return true; //segment typename X_curve_2::const_iterator p0=cv.begin(); typename X_curve_2::const_iterator p1=p0; ++p1; typename X_curve_2::const_iterator p2=p1; ++p2; for(; p2!=cv.end(); ++p0,++p1,++p2) { if ( compare_x(*p0,*p1) * compare_x(*p1,*p2) <=0 ) return false; } // <= a matter of decision - only one vertical segment is considered // x-monotone return true; } //cuts into x-monotone curves, each vertical segment is 1 x-monotone curve //and not part of a bigger x-monotone polyline void make_x_monotone(const Curve_2& cv, std::list& l) { CGAL_assertion(cv.size()>=2); //one point is not a curve if (cv.size()==2) { //segment l.push_back(cv); return; } typename X_curve_2::const_iterator p0=cv.begin(); typename X_curve_2::const_iterator p1=p0; ++p1; typename X_curve_2::const_iterator p2=p1; ++p2; typename X_curve_2::const_iterator last_cut=p0; for(; p2!=cv.end(); ++p0,++p1,++p2) { //in future use constants instead of compare_x if (compare_x(*p0,*p1)==EQUAL) { //vertical segment - (p0,p1) if (p0!=last_cut) { //needed for the case: // | p1 // o p0=lastcut (was p1 before) // | l.push_back(X_curve_2(last_cut,p1)); //push_back the curve (last_cut...p0) } l.push_back(X_curve_2(p0,p2)); //push_back the segment (p0,p1) last_cut=p1; } else if ( compare_x(*p0,*p1) * compare_x(*p1,*p2) <= 0 ) { l.push_back(X_curve_2(last_cut,p2)); last_cut=p1; } } l.push_back(X_curve_2(last_cut,p2)); //push the residue (last cut to end) CGAL_assertion(p2==cv.end()); } void curve_split(const X_curve_2& cv, X_curve_2& c1, X_curve_2& c2, const Point_2& split_pt) { //split curve at split point into c1 and c2 CGAL_precondition(curve_get_point_status(cv,split_pt)==EQUAL); CGAL_precondition(CGAL::compare_lexicographically_xy(curve_source(cv), split_pt) != EQUAL); CGAL_precondition(CGAL::compare_lexicographically_xy(curve_target(cv), split_pt) != EQUAL); typename X_curve_2::const_iterator p0=cv.begin(); typename X_curve_2::const_iterator p1=p0; ++p1; bool split_at_vertex=false; for (; p1 != cv.end(); ++p0,++p1) { if (point_is_same(*p1,split_pt)) { split_at_vertex=true; break; } if (compare_x(*p0,split_pt) * compare_x(split_pt,*p1) >= 0) { //in x range break; } } c1.clear(); c2.clear(); typename X_curve_2::const_iterator ci=cv.begin(); while (ci!=p1) { c1.push_back(*ci); ++ci; } if (!split_at_vertex) { c1.push_back(split_pt); c2.push_back(split_pt); } else { c1.push_back(*p1); } while (ci!=cv.end()) { c2.push_back(*ci); ++ci; } //moved this up to enable use of vector as container /* if (!split_at_vertex) { c1.push_back(split_pt); c2.push_front(split_pt); } else { c1.push_back(*p1); } */ } //NOTE: when there is an overlap we will always return a SEGMENT (i.e., // p1 and p2 will be on a segment) even if the overlap is a polyline // , this is still sufficient for the arrangement. might be // changed in the future. bool nearest_intersection_to_right(const X_curve_2& cv1, const X_curve_2& cv2, const Point_2& pt, Point_2& p1, Point_2& p2) const { CGAL_assertion(is_x_monotone(cv1)); CGAL_assertion(is_x_monotone(cv2)); bool found( false); // curves do not necessarily intersect if ( ! _do_curves_intersect_to_right(cv1,cv2,pt)) return false; X_curve_2 c1(cv1),c2(cv2); if ( ! lexicographically_xy_smaller (curve_source(c1),curve_target(c1))) c1=curve_flip(cv1); if ( ! lexicographically_xy_smaller (curve_source(c2),curve_target(c2))) c2=curve_flip(cv2); // check if both first points are left of pt, if they are reach the // points directly left of pt, and check if their segments intersect //to the right of pt, if not continue with a normal sweep until //we find an intersection point or we reach the end. typename X_curve_2::const_iterator i1s=c1.begin(),i1e=c1.end(); typename X_curve_2::const_iterator i1t=i1s; ++i1t; typename X_curve_2::const_iterator i2s=c2.begin(),i2e=c2.end(); typename X_curve_2::const_iterator i2t=i2s; ++i2t; int number_to_left=0; //increment this variable if curve starts left of pt if (!lexicographically_xy_larger (*i1s,pt)) { //increment to nearest from the left of pt ++number_to_left; for (; i1t!=i1e; ++i1s,++i1t) { if (lexicographically_xy_larger (*i1t,pt)) break; } if (i1t==i1e) return false; } //now i1s holds the source vertex and i1t holds the target if (!lexicographically_xy_larger (*i2s,pt)) { //increment ++number_to_left; for (; i2t!=i2e; ++i2s,++i2t) { if (lexicographically_xy_larger (*i2t,pt)) break; } if (i2t==i2e) return false ; //c2 ends to the left of pt } if (number_to_left==2) { //check if intersection exists and is lex larger Object result = intersection(Segment_2(*i1s, *i1t), Segment_2(*i2s, *i2t)); Point_2 i_pt; Segment_2 i_seg; if (assign(i_pt,result)) { //check if intersection point to the right of pt if (lexicographically_xy_larger (i_pt,pt)) { //debug #ifndef ARR_USES_LEDA_RATIONAL //normalize if we are with rational numbers p1=p2=i_pt; found = true; #else p1=p2=Point_2(i_pt.x().normalize(),i_pt.y().normalize()); found = true; #endif } } if ( ! found && assign(i_seg,result)) { //check if intersection seg to the right of pt if (lexicographically_xy_larger (i_seg.source(),i_seg.target())) i_seg=i_seg.opposite(); if (lexicographically_xy_larger (i_seg.target(),pt)) { p2=i_seg.target(); if (lexicographically_xy_larger (i_seg.source(),pt)) { p1=i_seg.source();} else { // p1=pt; // Modified by Eug // Performing vertical ray shooting from pt. // Finding the intersection point. We know by now // that there is exactly ONE point. Assinging this // point to p1. // Bug: What happens if the curves are vertical. The vertical ray // shoot will return a segment instead of point. Point_2 ap1( pt.x(), i_seg.source().y() ); Point_2 ap2( pt.x(), i_seg.target().y() ); Segment_2 vertical_pt_x_base( ap1, ap2 ); Object i_obj = intersection( vertical_pt_x_base, i_seg ); //assign( p1, i_obj ); // Causes a bug if the result is a segment. // Bug fix: Eti. Point_2 tmp_p1; Segment_2 i_vertical; if ( assign( tmp_p1, i_obj )) p1=tmp_p1; else if ( assign(i_vertical, i_obj)) // the intersection vertical segment starts at pt. p1=i_vertical.source(); } found = true; } } if ( ! found) { //advance to the nearer point if (lexicographically_xy_larger (*i2t,*i1t)) { ++i1s; ++i1t; if (i1t==i1e) return false; } else { ++i2s; ++i2t; if (i2t==i2e) return false; } } } //NOW we can start sweeping the chains while ( ! found) { //check intersection of the segments Object result; result = intersection(Segment_2(*i1s, *i1t), Segment_2(*i2s, *i2t)); Point_2 i_pt; Segment_2 i_seg; if (assign(i_pt,result)) { #ifndef ARR_USES_LEDA_RATIONAL //normalize if we are with rational numbers p1=p2=i_pt; #else p1=p2=Point_2(i_pt.x().normalize(),i_pt.y().normalize()); #endif found = true; } if (!found && assign(i_seg,result)) { //check if intersection seg to the right of pt if (lexicographically_xy_larger (i_seg.source(),i_seg.target())) i_seg=i_seg.opposite(); if (lexicographically_xy_larger (i_seg.target(),pt)) { p2=i_seg.target(); if (lexicographically_xy_larger (i_seg.source(),pt)) { p1=i_seg.source();} else { // p1=pt; // Modified by Eug // Performing vertical ray shooting from pt. // Finding the intersection point. We know by now // that there is exactly ONE point. Assinging this // point to p1. Point_2 ap1( pt.x(), i_seg.source().y() ); Point_2 ap2( pt.x(), i_seg.target().y() ); Segment_2 vertical_pt_x_base( ap1, ap2 ); Object i_obj = intersection( vertical_pt_x_base, i_seg ); //assign( p1, i_obj ); // Causes a bug if the result is a segment. // Bug fix: Eti. Point_2 tmp_p1; Segment_2 i_vertical; if ( assign( tmp_p1, i_obj )) p1=tmp_p1; else if ( assign(i_vertical, i_obj)) // the intersection vertical segment starts at pt. p1=i_vertical.source(); } found = true; } } if ( ! found) { //advance to the nearer point if (lexicographically_xy_larger (*i2t,*i1t)) { ++i1s; ++i1t; if (i1t==i1e) return false; } else { ++i2s; ++i2t; if (i2t==i2e) return false; } } } // end while ( ! found) // if the x point is at the end of a segment, then there might be // an overlap in the continious of the polyline if ( found && point_is_same(p1, p2) ) { typename X_curve_2::const_iterator s1=i1s, t1=i1t, s2=i2s, t2=i2t; s1++; t1++; s2++; t2++; if (t1 != i1e && t2 != i2e) { // check for overlap after x point Object result; Segment_2 i_seg; if ( point_is_same(p1, *i1t) && point_is_same(p1, *i2t)) { result = intersection(Segment_2(*s1, *t1), Segment_2(*s2, *t2)); } else if ( point_is_same(p1, *i1t)) { result = intersection(Segment_2(*s1, *t1), Segment_2(*i2s, *i2t)); } else if ( point_is_same(p1, *i2t)) { result = intersection(Segment_2(*i1s, *i1t), Segment_2(*s2, *t2)); } if (assign(i_seg,result)) { // no need to check whether intersection seg to the right of pt, // because we have already found an x point to the right of pt. if (lexicographically_xy_larger (i_seg.source(),i_seg.target())) i_seg=i_seg.opposite(); p1 = i_seg.source(); p2 = i_seg.target(); } } } return found; } bool curves_overlap(const X_curve_2& ca, const X_curve_2& cb) const { CGAL_assertion(is_x_monotone(ca)); CGAL_assertion(is_x_monotone(cb)); //do a flip so they are left to right X_curve_2 c1(ca),c2(cb); if (lexicographically_xy_larger(curve_source(ca),curve_target(ca))) c1=curve_flip(ca); if (lexicographically_xy_larger(curve_source(cb),curve_target(cb))) c2=curve_flip(cb); typename X_curve_2::const_iterator i1s=c1.begin(),i1e=c1.end(); typename X_curve_2::const_iterator i1t=i1s; ++i1t; typename X_curve_2::const_iterator i2s=c2.begin(),i2e=c2.end(); typename X_curve_2::const_iterator i2t=i2s; ++i2t; //now i1s holds the source vertex and i1t holds the target Point_2 i_pt; Segment_2 i_seg; Segment_2 s1(*i1s,*i1t),s2(*i2s,*i2t); Object res=intersection(s1,s2); if (assign(i_seg,res)) { if (!point_is_same(i_seg.source(),i_seg.target())) return true; } //advance to the nearer point if (lexicographically_xy_larger(*i2t,*i1t)) { ++i1s; ++i1t; if (i1t==i1e) return false; } else { ++i2s; ++i2t; if (i2t==i2e) return false; } //NOW we can start sweeping the chains while (1) { Segment_2 i_seg; Segment_2 s1(*i1s,*i1t),s2(*i2s,*i2t); res=intersection(s1,s2); if (assign(i_seg,res)) { if (!point_is_same(i_seg.source(),i_seg.target())) return true; } if (lexicographically_xy_larger(*i2t,*i1t)) { ++i1s; ++i1t; if (i1t==i1e) return false; } else { ++i2s; ++i2t; if (i2t==i2e) return false; } } } /*! point_reflect_in_x_and_y() reflects the given point about the origin */ Point_2 point_reflect_in_x_and_y(const Point_2 & pt) const { Point_2 org = construct_point_2_object()(ORIGIN); Vector_2 v = construct_vector_2_object()(pt, org); Point_2 reflected_pt(v); return reflected_pt; } /*! */ X_curve_2 curve_reflect_in_x_and_y( const X_curve_2 & cv) const { X_curve_2 reflected_cv; typename Curve_2::const_iterator it = cv.begin(); while (it != cv.end()) reflected_cv.push_back(point_reflect_in_x_and_y(*it++)); return reflected_cv; } //////////////////////////////////////////////////////////////////// // PRIVATE private: //! \todo Remove the point_to_left() and point_to_right() functions. Point_2 point_to_left(const Point_2& p) const { return p+Vector_2(-1,0);; } Point_2 point_to_right(const Point_2& p) const { return p+Vector_2(1,0);; } //returns true iff the intersectionis lexicographically strictly right of pt bool _do_curves_intersect_to_right (const X_curve_2& ca, const X_curve_2& cb, const Point_2& pt) const { CGAL_assertion(is_x_monotone(ca)); CGAL_assertion(is_x_monotone(cb)); // check if both first points are left of pt, if they are reach the // points directly left of pt, and check if their segments intersect //to the right of pt, if not continue with a normal sweep until //we find an intersection point or we reach the end. //do a flip or can we assume they are left to right ?? X_curve_2 c1(ca),c2(cb); if (lexicographically_xy_larger(curve_source(ca), curve_target(ca)) == LARGER ) c1=curve_flip(ca); if (lexicographically_xy_larger(curve_source(cb),curve_target(cb)) == LARGER ) c2=curve_flip(cb); typename X_curve_2::const_iterator i1s=c1.begin(),i1e=c1.end(); typename X_curve_2::const_iterator i1t=i1s; ++i1t; typename X_curve_2::const_iterator i2s=c2.begin(),i2e=c2.end(); typename X_curve_2::const_iterator i2t=i2s; ++i2t; int number_to_left=0; //increment this variable if curve starts left of pt if (!lexicographically_xy_larger (*i1s,pt)) { //increment to nearest from the left of pt ++number_to_left; for (; i1t!=i1e; ++i1s,++i1t) { if (lexicographically_xy_larger (*i1t,pt)) break; } if (i1t==i1e) return false; //c1 ends to the left of pt } //now i1s holds the source vertex and i1t holds the target if (!lexicographically_xy_larger (*i2s,pt)) { //increment ++number_to_left; for (; i2t!=i2e; ++i2s,++i2t) { if (lexicographically_xy_larger (*i2t,pt)) break; } if (i2t==i2e) return false; //c2 ends to the left of pt } if (number_to_left==2) { //check if intersection exists and is lex larger Object result; Point_2 i_pt; Segment_2 i_seg; result = intersection(Segment_2(*i1s, *i1t), Segment_2(*i2s, *i2t)); if (assign(i_pt,result)) { //check if intersection point to the right of pt if (lexicographically_xy_larger (i_pt,pt)) { return true; } } else if (assign(i_seg,result)) { //check if intersection seg to the right of pt if (lexicographically_xy_larger (i_seg.source(),pt) || lexicographically_xy_larger (i_seg.target(),pt)) { return true; } } //debug else { //cerr << "segments don't intersect ??" << endl; } //advance to the nearer point if (lexicographically_xy_larger (*i2t,*i1t)) { ++i1s; ++i1t; if (i1t==i1e) return false; } else { ++i2s; ++i2t; if (i2t==i2e) return false; } } //NOW we can start sweeping the chains while (1) { //check for intersection of the segments if (do_intersect(Segment_2(*i1s, *i1t), Segment_2(*i2s, *i2t))) { return true; } //advance to the nearer point if (lexicographically_xy_larger (*i2t,*i1t)) { ++i1s; ++i1t; if (i1t==i1e) return false; } else { ++i2s; ++i2t; if (i2t==i2e) return false; } } } public: void display(const X_curve_2& cv) const { typename X_curve_2::const_iterator it=cv.begin(),eit=cv.end(); while(it!=eit) { std::cerr << *it++;} } //the same for window stream }; CGAL_END_NAMESPACE #endif