diff --git a/Generator/include/CGAL/point_generators_2.h b/Generator/include/CGAL/point_generators_2.h index bfa26affe5f..ea08ed3170b 100644 --- a/Generator/include/CGAL/point_generators_2.h +++ b/Generator/include/CGAL/point_generators_2.h @@ -186,7 +186,7 @@ generate_point() { this->d_item = creator( T( this->d_range), T(d)); break; default: - CGAL_assume(false); + CGAL_unreachable(); } } diff --git a/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH2.h b/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH2.h index a97ca83abf5..7678de819f5 100644 --- a/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH2.h +++ b/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH2.h @@ -856,7 +856,7 @@ Aff_transformation_repH2::homogeneous(int i, int j) const case 0: return a; case 1: return b; case 2: return c; - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 1: switch (j) @@ -864,7 +864,7 @@ Aff_transformation_repH2::homogeneous(int i, int j) const case 0: return d; case 1: return e; case 2: return f; - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 2: switch (j) @@ -872,10 +872,10 @@ Aff_transformation_repH2::homogeneous(int i, int j) const case 0: return RT(0); case 1: return RT(0); case 2: return g; - default: CGAL_assume(false); + default: CGAL_unreachable(); } } - CGAL_assume(false); + CGAL_unreachable(); return RT(0); } @@ -900,7 +900,7 @@ Translation_repH2::homogeneous(int i, int j) const case 0: return _tv.hw(); case 1: return RT(0); case 2: return _tv.hx(); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 1: switch (j) @@ -908,7 +908,7 @@ Translation_repH2::homogeneous(int i, int j) const case 0: return RT(0); case 1: return _tv.hw(); case 2: return _tv.hy(); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 2: switch (j) @@ -916,10 +916,10 @@ Translation_repH2::homogeneous(int i, int j) const case 0: return RT(0); case 1: return RT(0); case 2: return _tv.hw(); - default: CGAL_assume(false); + default: CGAL_unreachable(); } } - CGAL_assume(false); + CGAL_unreachable(); return RT(0); } @@ -935,7 +935,7 @@ Translation_repH2::cartesian(int i, int j) const case 0: return FT(1); case 1: return FT(0); case 2: return _tv.x(); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 1: switch (j) @@ -943,7 +943,7 @@ Translation_repH2::cartesian(int i, int j) const case 0: return FT(0); case 1: return FT(1); case 2: return _tv.y(); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 2: switch (j) @@ -951,10 +951,10 @@ Translation_repH2::cartesian(int i, int j) const case 0: return FT(0); case 1: return FT(0); case 2: return FT(1); - default: CGAL_assume(false); + default: CGAL_unreachable(); } } - CGAL_assume(false); + CGAL_unreachable(); return FT(0); } @@ -971,7 +971,7 @@ homogeneous(int i, int j) const case 0: return _cos; case 1: return - _sin; case 2: return RT(0); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 1: switch (j) @@ -979,7 +979,7 @@ homogeneous(int i, int j) const case 0: return _sin; case 1: return _cos; case 2: return RT(0); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 2: switch (j) @@ -987,10 +987,10 @@ homogeneous(int i, int j) const case 0: return RT(0); case 1: return RT(0); case 2: return _den; - default: CGAL_assume(false); + default: CGAL_unreachable(); } } - CGAL_assume(false); + CGAL_unreachable(); return RT(0); } @@ -1007,7 +1007,7 @@ cartesian(int i, int j) const case 0: return FT(_cos) / FT(_den); case 1: return - FT(_sin) / FT(_den); case 2: return FT(0); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 1: switch (j) @@ -1015,7 +1015,7 @@ cartesian(int i, int j) const case 0: return FT(_sin) / FT(_den); case 1: return FT(_cos) / FT(_den); case 2: return FT(0); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 2: switch (j) @@ -1023,10 +1023,10 @@ cartesian(int i, int j) const case 0: return FT(0); case 1: return FT(0); case 2: return FT(1); - default: CGAL_assume(false); + default: CGAL_unreachable(); } } - CGAL_assume(false); + CGAL_unreachable(); return FT(0); } @@ -1043,7 +1043,7 @@ homogeneous(int i, int j) const case 0: return _sf_num; case 1: return RT(0); case 2: return RT(0); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 1: switch (j) @@ -1051,7 +1051,7 @@ homogeneous(int i, int j) const case 0: return RT(0); case 1: return _sf_num; case 2: return RT(0); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 2: switch (j) @@ -1059,10 +1059,10 @@ homogeneous(int i, int j) const case 0: return RT(0); case 1: return RT(0); case 2: return _sf_den; - default: CGAL_assume(false); + default: CGAL_unreachable(); } } - CGAL_assume(false); + CGAL_unreachable(); return RT(0); } @@ -1079,7 +1079,7 @@ cartesian(int i, int j) const case 0: return FT(_sf_num) / FT(_sf_den); case 1: return FT(0); case 2: return FT(0); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 1: switch (j) @@ -1087,7 +1087,7 @@ cartesian(int i, int j) const case 0: return FT(0); case 1: return FT(_sf_num) / FT(_sf_den); case 2: return FT(0); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 2: switch (j) @@ -1095,10 +1095,10 @@ cartesian(int i, int j) const case 0: return FT(0); case 1: return FT(0); case 2: return FT(1); - default: CGAL_assume(false); + default: CGAL_unreachable(); } } - CGAL_assume(false); + CGAL_unreachable(); return FT(0); } @@ -1116,7 +1116,7 @@ homogeneous(int i, int j) const case 0: return l.b()*l.b() - l.a()*l.a(); case 1: return l.a()*l.b()*mRT2; case 2: return l.a()*l.c()*mRT2; - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 1: switch (j) @@ -1124,7 +1124,7 @@ homogeneous(int i, int j) const case 0: return l.a()*l.b()*mRT2; case 1: return l.a()*l.a() - l.b()*l.b(); case 2: return l.b()*l.c()*mRT2; - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 2: switch (j) @@ -1132,10 +1132,10 @@ homogeneous(int i, int j) const case 0: return RT(0); case 1: return RT(0); case 2: return l.a()*l.a() + l.b()*l.b(); - default: CGAL_assume(false); + default: CGAL_unreachable(); } } - CGAL_assume(false); + CGAL_unreachable(); return RT(0); } @@ -1153,7 +1153,7 @@ cartesian(int i, int j) const case 0: return FT( l.b()-l.a() ) / FT( l.a()+l.b()); case 1: return FT( homogeneous(0,1)) / de; case 2: return FT( homogeneous(0,2)) / de; - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 1: switch (j) @@ -1161,7 +1161,7 @@ cartesian(int i, int j) const case 0: return FT( homogeneous(1,0)) / de; case 1: return FT( l.a()-l.b() ) / FT( l.a()+l.b()); case 2: return FT( homogeneous(1,2)) / de; - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 2: switch (j) @@ -1169,10 +1169,10 @@ cartesian(int i, int j) const case 0: return FT(0); case 1: return FT(0); case 2: return FT(1); - default: CGAL_assume(false); + default: CGAL_unreachable(); } } - CGAL_assume(false); + CGAL_unreachable(); return FT(0); } diff --git a/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH3.h b/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH3.h index f269496d79d..fa0ba377b4d 100644 --- a/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH3.h +++ b/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH3.h @@ -706,7 +706,7 @@ homogeneous(int i, int j) const case 1: return t01; case 2: return t02; case 3: return t03; - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 1: switch (j) @@ -715,7 +715,7 @@ homogeneous(int i, int j) const case 1: return t11; case 2: return t12; case 3: return t13; - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 2: switch (j) @@ -724,7 +724,7 @@ homogeneous(int i, int j) const case 1: return t21; case 2: return t22; case 3: return t23; - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 3: switch (j) @@ -733,10 +733,10 @@ homogeneous(int i, int j) const case 1: return RT0; case 2: return RT0; case 3: return t33; - default: CGAL_assume(false); + default: CGAL_unreachable(); } } - CGAL_assume(false); + CGAL_unreachable(); return RT0; } @@ -864,7 +864,7 @@ Translation_repH3::homogeneous(int i, int j) const case 1: return RT0; case 2: return RT0; case 3: return tv.hx(); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 1: switch (j) @@ -873,7 +873,7 @@ Translation_repH3::homogeneous(int i, int j) const case 1: return tv.hw(); case 2: return RT0; case 3: return tv.hy(); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 2: switch (j) @@ -882,7 +882,7 @@ Translation_repH3::homogeneous(int i, int j) const case 1: return RT0; case 2: return tv.hw(); case 3: return tv.hz(); - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case 3: switch (j) @@ -891,10 +891,10 @@ Translation_repH3::homogeneous(int i, int j) const case 1: return RT0; case 2: return RT0; case 3: return tv.hw(); - default: CGAL_assume(false); + default: CGAL_unreachable(); } } - CGAL_assume(false); + CGAL_unreachable(); return RT0; } diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h index 33350489671..2b392b6d8ca 100644 --- a/Installation/include/CGAL/config.h +++ b/Installation/include/CGAL/config.h @@ -369,15 +369,17 @@ using std::max; # define CGAL_NO_UNIQUE_ADDRESS #endif -// Macro CGAL_ASSUME +// Macro CGAL_ASSUME and CGAL_UNREACHABLE // Call a builtin of the compiler to pass a hint to the compiler #if __has_builtin(__builtin_unreachable) || (CGAL_GCC_VERSION > 0 && !__STRICT_ANSI__) // From g++ 4.5, there exists a __builtin_unreachable() // Also in LLVM/clang # define CGAL_ASSUME(EX) if(!(EX)) { __builtin_unreachable(); } +# define CGAL_UNREACHABLE() __builtin_unreachable() #elif defined(_MSC_VER) // MSVC has __assume # define CGAL_ASSUME(EX) __assume(EX) +# define CGAL_UNREACHABLE() __assume(0) #endif // If CGAL_ASSUME is not defined, then CGAL_assume and CGAL_assume_code are // defined differently, in diff --git a/Intersections_2/include/CGAL/Intersections_2/Line_2_Segment_2.h b/Intersections_2/include/CGAL/Intersections_2/Line_2_Segment_2.h index 0c5d881b544..5c2850af7a8 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Line_2_Segment_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Line_2_Segment_2.h @@ -125,7 +125,7 @@ Segment_2_Line_2_pair::intersection_type() const _result = SEGMENT; break; default: - CGAL_assume(false); + CGAL_unreachable(); } return _result; } diff --git a/Intersections_2/include/CGAL/Intersections_2/Segment_2_Segment_2.h b/Intersections_2/include/CGAL/Intersections_2/Segment_2_Segment_2.h index 3b9e7003a40..d912b2faf30 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Segment_2_Segment_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Segment_2_Segment_2.h @@ -34,48 +34,267 @@ namespace Intersections { namespace internal { +// struct used to report the combinaric of the intersection +// of 2 2D segments. +// More information could be gathered if exposed in do_intersect. +// See comments with DI_MORE_INFO_TAG +struct S2S2_inter_info +{ + bool inter = false; + bool dim = 0; + std::array pt_ids = {-1,-1}; + + S2S2_inter_info(bool inter) + : inter(inter) + {} + + // intersection is an input endpoint + S2S2_inter_info(int id) + : inter(true) + { + pt_ids[0]=id; + } + + // intersection is a segment + S2S2_inter_info(int id1,int id2) + : inter(true) + , dim(1) + { + pt_ids[0]=id1; + pt_ids[1]=id2; + } +}; + template -inline bool +inline S2S2_inter_info do_intersect(const typename K::Segment_2 &seg1, const typename K::Segment_2 &seg2); - - +// lexicographic order of points p1 < p3 < p2 < p4, with segments (p1,p2) and (p3,p4) template -bool seg_seg_do_intersect_crossing( - const typename K::Point_2 &p1, const typename K::Point_2 &p2, - const typename K::Point_2 &p3, const typename K::Point_2 &p4, - const K& k) +S2S2_inter_info +seg_seg_do_intersect_crossing( + const typename K::Point_2& p1, const typename K::Point_2& p2, + const typename K::Point_2& p3, const typename K::Point_2& p4, + int /* i1 */, int i2, int i3, int /* i4 */, + const K& k, bool extra_test) { switch (make_certain(k.orientation_2_object()(p1,p2,p3))) { case LEFT_TURN: - return ! (k.orientation_2_object()(p3,p4,p2) == RIGHT_TURN); // right_turn(p3,p4,p2); + { + switch (k.orientation_2_object()(p3,p4,p2)) + { + case COLLINEAR: + return S2S2_inter_info(i2); + case RIGHT_TURN: + return S2S2_inter_info(false); + case LEFT_TURN: + return S2S2_inter_info(true); + default: + CGAL_unreachable(); + } + } case RIGHT_TURN: - return ! (k.orientation_2_object()(p3,p4,p2) == LEFT_TURN); //left_turn(p3,p4,p2); + { + switch (k.orientation_2_object()(p3,p4,p2)) + { + case COLLINEAR: + return S2S2_inter_info(i2); + case RIGHT_TURN: + return S2S2_inter_info(true); + case LEFT_TURN: + return S2S2_inter_info(false); + default: + CGAL_unreachable(); + } + } case COLLINEAR: - return true; + if (extra_test && k.collinear_2_object()(p3,p4,p2)) + return S2S2_inter_info(i3, i2); + return S2S2_inter_info(i3); + default: + CGAL_unreachable(); } CGAL_kernel_assertion(false); - return false; + return S2S2_inter_info(false); +} + +// used internally by Arr_segment_traits_2template +template +bool +seg_seg_do_intersect_crossing( + const typename K::Point_2& p1, const typename K::Point_2& p2, + const typename K::Point_2& p3, const typename K::Point_2& p4, + const K& k) +{ + return seg_seg_do_intersect_crossing(p1,p2,p3,p4,0,0,0,0,k,false).inter; } +// lexicographic order of points p1 < p3 < p4 < p2, with segments (p1,p2) and (p3,p4) template -bool seg_seg_do_intersect_contained( - const typename K::Point_2 &p1, const typename K::Point_2 &p2, - const typename K::Point_2 &p3, const typename K::Point_2 &p4, - const K& k) +S2S2_inter_info +seg_seg_do_intersect_contained( + const typename K::Point_2& p1, const typename K::Point_2& p2, + const typename K::Point_2& p3, const typename K::Point_2& p4, + int /* i1 */, int /* i2 */, int i3, int i4, + const K& k, bool extra_test) { switch (make_certain(k.orientation_2_object()(p1,p2,p3))) { case LEFT_TURN: - return ! (k.orientation_2_object()(p1,p2,p4) == LEFT_TURN); // left_turn(p1,p2,p4); + { + switch (k.orientation_2_object()(p1,p2,p4)) + { + case COLLINEAR: + return S2S2_inter_info(i4); + case RIGHT_TURN: + return S2S2_inter_info(true); + case LEFT_TURN: + return S2S2_inter_info(false); + default: + CGAL_unreachable(); + } + } case RIGHT_TURN: - return ! (k.orientation_2_object()(p1,p2,p4) == RIGHT_TURN); // right_turn(p1,p2,p4); + { + switch (k.orientation_2_object()(p1,p2,p4)) + { + case COLLINEAR: + return S2S2_inter_info(i4); + case RIGHT_TURN: + return S2S2_inter_info(false); + case LEFT_TURN: + return S2S2_inter_info(true); + default: + CGAL_unreachable(); + } + } case COLLINEAR: - return true; + if (extra_test && k.collinear_2_object()(p3,p4,p2)) + return S2S2_inter_info(i3, i4); + return S2S2_inter_info(i3); + default: + CGAL_unreachable(); } CGAL_kernel_assertion(false); - return false; + return S2S2_inter_info(false); +} + +// used internally by Arr_segment_traits_2 +template +bool +seg_seg_do_intersect_contained( + const typename K::Point_2& p1, const typename K::Point_2& p2, + const typename K::Point_2& p3, const typename K::Point_2& p4, + const K& k) +{ + return seg_seg_do_intersect_contained(p1,p2,p3,p4,0,0,0,0,k,false).inter; +} + +template +S2S2_inter_info +do_intersect_with_info(const typename K::Segment_2 &seg1, + const typename K::Segment_2 &seg2, + const K& k, bool extra_test) +{ + typename K::Less_xy_2 less_xy; + + bool seg1_is_left_to_right = less_xy(seg1.source(),seg1.target()); + bool seg2_is_left_to_right = less_xy(seg2.source(),seg2.target()); + + int A1_id = seg1_is_left_to_right ? 0 : 1; + int A2_id = seg1_is_left_to_right ? 1 : 0; + int B1_id = seg2_is_left_to_right ? 0 : 1; + int B2_id = seg2_is_left_to_right ? 1 : 0; + + typename K::Point_2 const & A1 = seg1.point(A1_id); + typename K::Point_2 const & A2 = seg1.point(A2_id); + typename K::Point_2 const & B1 = seg2.point(B1_id); + typename K::Point_2 const & B2 = seg2.point(B2_id); + + typename K::Compare_xy_2 compare_xy; + + // first try to filter using the bbox of the segments + if (less_xy(A2,B1) + || less_xy(B2,A1)) + return S2S2_inter_info(false); + + switch(make_certain(compare_xy(A1,B1))) { + case SMALLER: + switch(make_certain(compare_xy(A2,B1))) { + case SMALLER: + return S2S2_inter_info(false); + case EQUAL: + return S2S2_inter_info(A2_id); // DI_MORE_INFO_TAG: A2==B1 but only A2 is reported + case LARGER: + switch(make_certain(compare_xy(A2,B2))) { + case SMALLER: + return seg_seg_do_intersect_crossing(A1,A2,B1,B2, A1_id,A2_id,B1_id+2,B2_id+2, k, extra_test); + case EQUAL: + // A1 < B1 < B2 = A1 + if (extra_test && k.collinear_2_object()(A1, A2, B1)) + return S2S2_inter_info(B1_id+2, B2_id+2); // DI_MORE_INFO_TAG: A2==B2 but only B2 is reported + return S2S2_inter_info(A2_id); // DI_MORE_INFO_TAG: A2==B2 but only A2 is reported + case LARGER: + return seg_seg_do_intersect_contained(A1,A2,B1,B2, A1_id,A2_id,B1_id+2,B2_id+2, k, extra_test); + default: + CGAL_unreachable(); + } + default: + CGAL_unreachable(); + + } + case EQUAL: + if (extra_test) + { + switch(make_certain(compare_xy(A2,B2))) { + case SMALLER: + // A1 = B1 < A2 < B2 + if (k.collinear_2_object()(A1,A2,B2)) + return S2S2_inter_info(A1_id, A2_id); // DI_MORE_INFO_TAG: A1==B1 but only A1 is reported + break; + case EQUAL: + // A1 = B1 < A2 = B2 + return S2S2_inter_info(A1_id, A2_id); // DI_MORE_INFO_TAG: A1==B1 and A2==B2 but only A1 and A2 are reported + case LARGER: + // A1 = B1 < B2 < A2 + if (k.collinear_2_object()(A1,A2,B2)) + return S2S2_inter_info(B1_id+2, B2_id+2); // DI_MORE_INFO_TAG: A1==B1 but only B1 is reported + break; + default: + CGAL_unreachable(); + } + } + return S2S2_inter_info(A1_id); // DI_MORE_INFO_TAG: A1==B1 but only A1 is reported + case LARGER: + switch(make_certain(compare_xy(B2,A1))) { + case SMALLER: + return S2S2_inter_info(false); + case EQUAL: + return S2S2_inter_info(A1_id); // DI_MORE_INFO_TAG: A1==B2 but only A1 is reported + case LARGER: + switch(make_certain(compare_xy(B2,A2))) { + case SMALLER: + return seg_seg_do_intersect_crossing(B1,B2,A1,A2, B1_id+2,B2_id+2,A1_id,A2_id, k, extra_test); + case EQUAL: + // B1 < A1 < A2 = B2 + if (extra_test && k.collinear_2_object()(B1, A1, B2)) + return S2S2_inter_info(A1_id, A2_id); // DI_MORE_INFO_TAG: A2==B2 but only A2 is reported + return S2S2_inter_info(A2_id); // DI_MORE_INFO_TAG: A2==B2 but only A2 is reported + case LARGER: + return seg_seg_do_intersect_contained(B1,B2,A1,A2, B1_id+2,B2_id+2,A1_id,A2_id, k, extra_test); + default: + CGAL_unreachable(); + } + default: + CGAL_unreachable(); + } + default: + CGAL_unreachable(); + } + + CGAL_kernel_assertion(false); + return S2S2_inter_info(false); } @@ -85,192 +304,9 @@ do_intersect(const typename K::Segment_2 &seg1, const typename K::Segment_2 &seg2, const K& k) { - typename K::Point_2 const & A1 = seg1.source(); - typename K::Point_2 const & A2 = seg1.target(); - typename K::Point_2 const & B1 = seg2.source(); - typename K::Point_2 const & B2 = seg2.target(); - typename K::Less_xy_2 less_xy; - typename K::Compare_xy_2 compare_xy; - - if (less_xy(A1,A2)) { - if (less_xy(B1,B2)) { - if (less_xy(A2,B1) - || less_xy(B2,A1)) - return false; - } else { - if (less_xy(A2,B2) - || less_xy(B1,A1)) - return false; - } - } else { - if (less_xy(B1,B2)) { - if (less_xy(A1,B1) - || less_xy(B2,A2)) - return false; - } else { - if (less_xy(A1,B2) - || less_xy(B1,A2)) - return false; - } - } - if (less_xy(A1,A2)) { - if (less_xy(B1,B2)) { - switch(make_certain(compare_xy(A1,B1))) { - case SMALLER: - switch(make_certain(compare_xy(A2,B1))) { - case SMALLER: - return false; - case EQUAL: - return true; - default: // LARGER - switch(make_certain(compare_xy(A2,B2))) { - case SMALLER: - return seg_seg_do_intersect_crossing(A1,A2,B1,B2, k); - case EQUAL: - return true; - default: // LARGER - return seg_seg_do_intersect_contained(A1,A2,B1,B2, k); - } - } - case EQUAL: - return true; - default: // LARGER - switch(make_certain(compare_xy(B2,A1))) { - case SMALLER: - return false; - case EQUAL: - return true; - default: // LARGER - switch(make_certain(compare_xy(B2,A2))) { - case SMALLER: - return seg_seg_do_intersect_crossing(B1,B2,A1,A2, k); - case EQUAL: - return true; - default: // LARGER - return seg_seg_do_intersect_contained(B1,B2,A1,A2, k); - } - } - } - } else { - switch(make_certain(compare_xy(A1,B2))) { - case SMALLER: - switch(make_certain(compare_xy(A2,B2))) { - case SMALLER: - return false; - case EQUAL: - return true; - default: // LARGER - switch(make_certain(compare_xy(A2,B1))) { - case SMALLER: - return seg_seg_do_intersect_crossing(A1,A2,B2,B1, k); - case EQUAL: - return true; - default: // LARGER - return seg_seg_do_intersect_contained(A1,A2,B2,B1, k); - } - } - case EQUAL: - return true; - default: // LARGER - switch(make_certain(compare_xy(B1,A1))) { - case SMALLER: - return false; - case EQUAL: - return true; - default: // LARGER - switch(make_certain(compare_xy(B1,A2))) { - case SMALLER: - return seg_seg_do_intersect_crossing(B2,B1,A1,A2, k); - case EQUAL: - return true; - default: // LARGER - return seg_seg_do_intersect_contained(B2,B1,A1,A2, k); - } - } - } - } - } else { - if (less_xy(B1,B2)) { - switch(make_certain(compare_xy(A2,B1))) { - case SMALLER: - switch(make_certain(compare_xy(A1,B1))) { - case SMALLER: - return false; - case EQUAL: - return true; - default: // LARGER - switch(make_certain(compare_xy(A1,B2))) { - case SMALLER: - return seg_seg_do_intersect_crossing(A2,A1,B1,B2, k); - case EQUAL: - return true; - default: // LARGER - return seg_seg_do_intersect_contained(A2,A1,B1,B2, k); - } - } - case EQUAL: - return true; - default: // LARGER - switch(make_certain(compare_xy(B2,A2))) { - case SMALLER: - return false; - case EQUAL: - return true; - default: // LARGER - switch(make_certain(compare_xy(B2,A1))) { - case SMALLER: - return seg_seg_do_intersect_crossing(B1,B2,A2,A1, k); - case EQUAL: - return true; - default: // LARGER - return seg_seg_do_intersect_contained(B1,B2,A2,A1, k); - } - } - } - } else { - switch(make_certain(compare_xy(A2,B2))) { - case SMALLER: - switch(make_certain(compare_xy(A1,B2))) { - case SMALLER: - return false; - case EQUAL: - return true; - default: // LARGER - switch(make_certain(compare_xy(A1,B1))) { - case SMALLER: - return seg_seg_do_intersect_crossing(A2,A1,B2,B1, k); - case EQUAL: - return true; - default: // LARGER - return seg_seg_do_intersect_contained(A2,A1,B2,B1, k); - } - } - case EQUAL: - return true; - default: // LARGER - switch(make_certain(compare_xy(B1,A2))) { - case SMALLER: - return false; - case EQUAL: - return true; - default: // LARGER - switch(make_certain(compare_xy(B1,A1))) { - case SMALLER: - return seg_seg_do_intersect_crossing(B2,B1,A2,A1, k); - case EQUAL: - return true; - default: // LARGER - return seg_seg_do_intersect_contained(B2,B1,A2,A1, k); - } - } - } - } - } - CGAL_kernel_assertion(false); - return false; + return do_intersect_with_info(seg1, seg2, k, false).inter; } - template class Segment_2_Segment_2_pair { public: @@ -294,110 +330,52 @@ template typename Segment_2_Segment_2_pair::Intersection_results Segment_2_Segment_2_pair::intersection_type() const { - typename K::Construct_vector_2 construct_vector; if (_result!=UNKNOWN) return _result; - if (!internal::do_intersect(*_seg1, *_seg2, K())) { + + S2S2_inter_info inter_info = do_intersect_with_info(*_seg1, *_seg2, K(), true); + + if (!inter_info.inter) { _result = NO_INTERSECTION; return _result; } - typename K::Line_2 const &l1 = _seg1->supporting_line(); - typename K::Line_2 const &l2 = _seg2->supporting_line(); - Line_2_Line_2_pair linepair(&l1, &l2); - switch ( linepair.intersection_type()) { - case Line_2_Line_2_pair::NO_INTERSECTION: - default: - _result = NO_INTERSECTION; - break; - case Line_2_Line_2_pair::POINT: - _intersection_point = linepair.intersection_point(); - _result = POINT; - break; - case Line_2_Line_2_pair::LINE: - { - //typedef typename K::RT RT; - typename K::Point_2 const &start1 = _seg1->source(); - typename K::Point_2 const &end1 = _seg1->target(); - typename K::Point_2 const &start2 = _seg2->source(); - typename K::Point_2 const &end2 = _seg2->target(); - typename K::Vector_2 diff1 = construct_vector(start1, end1); - typename K::Point_2 const *minpt; - typename K::Point_2 const *maxpt; - if (CGAL_NTS abs(diff1.x()) > CGAL_NTS abs(diff1.y())) { - if (start1.x() < end1.x()) { - minpt = &start1; - maxpt = &end1; - } else { - minpt = &end1; - maxpt = &start1; - } - if (start2.x() < end2.x()) { - if (start2.x() > minpt->x()) { - minpt = &start2; - } - if (end2.x() < maxpt->x()) { - maxpt = &end2; - } - } else { - if (end2.x() > minpt->x()) { - minpt = &end2; - } - if (start2.x() < maxpt->x()) { - maxpt = &start2; - } - } - if (maxpt->x() < minpt->x()) { - _result = NO_INTERSECTION; - return _result; - } - if (maxpt->x() == minpt->x()) { - _intersection_point = *minpt; - _result = POINT; - return _result; - } - _intersection_point = *minpt; - _other_point = *maxpt; - _result = SEGMENT; - return _result; - } else { - if (start1.y() < end1.y()) { - minpt = &start1; - maxpt = &end1; - } else { - minpt = &end1; - maxpt = &start1; - } - if (start2.y() < end2.y()) { - if (start2.y() > minpt->y()) { - minpt = &start2; - } - if (end2.y() < maxpt->y()) { - maxpt = &end2; - } - } else { - if (end2.y() > minpt->y()) { - minpt = &end2; - } - if (start2.y() < maxpt->y()) { - maxpt = &start2; - } - } - if (maxpt->y() < minpt->y()) { - _result = NO_INTERSECTION; - return _result; - } - if (maxpt->y() == minpt->y()) { - _intersection_point = *minpt; - _result = POINT; - return _result; - } - _intersection_point = *minpt; - _other_point = *maxpt; - _result = SEGMENT; - return _result; - } - } + + // check if intersection is a segment + if (inter_info.dim==1) + { + _result=SEGMENT; + _intersection_point = (inter_info.pt_ids[0]>1) + ? _seg2->point(inter_info.pt_ids[0]-2) + : _seg1->point(inter_info.pt_ids[0]); + _other_point = inter_info.pt_ids[1]>1 + ? _seg2->point(inter_info.pt_ids[1]-2) + : _seg1->point(inter_info.pt_ids[1]); + return _result; } + + // starting from here we know that the intersection is a point + _result = POINT; + + // check if intersection is an input endpoint + if (inter_info.pt_ids[0]>=0) + { + _intersection_point = (inter_info.pt_ids[0]>1) + ? _seg2->point(inter_info.pt_ids[0]-2) + : _seg1->point(inter_info.pt_ids[0]); + return _result; + } + + // segments intersect in their interiors + typename K::FT s1_dx = _seg1->point(0).x() - _seg1->point(1).x(), + s1_dy = _seg1->point(0).y() - _seg1->point(1).y(), + s2_dx = _seg2->point(1).x() - _seg2->point(0).x(), + s2_dy = _seg2->point(1).y() - _seg2->point(0).y(), + lx = _seg2->point(1).x() - _seg1->point(1).x(), + ly = _seg2->point(1).y() - _seg1->point(1).y(); + + typename K::FT alpha = (lx*s2_dy-ly*s2_dx)/(s1_dx*s2_dy-s1_dy*s2_dx); + _intersection_point = K().construct_barycenter_2_object()(_seg1->point(0), alpha, _seg1->point(1)); + return _result; } diff --git a/Intersections_2/test/Intersections_2/test_intersections_2.cpp b/Intersections_2/test/Intersections_2/test_intersections_2.cpp index 9cde3a3f12e..40c55d26c66 100644 --- a/Intersections_2/test/Intersections_2/test_intersections_2.cpp +++ b/Intersections_2/test/Intersections_2/test_intersections_2.cpp @@ -431,6 +431,56 @@ struct Test check_intersection (S(p( 0, 0), p( 10, 0)), S(p( 1, 0), p( 8, 0)), S(P( 1, 0), P( 8, 0))); check_intersection (S(p(68, 106), p(192, 106)), S(p(150, 106), p(255, 106)), S(P(150, 106), P(192, 106))); check_intersection (S(p( 1, 10), p( 1, 2)), S(p( 1, 7), p( 1, 3)), S(P( 1, 3), P( 1, 7))); + + // exact point intersection + check_intersection (S(p( 3, 0), p( 3, 10)), S(p( 3, 3), p( 5, 10)), p( 3, 3)); + check_intersection (S(p( 3, 0), p( 3, 10)), S(p( 5, 10), p( 3, 3)), p( 3, 3)); + check_intersection (S(p( 3, 0), p( 3, 10)), S(p( 3, 3), p( -5, 10)), p( 3, 3)); + check_intersection (S(p( 3, 0), p( 3, 10)), S(p( -5, 10), p( 3, 3)), p( 3, 3)); + check_intersection (S(p( 0, 0), p( 44, 44)), S(p( 44, 44), p( 55, 55)), p( 44, 44)); + check_intersection (S(p( 0, 0), p( 44, 44)), S(p( 55, 55), p( 44, 44)), p( 44, 44)); + check_intersection (S(p( 44, 44), p( 0, 0)), S(p( 44, 44), p( 55, 55)), p( 44, 44)); + check_intersection (S(p( 44, 44), p( 0, 0)), S(p( 55, 55), p( 44, 44)), p( 44, 44)); + check_intersection (S(p( 0, 0), p( -44, -44)), S(p( -44, -44), p( -55, -55)), p( -44, -44)); + check_intersection (S(p( 0, 0), p( -44, -44)), S(p( -55, -55), p( -44, -44)), p( -44, -44)); + check_intersection (S(p( -44, -44), p( 0, 0)), S(p( -44, -44), p( -55, -55)), p( -44, -44)); + check_intersection (S(p( -44, -44), p( 0, 0)), S(p( -55, -55), p( -44, -44)), p( -44, -44)); + + // more segment intersection (containment) + check_intersection (S(p(0,0), p(4,4)), S(p(1,1), p(2,2)), S(p(1,1), p(2,2))); + check_intersection (S(p(0,0), p(4,4)), S(p(2,2), p(1,1)), S(p(1,1), p(2,2))); + check_intersection (S(p(4,4), p(0,0)), S(p(1,1), p(2,2)), S(p(1,1), p(2,2))); + check_intersection (S(p(4,4), p(0,0)), S(p(2,2), p(1,1)), S(p(1,1), p(2,2))); + + // more segment intersection (overlap) + check_intersection (S(p( 0,0), p( 2,2)), S(p(1,1), p(4,4)), S(p(1,1), p(2,2))); + check_intersection (S(p( 0,0), p( 2,2)), S(p(4,4), p(1,1)), S(p(1,1), p(2,2))); + check_intersection (S(p( 2,2), p( 0,0)), S(p(1,1), p(4,4)), S(p(1,1), p(2,2))); + check_intersection (S(p( 2,2), p( 0,0)), S(p(4,4), p(1,1)), S(p(1,1), p(2,2))); + check_intersection (S(p( 0,0), p( -2,-2)), S(p(-1,-1), p(-4,-4)), S(p(-2,-2),p(-1,-1))); + check_intersection (S(p( 0,0), p( -2,-2)), S(p(-4,-4), p(-1,-1)), S(p(-2,-2),p(-1,-1))); + check_intersection (S(p( -2,-2), p( 0,0)), S(p(-1,-1), p(-4,-4)), S(p(-2,-2),p(-1,-1))); + check_intersection (S(p( -2,-2), p( 0,0)), S(p(-4,-4), p(-1,-1)), S(p(-2,-2),p(-1,-1))); + + // more segment intersection (one common point) + check_intersection (S(p( 0,0), p( 2,2)), S(p(1,1), p(2,2)), S(p(1,1), p(2,2))); + check_intersection (S(p( 0,0), p( 2,2)), S(p(2,2), p(1,1)), S(p(1,1), p(2,2))); + check_intersection (S(p( 2,2), p( 0,0)), S(p(1,1), p(2,2)), S(p(1,1), p(2,2))); + check_intersection (S(p( 2,2), p( 0,0)), S(p(2,2), p(1,1)), S(p(1,1), p(2,2))); + check_intersection (S(p( 0,0), p( -2,-2)), S(p(-1,-1), p(-2,-2)), S(p(-2,-2),p(-1,-1))); + check_intersection (S(p( 0,0), p( -2,-2)), S(p(-2,-2), p(-1,-1)), S(p(-2,-2),p(-1,-1))); + check_intersection (S(p( -2,-2), p( 0,0)), S(p(-1,-1), p(-2,-2)), S(p(-2,-2),p(-1,-1))); + check_intersection (S(p( -2,-2), p( 0,0)), S(p(-2,-2), p(-1,-1)), S(p(-2,-2),p(-1,-1))); + + // more segment intersection (two identical points) + check_intersection (S(p( 1,1), p( 2,2)), S(p(1,1), p(2,2)), S(p(1,1), p(2,2))); + check_intersection (S(p( 1,1), p( 2,2)), S(p(2,2), p(1,1)), S(p(1,1), p(2,2))); + check_intersection (S(p( 2,2), p( 1,1)), S(p(1,1), p(2,2)), S(p(1,1), p(2,2))); + check_intersection (S(p( 2,2), p( 1,1)), S(p(2,2), p(1,1)), S(p(1,1), p(2,2))); + check_intersection (S(p( -1,-1), p( -2,-2)), S(p(-1,-1), p(-2,-2)), S(p(-2,-2),p(-1,-1))); + check_intersection (S(p( -1,-1), p( -2,-2)), S(p(-2,-2), p(-1,-1)), S(p(-2,-2),p(-1,-1))); + check_intersection (S(p( -2,-2), p( -1,-1)), S(p(-1,-1), p(-2,-2)), S(p(-2,-2),p(-1,-1))); + check_intersection (S(p( -2,-2), p( -1,-1)), S(p(-2,-2), p(-1,-1)), S(p(-2,-2),p(-1,-1))); } void R_R() diff --git a/STL_Extension/include/CGAL/assertions.h b/STL_Extension/include/CGAL/assertions.h index 90ea7557ed6..45d513d9f5f 100644 --- a/STL_Extension/include/CGAL/assertions.h +++ b/STL_Extension/include/CGAL/assertions.h @@ -106,6 +106,12 @@ inline bool possibly(Uncertain c); # define CGAL_assume_code(CODE) CGAL_assertion_code(CODE) #endif // no CGAL_NO_ASSERTIONS +# ifdef CGAL_UNREACHABLE +# define CGAL_unreachable() CGAL_UNREACHABLE() +# else // not def CGAL_UNREACHABLE +# define CGAL_unreachable() CGAL_assertion(false) +# endif // CGAL_UNREACHABLE + # define CGAL_static_assertion(EX) \ static_assert(EX, #EX) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 375b8096617..eb1fa780be4 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -144,7 +144,7 @@ bool test(const DT& dt, break; } default: - CGAL_assume(false); + CGAL_unreachable(); } // end switch } } diff --git a/Visibility_2/include/CGAL/Rotational_sweep_visibility_2.h b/Visibility_2/include/CGAL/Rotational_sweep_visibility_2.h index 521565ba3bb..2ee98969576 100644 --- a/Visibility_2/include/CGAL/Rotational_sweep_visibility_2.h +++ b/Visibility_2/include/CGAL/Rotational_sweep_visibility_2.h @@ -120,7 +120,7 @@ private: return 1; case LEFT_TURN: return 2; - default: CGAL_assume(false); + default: CGAL_unreachable(); } return -1; } @@ -215,7 +215,7 @@ private: == Visibility_2::orientation_2(geom_traits, s2, t2, s1); else return true; - default: CGAL_assume(false); + default: CGAL_unreachable(); } break; case LEFT_TURN: @@ -234,11 +234,11 @@ private: == Visibility_2::orientation_2(geom_traits, s2, t2, s1); else return true; - default: CGAL_assume(false); + default: CGAL_unreachable(); } } - CGAL_assume(false); + CGAL_unreachable(); return false; }