IGL_INLINE bool igl::copyleft::cgal::triangle_triangle_squared_distance( const CGAL::Triangle_3<Kernel> & T1, const CGAL::Triangle_3<Kernel> & T2, CGAL::Point_3<Kernel> & P1, CGAL::Point_3<Kernel> & P2, typename Kernel::FT & d) { typedef CGAL::Point_3<Kernel> Point_3; typedef CGAL::Vector_3<Kernel> Vector_3; typedef CGAL::Triangle_3<Kernel> Triangle_3; typedef CGAL::Segment_3<Kernel> Segment_3; typedef typename Kernel::FT EScalar; assert(!T1.is_degenerate()); assert(!T2.is_degenerate()); bool unique = true; if(CGAL::do_intersect(T1,T2)) { // intersecting triangles have zero (squared) distance CGAL::Object result = CGAL::intersection(T1,T2); // Some point on the intersection result CGAL::Point_3<Kernel> Q; if(const Point_3 * p = CGAL::object_cast<Point_3 >(&result)) { Q = *p; }else if(const Segment_3 * s = CGAL::object_cast<Segment_3 >(&result)) { unique = false; Q = s->source(); }else if(const Triangle_3 *itri = CGAL::object_cast<Triangle_3 >(&result)) { Q = s->vertex(0); unique = false; }else if(const std::vector<Point_3 > *polyp = CGAL::object_cast< std::vector<Point_3 > >(&result)) { assert(polyp->size() > 0 && "intersection poly should not be empty"); Q = polyp[0]; unique = false; }else { assert(false && "Unknown intersection result"); } P1 = Q; P2 = Q; d = 0; return unique; } // triangles do not intersect: the points of closest approach must be on the // boundary of one of the triangles d = std::numeric_limits<double>::infinity(); const auto & vertices_face = [&unique]( const Triangle_3 & T1, const Triangle_3 & T2, Point_3 & P1, Point_3 & P2, EScalar & d) { for(int i = 0;i<3;i++) { const Point_3 vi = T1.vertex(i); Point_3 P2i; EScalar di; point_triangle_squared_distance(vi,T2,P2i,di); if(di<d) { d = di; P1 = vi; P2 = P2i; unique = true; }else if(d == di) { // edge of T1 floating parallel above T2 unique = false; } } }; vertices_face(T1,T2,P1,P2,d); vertices_face(T2,T1,P1,P2,d); for(int i = 0;i<3;i++) { const Segment_3 s1( T1.vertex(i+1), T1.vertex(i+2)); for(int j = 0;j<3;j++) { const Segment_3 s2( T2.vertex(i+1), T2.vertex(i+2)); Point_3 P1ij; Point_3 P2ij; EScalar dij; bool uniqueij = segment_segment_squared_distance(s1,s2,P1ij,P2ij,dij); if(dij < d) { P1 = P1ij; P2 = P2ij; d = dij; unique = uniqueij; } } } return unique; }
IGL_INLINE void igl::cgal::projected_delaunay( const CGAL::Triangle_3<Kernel> & A, const std::vector<CGAL::Object> & A_objects_3, CGAL::Constrained_triangulation_plus_2< CGAL::Constrained_Delaunay_triangulation_2< Kernel, CGAL::Triangulation_data_structure_2< CGAL::Triangulation_vertex_base_2<Kernel>, CGAL::Constrained_triangulation_face_base_2<Kernel> >, CGAL::Exact_intersections_tag> > & cdt) { using namespace std; // 3D Primitives typedef CGAL::Point_3<Kernel> Point_3; typedef CGAL::Segment_3<Kernel> Segment_3; typedef CGAL::Triangle_3<Kernel> Triangle_3; typedef CGAL::Plane_3<Kernel> Plane_3; //typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3; typedef CGAL::Point_2<Kernel> Point_2; //typedef CGAL::Segment_2<Kernel> Segment_2; //typedef CGAL::Triangle_2<Kernel> Triangle_2; typedef CGAL::Triangulation_vertex_base_2<Kernel> TVB_2; typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2; typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2; typedef CGAL::Exact_intersections_tag Itag; typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> CDT_2; typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2; // http://www.cgal.org/Manual/3.2/doc_html/cgal_manual/Triangulation_2/Chapter_main.html#Section_2D_Triangulations_Constrained_Plus // Plane of triangle A Plane_3 P(A.vertex(0),A.vertex(1),A.vertex(2)); // Insert triangle into vertices typename CDT_plus_2::Vertex_handle corners[3]; typedef size_t Index; for(Index i = 0;i<3;i++) { const Point_3 & p3 = A.vertex(i); const Point_2 & p2 = P.to_2d(p3); typename CDT_plus_2::Vertex_handle corner = cdt.insert(p2); corners[i] = corner; } // Insert triangle edges as constraints for(Index i = 0;i<3;i++) { cdt.insert_constraint( corners[(i+1)%3], corners[(i+2)%3]); } // Insert constraints for intersection objects for( const auto & obj : A_objects_3) { if(const Segment_3 *iseg = CGAL::object_cast<Segment_3 >(&obj)) { // Add segment constraint cdt.insert_constraint(P.to_2d(iseg->vertex(0)),P.to_2d(iseg->vertex(1))); }else if(const Point_3 *ipoint = CGAL::object_cast<Point_3 >(&obj)) { // Add point cdt.insert(P.to_2d(*ipoint)); } else if(const Triangle_3 *itri = CGAL::object_cast<Triangle_3 >(&obj)) { // Add 3 segment constraints cdt.insert_constraint(P.to_2d(itri->vertex(0)),P.to_2d(itri->vertex(1))); cdt.insert_constraint(P.to_2d(itri->vertex(1)),P.to_2d(itri->vertex(2))); cdt.insert_constraint(P.to_2d(itri->vertex(2)),P.to_2d(itri->vertex(0))); } else if(const std::vector<Point_3 > *polyp = CGAL::object_cast< std::vector<Point_3 > >(&obj)) { //cerr<<REDRUM("Poly...")<<endl; const std::vector<Point_3 > & poly = *polyp; const Index m = poly.size(); assert(m>=2); for(Index p = 0;p<m;p++) { const Index np = (p+1)%m; cdt.insert_constraint(P.to_2d(poly[p]),P.to_2d(poly[np])); } }else { cerr<<REDRUM("What is this object?!")<<endl; assert(false); } } }