diff --git a/Heat_method_3/include/CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h b/Heat_method_3/include/CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h index 8d3aff70392..d1499bbca35 100644 --- a/Heat_method_3/include/CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h +++ b/Heat_method_3/include/CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h @@ -35,6 +35,7 @@ #include namespace CGAL { + namespace Heat_method_3 { /** @@ -49,6 +50,12 @@ struct Direct struct Intrinsic_Delaunay {}; +namespace internal { + + template + bool has_degenerate_faces(const TriangleMesh& tm, const Traits& traits); +} + namespace internal { template void estimate_geodesic_distances(VertexDistanceMap vdm) { + CGAL_precondition( + !CGAL::Heat_method_3::internal::has_degenerate_faces(triangle_mesh(), Traits())); + if(is_empty(tm)){ return; } @@ -676,6 +686,32 @@ struct Idt_storage {} }; +template +bool has_degenerate_faces(const TriangleMesh& tm, const Traits& traits) +{ + typedef typename Traits::Point_3 Point; + typedef typename Traits::Vector_3 Vector_3; + typename Traits::Construct_vector_3 + construct_vector = traits.construct_vector_3_object(); + typename Traits::Compute_scalar_product_3 + scalar_product = traits.compute_scalar_product_3_object(); + typename Traits::Construct_cross_product_vector_3 + cross_product = traits.construct_cross_product_vector_3_object(); + + typename boost::property_map< TriangleMesh, boost::vertex_point_t>::const_type + vpm = get(boost::vertex_point, tm); + for (typename boost::graph_traits::face_descriptor f : faces(tm)) + { + const Point p1 = get(vpm, target(halfedge(f, tm), tm)); + const Point p2 = get(vpm, target(next(halfedge(f, tm), tm), tm)); + const Point p3 = get(vpm, target(next(next(halfedge(f, tm), tm), tm), tm)); + Vector_3 v = cross_product(construct_vector(p1, p2), construct_vector(p1, p3)); + if(scalar_product(v, v) == 0.) + return true; + } + return false; +} + template template void estimate_geodesic_distances(VertexDistanceMap vdm) { + CGAL_precondition( + !CGAL::Heat_method_3::internal::has_degenerate_faces( + this->m_idt.triangle_mesh(), Traits())); base().estimate_geodesic_distances(this->m_idt.vertex_distance_map(vdm)); } }; @@ -730,6 +769,7 @@ struct Base_helper * time after changes to the set of sources. * * \tparam TriangleMesh a triangulated surface mesh, model of `FaceListGraph` and `HalfedgeListGraph` + * with no degenerate faces * \tparam Mode must be `Intrinsic_Delaunay` to indicate that an intrinsic Delaunay triangulation is internally constructed * or `Direct` to indicate that the input mesh should be used as is. * If `Intrinsic_Delaunay`, then the type `TriangleMesh` must have an internal property for `vertex_point` @@ -743,7 +783,6 @@ struct Base_helper * is used as default * \tparam Traits a model of `HeatMethodTraits_3`. The default is the Kernel of the value type * of the vertex point map (extracted using `Kernel_traits`). - * */ template @@ -921,6 +961,7 @@ public: /// \tparam Mode either the tag `Direct` or `Intrinsic_Delaunay`, which determines if the geodesic distance /// is computed directly on the mesh or if the intrinsic Delaunay triangulation is applied first. /// The default is `Intrinsic_Delaunay`. +/// \pre `tm` does not have any degenerate faces /// \warning The return type is `double` even when used with an exact kernel. /// /// \sa `CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3` @@ -962,6 +1003,7 @@ estimate_geodesic_distances(const TriangleMesh& tm, /// \tparam Mode either the tag `Direct` or `Intrinsic_Delaunay`, which determines if the geodesic distance /// is computed directly on the mesh or if the intrinsic Delaunay triangulation is applied first. /// The default is `Intrinsic_Delaunay`. +/// \pre `tm` does not have any degenerate faces /// \warning The return type is `double` even when used with an exact kernel. /// \sa `CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3` template