Merge pull request #5244 from afabri/Triangulation_2-Intersect_use_variant-GF

Nef_3, Triangulation_2:  Change the result type of the Intersect_2 functor
This commit is contained in:
Laurent Rineau 2021-02-05 16:12:58 +01:00
commit 3bd7181ff3
8 changed files with 174 additions and 108 deletions

View File

@ -77,7 +77,7 @@ typedef Line_3<K> Line_2;
A construction object.
Provides the operator :
`Object_2 operator()(Segment_2 s1, Segment_2 s2);`
`boost::optional< boost::variant<Point_2,Segment_2> > operator()(Segment_2 s1, Segment_2 s2);`
which returns a 3D object whose projection on the xy-plane
is the intersection of the projections of `s1` and `s2`.
If non empty, the returned object is either a segment or a point.

View File

@ -308,8 +308,13 @@ public:
return (CGAL::abs(dx)>CGAL::abs(dy)) ? ( p.x()-source.x() ) / dx : (p.y()-source.y() ) / dy;
}
Object operator()(const Segment_3& s1, const Segment_3& s2) const
boost::optional< boost::variant<Point_3,Segment_3> >
operator()(const Segment_3& s1, const Segment_3& s2) const
{
typedef boost::variant<Point_3, Segment_3> variant_type;
Point_2 s1_source = project(s1.source());
Point_2 s1_target = project(s1.target());
Point_2 s2_source = project(s2.source());
@ -321,11 +326,14 @@ public:
//compute intersection points in projected plane
//We know that none of the segment is degenerate
Object o = intersection(s1_2,s2_2);
const Point_2* pi=CGAL::object_cast<Point_2>(&o);
if (pi==nullptr) { //case of segment or empty
const Segment_2* si=CGAL::object_cast<Segment_2>(&o);
if (si==nullptr) return Object();
typename CGAL::cpp11::result_of<typename R::Intersect_2(Segment_2, Segment_2)>::type
o = intersection(s1_2,s2_2);
if(! o){
return boost::none;
}
if(const Segment_2* si = boost::get<Segment_2>(&*o)){
FT src[3],tgt[3];
//the third coordinate is the midpoint between the points on s1 and s2
FT z1 = s1.source()[dim] + ( alpha(si->source(), s1_source, s1_target) * ( s1.target()[dim] - s1.source()[dim] ));
@ -343,8 +351,11 @@ public:
src[Projector<R,dim>::y_index] = si->source().y();
tgt[Projector<R,dim>::x_index] = si->target().x();
tgt[Projector<R,dim>::y_index] = si->target().y();
return make_object( Segment_3( Point_3(src[0],src[1],src[2]),Point_3(tgt[0],tgt[1],tgt[2]) ) );
return boost::make_optional(variant_type(Segment_3( Point_3(src[0],src[1],src[2]),Point_3(tgt[0],tgt[1],tgt[2]) ) ) );
}
const Point_2* pi = boost::get<Point_2>(&*o);
FT coords[3];
//compute the third coordinate of the projected intersection point onto 3D segments
FT z1 = s1.source()[dim] + ( alpha(*pi, s1_source, s1_target) * ( s1.target()[dim] - s1.source()[dim] ));
@ -356,7 +367,7 @@ public:
Point_3 res(coords[0],coords[1],coords[2]);
CGAL_assertion(x(res)==pi->x() && y(res)==pi->y());
return make_object(res);
return boost::make_optional(variant_type(res));
}
};

View File

