update from master branch

This commit is contained in:
Sébastien Loriot 2021-06-17 17:45:25 +02:00
commit fc40a2760f
2 changed files with 135 additions and 7 deletions

View File

@ -190,6 +190,7 @@ public:
{
CGAL_PROFILER("Projected_intersect_3::operator()")
CGAL_TIME_PROFILER("Projected_intersect_3::operator()")
typedef boost::variant<Point, Segment> variant_type;
const Vector_3 u1 = cross_product(s1.to_vector(), normal);
if(u1 == NULL_VECTOR)
return K().intersect_3_object()(s1.supporting_line(), s2);
@ -203,21 +204,29 @@ public:
auto planes_intersection = intersection(plane_1, plane_2);
if(! planes_intersection) {
#ifdef CGAL_T2_PTB_3_DEBUG
std::cerr << "planes_intersection is empty\n";
#endif
return boost::none;
}
if(const Line* line = boost::get<Line>(&*planes_intersection))
{
// check if the intersection line intersects both segments by
// checking if a point on the intersection line is between
// the segments endpoints
const Point& pi = line->point(0);
if(cross_product(normal, pi - s1.source())
if( cross_product(normal, pi - s1.source())
* cross_product(normal, pi - s1.target()) > FT(0)
||
cross_product(normal, pi - s2.source())
* cross_product(normal, pi - s2.target()) > FT(0) )
{
// the intersection of the lines is not inside the segments
// the intersection of the supporting lines is not inside both segments
#ifdef CGAL_T2_PTB_3_DEBUG
std::cerr << "intersection not inside\n";
return boost::none;
#endif
return boost::none;
}
else
{
@ -231,15 +240,66 @@ public:
return boost::none;
}
if(const Point* point = boost::get<Point>(&*inter)){
typedef boost::variant<Point, Segment> variant_type;
return boost::make_optional(variant_type(*point));
}
}
}
if(boost::get<Plane_3>(&*planes_intersection))
{
std::cerr << "coplanar lines\n";
CGAL_error();
#ifdef CGAL_T2_PTB_3_DEBUG
std::cerr << "coplanar supporting lines\n";
#endif
auto is_inside_segment = [](const Segment& s, const Point& q)
{
return Vector_3(q,s.source()) * Vector_3(q,s.target()) <=0;
};
bool src2_in_s1 = is_inside_segment(s1, s2.source());
bool tgt2_in_s1 = is_inside_segment(s1, s2.target());
bool src1_in_s2 = is_inside_segment(s2, s1.source());
bool tgt1_in_s2 = is_inside_segment(s2, s1.target());
if (src1_in_s2 && tgt1_in_s2) return boost::make_optional(variant_type(s1));
if (src2_in_s1 && tgt2_in_s1) return boost::make_optional(variant_type(s2));
if (src1_in_s2)
{
if (src2_in_s1)
{
if (cross_product(normal, Vector_3(s1.source(), s2.source())) != NULL_VECTOR)
return boost::make_optional(variant_type(Segment(s1.source(), s2.source())));
else
return boost::make_optional(variant_type((s1.source())));
}
if (tgt2_in_s1)
{
if (cross_product(normal, Vector_3(s1.source(), s2.target())) != NULL_VECTOR)
return boost::make_optional(variant_type(Segment(s1.source(), s2.target())));
else
return boost::make_optional(variant_type(s1.source()));
}
// should never get here with a Kernel with exact constructions
return boost::make_optional(variant_type(s1.source()));
}
if (tgt1_in_s2)
{
if (src2_in_s1)
{
if (cross_product(normal, Vector_3(s1.target(), s2.source())) != NULL_VECTOR)
return boost::make_optional(variant_type(Segment(s1.target(), s2.source())));
else
return boost::make_optional(variant_type(s1.target()));
}
if (tgt2_in_s1)
{
if (cross_product(normal, Vector_3(s1.target(), s2.target())) != NULL_VECTOR)
return boost::make_optional(variant_type(Segment(s1.target(), s2.target())));
else
return boost::make_optional(variant_type(s1.target()));
}
// should never get here with a Kernel with exact constructions
return boost::make_optional(variant_type(s1.target()));
}
return boost::none;
}
return boost::none;

View File

@ -60,6 +60,67 @@ bool test(std::string test_name)
return cdt.is_valid();
}
template <class K, typename CDT_2_traits>
bool test_segment_intersections(std::string test_name)
{
std::cerr << "Testing " << test_name << std::endl;
CDT_2_traits traits(typename K::Vector_3(0,0,1));
typename CDT_2_traits::Intersect_2 intersect = traits.intersect_2_object();
typedef typename CDT_2_traits::Segment_2 Segment_2;
typedef typename CDT_2_traits::Point_2 Point_2;
// test point intersection
Segment_2 s1( Point_2(0,0,0), Point_2(1,1,0) ),
s2( Point_2(0,1,0), Point_2(1,0,0) );
CGAL::Object o = intersect(s1,s2);
assert( o.is<Point_2>() );
// test segment overlap
Point_2 pts[4] = { Point_2(0,0,0), Point_2(1,0,1), Point_2(2,0,2), Point_2(4,0,3) };
o = intersect( Segment_2(pts[0], pts[1]), Segment_2(pts[2], pts[3]) );
assert( o.empty() );
// pure overlap
o = intersect( Segment_2(pts[0], pts[2]), Segment_2(pts[1], pts[3]) );
assert( o.is<Segment_2>() );
o = intersect( Segment_2(pts[0], pts[2]), Segment_2(pts[3], pts[1]) );
assert( o.is<Segment_2>() );
o = intersect( Segment_2(pts[2], pts[0]), Segment_2(pts[1], pts[3]) );
assert( o.is<Segment_2>() );
o = intersect( Segment_2(pts[2], pts[0]), Segment_2(pts[3], pts[1]) );
assert( o.is<Segment_2>() );
// segment fully included
o = intersect( Segment_2(pts[0], pts[3]), Segment_2(pts[1], pts[2]) );
assert( o.is<Segment_2>() );
assert( CGAL::object_cast<Segment_2>(o) == Segment_2(pts[1], pts[2]) );
// segment fully included with shared vertex
o = intersect( Segment_2(pts[0], pts[1]), Segment_2(pts[0], pts[2]) );
assert( o.is<Segment_2>() );
assert( CGAL::object_cast<Segment_2>(o) == Segment_2(pts[0], pts[1]) );
// segment sharing a vertex
o = intersect( Segment_2(pts[0], pts[1]), Segment_2(pts[1], pts[2]) );
assert( o.is<Point_2>() );
assert( CGAL::object_cast<Point_2>(o) == pts[1]);
// degenerate segment
Segment_2 sd(Point_2(1,0,6), Point_2(1,0,7));
o = intersect( Segment_2(pts[0], pts[2]), sd );
assert( o.is<Point_2>() );
o = intersect( Segment_2(pts[0], pts[1]), sd );
assert( o.is<Point_2>() );
o = intersect( Segment_2(pts[1], pts[0]), sd );
assert( o.is<Point_2>() );
o = intersect( Segment_2(pts[2], pts[3]), sd );
assert( o.empty() );
return true;
}
int main()
{
std::cerr.precision(17);
@ -75,5 +136,12 @@ int main()
test<CGAL::Epeck,
CGAL::Triangulation_2_projection_traits_3<Epeck> >
("CDT_2 in a 3D plane, with Epeck");
ok = ok && test_segment_intersections<CGAL::Epick,
CGAL::Triangulation_2_projection_traits_3<Epick> >
("CDT_2 traits intersection with Epick");
ok = ok && test_segment_intersections<CGAL::Epeck,
CGAL::Triangulation_2_projection_traits_3<Epeck> >
("CDT_2 traits intersection with Epeck");
return ok ? 0 : 1;
}