Merge pull request #6052 from sloriot/Intersection_2-segment_segment_inter_info

Improve 2D segment intersection
This commit is contained in:
Laurent Rineau 2021-10-29 16:59:47 +02:00
commit 90381147f2
10 changed files with 391 additions and 355 deletions

View File

@ -186,7 +186,7 @@ generate_point() {
this->d_item = creator( T( this->d_range), T(d));
break;
default:
CGAL_assume(false);
CGAL_unreachable();
}
}

View File

@ -856,7 +856,7 @@ Aff_transformation_repH2<R>::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<R>::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<R>::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<R>::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<R>::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<R>::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<R>::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<R>::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<R>::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);
}

View File

@ -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<R>::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<R>::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<R>::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<R>::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;
}

View File

@ -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 <CGAL/assertions.h>

View File

@ -125,7 +125,7 @@ Segment_2_Line_2_pair<K>::intersection_type() const
_result = SEGMENT;
break;
default:
CGAL_assume(false);
CGAL_unreachable();
}
return _result;
}

View File

@ -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<int, 2> 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 <class K>
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 <class K>
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 <class K>
template <class K>
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 <class K>
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 <class K>
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 <class K>
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 K>
class Segment_2_Segment_2_pair {
public:
@ -294,110 +330,52 @@ template <class K>
typename Segment_2_Segment_2_pair<K>::Intersection_results
Segment_2_Segment_2_pair<K>::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<K> linepair(&l1, &l2);
switch ( linepair.intersection_type()) {
case Line_2_Line_2_pair<K>::NO_INTERSECTION:
default:
_result = NO_INTERSECTION;
break;
case Line_2_Line_2_pair<K>::POINT:
_intersection_point = linepair.intersection_point();
_result = POINT;
break;
case Line_2_Line_2_pair<K>::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;
}

View File

@ -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()

View File

@ -106,6 +106,12 @@ inline bool possibly(Uncertain<bool> 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)

View File

@ -144,7 +144,7 @@ bool test(const DT& dt,
break;
}
default:
CGAL_assume(false);
CGAL_unreachable();
} // end switch
}
}

View File

@ -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;
}