@ -34,7 +34,10 @@ struct Exact_intersect_xy_2 <R,Cartesian_tag>
typedef typename R::Point_3 Point_3;
typedef typename R::Segment_3 Segment_3;
CGAL::Object operator() (Segment_3 s3, Segment_3 t3)
typedef boost::variant<Point_3, Segment_3> variant_type;
boost::optional<variant_type>
operator() (const Segment_3& s3, const Segment_3& t3)
{ Point_2 p2, q2;
Point_3 p3, q3;
@ -50,17 +53,21 @@ struct Exact_intersect_xy_2 <R,Cartesian_tag>
// convert intersection from Object_2 to Object_3
// Note: there is not necessarily a spartial intersection,
// so all third components are faked!
CGAL::Object obj = intersection (s2,t2);
if ( CGAL::assign(p2, obj) )
{ obj = make_object (Point_3 (p2.x(),p2.y(),0));
auto obj = intersection (s2,t2);
if(! obj){
return boost::none;
}
else if ( CGAL::assign(s2, obj) )
{ p2 = s2.source();
q2 = s2.target();
obj = make_object( Segment_3(
Point_3(p2.x(),p2.y(),0), Point_3(q2.x(),q2.y(),0) ) );
if (const Point_2* pi = boost::get<Point_2>(&*obj))
{
return boost::make_optional(variant_type(Point_3(p2.x(),p2.y(),0)));
}
return obj;
const Segment_2* si = boost::get<Segment_2>(&*obj);
p2 = si->source();
q2 = si->target();
return boost::make_optional(variant_type(Segment_3(Point_3(p2.x(),p2.y(),0),
Point_3(q2.x(),q2.y(),0) ) ));
}
};
@ -73,7 +80,9 @@ struct Exact_intersect_xy_2 <R,Homogeneous_tag>
typedef typename R::Point_3 Point_3;
typedef typename R::Segment_3 Segment_3;
CGAL::Object operator() (Segment_3 s3, Segment_3 t3)
typedef boost::variant<Point_3, Segment_3> variant_type;
boost::optional<variant_type> operator() (Segment_3 s3, Segment_3 t3)
{ Point_2 p2, q2;
Point_3 p3, q3;
@ -91,18 +100,21 @@ struct Exact_intersect_xy_2 <R,Homogeneous_tag>
// convert intersection from Object_2 to Object_3
// Note: there is not necessarily a spartial intersection,
// so all third components are faked!
CGAL::Object obj = intersection (s2,t2);
if ( CGAL::assign(p2, obj) )
{ obj = make_object (Point_3 (p2.hx(),p2.hy(),0,p2.hw()));
auto obj = intersection (s2,t2);
if(! obj){
return boost::none;
}
else if ( CGAL::assign(s2, obj) )
{ p2 = s2.source();
q2 = s2.target();
obj = make_object( Segment_3(
Point_3 (p2.hx(),p2.hy(),0,p2.hw()),
Point_3 (q2.hx(),q2.hy(),0,q2.hw()) ) );
if (const Point_2* pi = boost::get<Point_2>(&*obj))
{
return boost::make_optional(variant_type(Point_3(p2.hx(),p2.hy(),0,p2.hw())));
}
return obj;
const Segment_2* si = boost::get<Segment_2>(&*obj);
p2 = si->source();
q2 = si->target();
return boost::make_optional(variant_type(Segment_3(Point_3 (p2.hx(),p2.hy(),0,p2.hw()),
Point_3 (q2.hx(),q2.hy(),0,q2.hw())) ));
}
};

View File

@ -33,7 +33,10 @@ struct Exact_intersect_xz_2 <R,Cartesian_tag>
typedef typename R::Point_3 Point_3;
typedef typename R::Segment_3 Segment_3;
CGAL::Object operator() (Segment_3 s3, Segment_3 t3)
typedef boost::variant<Point_3, Segment_3> variant_type;
boost::optional<variant_type>
operator() (const Segment_3& s3, const Segment_3& t3)
{ Point_2 p2, q2;
Point_3 p3, q3;
@ -48,18 +51,22 @@ struct Exact_intersect_xz_2 <R,Cartesian_tag>
// convert intersection from Object_2 to Object_3
// Note: there is not necessarily a spartial intersection,
// so all second components are faked!
CGAL::Object obj = intersection (s2,t2);
if ( CGAL::assign(p2, obj) )
{ obj = make_object (Point_3 (p2.x(),0,p2.y()));
// so all third components are faked!
auto obj = intersection (s2,t2);
if(! obj){
return boost::none;
}
else if ( CGAL::assign(s2, obj) )
{ p2 = s2.source();
q2 = s2.target();
obj = make_object( Segment_3(
Point_3(p2.x(),0,p2.y()), Point_3(q2.x(),0,q2.y()) ) );
if (const Point_2* pi = boost::get<Point_2>(&*obj))
{
return boost::make_optional(variant_type(Point_3(p2.x(),0,p2.y())));
}
return obj;
const Segment_2* si = boost::get<Segment_2>(&*obj);
p2 = si->source();
q2 = si->target();
return boost::make_optional(variant_type(Segment_3(Point_3(p2.x(),0,p2.y()),
Point_3(q2.x(),0,q2.y()) ) ));
}
};
@ -72,7 +79,9 @@ struct Exact_intersect_xz_2 <R,Homogeneous_tag>
typedef typename R::Point_3 Point_3;
typedef typename R::Segment_3 Segment_3;
CGAL::Object operator() (Segment_3 s3, Segment_3 t3)
typedef boost::variant<Point_3, Segment_3> variant_type;
boost::optional<variant_type> operator() (Segment_3 s3, Segment_3 t3)
{ Point_2 p2, q2;
Point_3 p3, q3;
@ -89,20 +98,24 @@ struct Exact_intersect_xz_2 <R,Homogeneous_tag>
// convert intersection from Object_2 to Object_3
// Note: there is not necessarily a spartial intersection,
// so all second components are faked!
CGAL::Object obj = intersection (s2,t2);
if ( CGAL::assign(p2, obj) )
{ obj = make_object (Point_3 (p2.hx(),0,p2.hy(),p2.hw()));
// so all third components are faked!
auto obj = intersection (s2,t2);
if(! obj){
return boost::none;
}
else if ( CGAL::assign(s2, obj) )
{ p2 = s2.source();
q2 = s2.target();
obj = make_object( Segment_3(
Point_3 (p2.hx(),0,p2.hy(),p2.hw()),
Point_3 (q2.hx(),0,q2.hy(),q2.hw()) ) );
if (const Point_2* pi = boost::get<Point_2>(&*obj))
{
return boost::make_optional(variant_type(Point_3(p2.hx(),0,p2.hy(),p2.hw())));
}
return obj;
const Segment_2* si = boost::get<Segment_2>(&*obj);
p2 = si->source();
q2 = si->target();
return boost::make_optional(variant_type(Segment_3(Point_3 (p2.hx(),0,p2.hy(),p2.hw()),
Point_3 (q2.hx(),0,q2.hy(),q2.hw())) ));
}
};
template <class R>

View File

@ -34,7 +34,10 @@ struct Exact_intersect_yz_2 <R,Cartesian_tag>
typedef typename R::Point_3 Point_3;
typedef typename R::Segment_3 Segment_3;
CGAL::Object operator() (Segment_3 s3, Segment_3 t3)
typedef boost::variant<Point_3, Segment_3> variant_type;
boost::optional<variant_type>
operator() (const Segment_3& s3, const Segment_3& t3)
{ Point_2 p2, q2;
Point_3 p3, q3;
@ -49,18 +52,22 @@ struct Exact_intersect_yz_2 <R,Cartesian_tag>
// convert intersection from Object_2 to Object_3
// Note: there is not necessarily a spartial intersection,
// so all first components are faked!
CGAL::Object obj = intersection (s2,t2);
if ( CGAL::assign(p2, obj) )
{ obj = make_object (Point_3 (0,p2.x(),p2.y()));
// so all third components are faked!
auto obj = intersection (s2,t2);
if(! obj){
return boost::none;
}
else if ( CGAL::assign(s2, obj) )
{ p2 = s2.source();
q2 = s2.target();
obj = make_object( Segment_3(
Point_3(0,p2.x(),p2.y()), Point_3(0,q2.x(),q2.y()) ) );
if (const Point_2* pi = boost::get<Point_2>(&*obj))
{
return boost::make_optional(variant_type(Point_3(0,p2.x(),p2.y())));
}
return obj;
const Segment_2* si = boost::get<Segment_2>(&*obj);
p2 = si->source();
q2 = si->target();
return boost::make_optional(variant_type(Segment_3(Point_3(0,p2.x(),p2.y()),
Point_3(0,q2.x(),q2.y()) ) ));
}
};
@ -73,7 +80,9 @@ struct Exact_intersect_yz_2 <R,Homogeneous_tag>
typedef typename R::Point_3 Point_3;
typedef typename R::Segment_3 Segment_3;
CGAL::Object operator() (Segment_3 s3, Segment_3 t3)
typedef boost::variant<Point_3, Segment_3> variant_type;
boost::optional<variant_type> operator() (Segment_3 s3, Segment_3 t3)
{ Point_2 p2, q2;
Point_3 p3, q3;
@ -90,19 +99,22 @@ struct Exact_intersect_yz_2 <R,Homogeneous_tag>
// convert intersection from Object_2 to Object_3
// Note: there is not necessarily a spartial intersection,
// so all first components are faked!
CGAL::Object obj = intersection (s2,t2);
if ( CGAL::assign(p2, obj) )
{ obj = make_object (Point_3 (0,p2.hx(),p2.hy(),p2.hw()));
// so all third components are faked!
auto obj = intersection (s2,t2);
if(! obj){
return boost::none;
}
else if ( CGAL::assign(s2, obj) )
{ p2 = s2.source();
q2 = s2.target();
obj = make_object( Segment_3(
Point_3 (0,p2.hx(),p2.hy(),p2.hw()),
Point_3 (0,q2.hx(),q2.hy(),q2.hw()) ) );
if (const Point_2* pi = boost::get<Point_2>(&*obj))
{
return boost::make_optional(variant_type(Point_3(0,p2.hx(),p2.hy(),p2.hw())));
}
return obj;
const Segment_2* si = boost::get<Segment_2>(&*obj);
p2 = si->source();
q2 = si->target();
return boost::make_optional(variant_type(Segment_3(Point_3 (0,p2.hx(),p2.hy(),p2.hw()),
Point_3 (0,q2.hx(),q2.hy(),q2.hw())) ));
}
};

View File

@ -39,7 +39,7 @@ public:
/*!
A function object whose `operator()` computes the intersection of two segments.
`Object_2 operator()(Segment_2 s1, Segment_2 s2);`
`boost:optional<boost::variant<Point_2,Segment_2> > operator()(Segment_2 s1, Segment_2 s2);`
Returns the intersection of `s1` and `s2`.
*/
typedef unspecified_type Intersect_2;
@ -113,4 +113,3 @@ compute_squared_distance_2_object();
/// @}
}; /* end ConstrainedTriangulationTraits_2 */

View File

@ -1710,23 +1710,34 @@ compute_intersection(const Gt& gt,
const typename Gt::Point_2& pd,
typename Gt::Point_2& pi)
{
typename Gt::Intersect_2 compute_intersec=gt.intersect_2_object();
typename Gt::Construct_segment_2
construct_segment=gt.construct_segment_2_object();
Object result = compute_intersec(construct_segment(pa,pb),
typedef typename Gt::Point_2 Point_2;
typename Gt::Intersect_2 compute_intersec = gt.intersect_2_object();
typename Gt::Construct_segment_2 construct_segment = gt.construct_segment_2_object();
auto // CGAL::cpp11::result_of<typename Gt::Intersect_2(Segment_2, Segment_2)>::type
result = compute_intersec(construct_segment(pa,pb),
construct_segment(pc,pd));
#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
typename Gt::Segment_2 s;
if(assign(s, result)) {
typedef typename Gt::Segment_2 Segment_2;
if(result){
if (const Segment_2* s = boost::get<Segment_2>(&*result)){
std::cerr << CGAL::internal::cdt_2_indent_level
<< "compute_intersection: " << s << '\n';
}
if(assign(pi, result)) {
<< "compute_intersection: " << *s << '\n';
}else if(const Point_2* p = boost::get<Point_2 >(&*result))
std::cerr << CGAL::internal::cdt_2_indent_level
<< "compute_intersection: " << pi << '\n';
<< "compute_intersection: " << *p << '\n';
}
#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
return assign(pi, result);
if(result){
if(const Point_2* p = boost::get<Point_2 >(&*result)){
pi = *p;
return true;
}
}
return false;
}

View File

@ -185,7 +185,8 @@ public:
CGAL_TIME_PROFILER("Construct Projected_intersect_3")
}
Object operator()(const Segment& s1, const Segment& s2)
boost::optional<boost::variant<Point,Segment> >
operator()(const Segment& s1, const Segment& s2)
{
CGAL_PROFILER("Projected_intersect_3::operator()")
CGAL_TIME_PROFILER("Projected_intersect_3::operator()")
@ -200,12 +201,12 @@ public:
const Plane_3 plane_1(s1.source(), u1);
const Plane_3 plane_2(s2.source(), u2);
Object planes_intersection = intersection(plane_1, plane_2);
if(planes_intersection.empty()) {
auto planes_intersection = intersection(plane_1, plane_2);
if(! planes_intersection) {
std::cerr << "planes_intersection is empty\n";
return planes_intersection;
return boost::none;
}
if(const Line* line = object_cast<Line>(&planes_intersection))
if(const Line* line = boost::get<Line>(&*planes_intersection))
{
const Point& pi = line->point(0);
if(cross_product(normal, pi - s1.source())
@ -216,25 +217,32 @@ public:
{
// the intersection of the lines is not inside the segments
std::cerr << "intersection not inside\n";
return Object();
return boost::none;
}
else
{
// Let the plane passing through s1.source() and with normal
// the cross product of s1.to_vector() and s2.to_vector(). That
// plane should intersect *l, now.
return intersection(*line, Plane_3(s1.source(),
auto inter = intersection(*line, Plane_3(s1.source(),
cross_product(s1.to_vector(),
s2.to_vector())));
if(! inter){
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(object_cast<Plane_3>(&planes_intersection))
}
if(boost::get<Plane_3>(&*planes_intersection))
{
std::cerr << "coplanar lines\n";
CGAL_error();
return Object();
return boost::none;
}
return Object();
return boost::none;
}
}; // end class Projected_intersect_3