From a23d2baa87f76763fad01b441a813fc246d8d4cf Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 29 Sep 2020 12:06:18 +0200 Subject: [PATCH 1/6] add a precondition to avoid degenerate faces in input degenerate faces cause an infinite loop in `loop_over_edges()` --- .../Surface_mesh_geodesic_distances_3.h | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) 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..07bdbfefef3 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 @@ -24,6 +24,7 @@ #include #include #include +#include #include #ifdef CGAL_EIGEN3_ENABLED #include @@ -35,6 +36,7 @@ #include namespace CGAL { + namespace Heat_method_3 { /** @@ -478,6 +480,8 @@ public: template void estimate_geodesic_distances(VertexDistanceMap vdm) { + CGAL_precondition(!internal::has_degenerate_faces(triangle_mesh(), vertex_point_map())); + if(is_empty(tm)){ return; } @@ -676,6 +680,25 @@ struct Idt_storage {} }; +template +bool has_degenerate_faces(const TriangleMesh& tm, VertexPointMap vpm) +{ + for (typename boost::graph_traits::face_descriptor f : faces(tm)) + { + if (CGAL::Polygon_mesh_processing::is_degenerate_triangle_face(f, tm, + CGAL::Polygon_mesh_processing::parameters::vertex_point_map(vpm))) + return true; + } + return false; +} + +template +bool has_degenerate_faces(const TriangleMesh& tm) +{ + return has_degenerate_faces(tm, get(vertex_point, tm)); +} + + template template void estimate_geodesic_distances(VertexDistanceMap vdm) { + CGAL_precondition(!internal::has_degenerate_faces(this->m_idt.triangle_mesh(), + this->m_idt.vertex_point_map())); + base().estimate_geodesic_distances(this->m_idt.vertex_distance_map(vdm)); } }; @@ -730,6 +756,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 +770,7 @@ 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`). - * + * \pre */ template @@ -921,6 +949,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` @@ -931,6 +960,8 @@ estimate_geodesic_distances(const TriangleMesh& tm, typename boost::graph_traits::vertex_descriptor source, Mode) { + CGAL_precondition(!internal::has_degenerate_faces(tm)); + CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 hm(tm); hm.add_source(source); hm.estimate_geodesic_distances(vdm); @@ -944,6 +975,8 @@ estimate_geodesic_distances(const TriangleMesh& tm, VertexDistanceMap vdm, typename boost::graph_traits::vertex_descriptor source) { + CGAL_precondition(!internal::has_degenerate_faces(tm)); + CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 hm(tm); hm.add_source(source); hm.estimate_geodesic_distances(vdm); @@ -962,6 +995,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 @@ -977,6 +1011,8 @@ estimate_geodesic_distances(const TriangleMesh& tm, #endif ) { + CGAL_precondition(!internal::has_degenerate_faces(tm)); + CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 hm(tm); hm.add_sources(sources); hm.estimate_geodesic_distances(vdm); @@ -992,6 +1028,8 @@ estimate_geodesic_distances(const TriangleMesh& tm, typename boost::has_range_const_iterator >::type* = 0) { + CGAL_precondition(!internal::has_degenerate_faces(tm)); + CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 hm(tm); hm.add_sources(sources); hm.estimate_geodesic_distances(vdm); From 2168bdda9c3ac635c5a3a93bb408b067e850a1af Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 29 Sep 2020 13:01:21 +0200 Subject: [PATCH 2/6] remove empty \pre --- .../CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h | 1 - 1 file changed, 1 deletion(-) 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 07bdbfefef3..ee8b77792e2 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 @@ -770,7 +770,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`). - * \pre */ template Date: Tue, 20 Oct 2020 11:07:49 +0200 Subject: [PATCH 3/6] use internal vertex point map --- .../CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 ee8b77792e2..c3b0688ba9f 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 @@ -738,9 +738,7 @@ struct Base_helper template void estimate_geodesic_distances(VertexDistanceMap vdm) { - CGAL_precondition(!internal::has_degenerate_faces(this->m_idt.triangle_mesh(), - this->m_idt.vertex_point_map())); - + CGAL_precondition(!internal::has_degenerate_faces(this->m_idt.triangle_mesh())); base().estimate_geodesic_distances(this->m_idt.vertex_distance_map(vdm)); } }; From 88121fa3ef673097696a0a1478c7af95bbc90330 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 27 Oct 2020 09:42:55 +0100 Subject: [PATCH 4/6] fix namespace not precise enough for some compilers --- .../CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 c3b0688ba9f..4777e95dce8 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 @@ -480,7 +480,8 @@ public: template void estimate_geodesic_distances(VertexDistanceMap vdm) { - CGAL_precondition(!internal::has_degenerate_faces(triangle_mesh(), vertex_point_map())); + CGAL_precondition( + !CGAL::Heat_method_3::internal::has_degenerate_faces(triangle_mesh(), vertex_point_map())); if(is_empty(tm)){ return; @@ -738,7 +739,8 @@ struct Base_helper template void estimate_geodesic_distances(VertexDistanceMap vdm) { - CGAL_precondition(!internal::has_degenerate_faces(this->m_idt.triangle_mesh())); + CGAL_precondition( + !CGAL::Heat_method_3::internal::has_degenerate_faces(this->m_idt.triangle_mesh())); base().estimate_geodesic_distances(this->m_idt.vertex_distance_map(vdm)); } }; From 771da5d1dc463de5dc2f4f6749bbeb79c353a90f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 27 Oct 2020 10:25:11 +0100 Subject: [PATCH 5/6] forward-declare has_degenerate_faces before it is used --- .../Heat_method_3/Surface_mesh_geodesic_distances_3.h | 8 ++++++++ 1 file changed, 8 insertions(+) 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 4777e95dce8..69f024199a1 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 @@ -51,6 +51,14 @@ struct Direct struct Intrinsic_Delaunay {}; +namespace internal { + template + bool has_degenerate_faces(const TriangleMesh& tm); + + template + bool has_degenerate_faces(const TriangleMesh& tm, VertexPointMap vpm); +} + namespace internal { template Date: Thu, 12 Nov 2020 15:22:49 +0100 Subject: [PATCH 6/6] fix degenerate faces precondition --- .../Surface_mesh_geodesic_distances_3.h | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) 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 69f024199a1..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 @@ -24,7 +24,6 @@ #include #include #include -#include #include #ifdef CGAL_EIGEN3_ENABLED #include @@ -52,11 +51,9 @@ struct Intrinsic_Delaunay {}; namespace internal { - template - bool has_degenerate_faces(const TriangleMesh& tm); - template - bool has_degenerate_faces(const TriangleMesh& tm, VertexPointMap vpm); + template + bool has_degenerate_faces(const TriangleMesh& tm, const Traits& traits); } namespace internal { @@ -489,7 +486,7 @@ public: void estimate_geodesic_distances(VertexDistanceMap vdm) { CGAL_precondition( - !CGAL::Heat_method_3::internal::has_degenerate_faces(triangle_mesh(), vertex_point_map())); + !CGAL::Heat_method_3::internal::has_degenerate_faces(triangle_mesh(), Traits())); if(is_empty(tm)){ return; @@ -689,25 +686,32 @@ struct Idt_storage {} }; -template -bool has_degenerate_faces(const TriangleMesh& tm, VertexPointMap vpm) +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)) { - if (CGAL::Polygon_mesh_processing::is_degenerate_triangle_face(f, tm, - CGAL::Polygon_mesh_processing::parameters::vertex_point_map(vpm))) + 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 -bool has_degenerate_faces(const TriangleMesh& tm) -{ - return has_degenerate_faces(tm, get(vertex_point, tm)); -} - - template void estimate_geodesic_distances(VertexDistanceMap vdm) { CGAL_precondition( - !CGAL::Heat_method_3::internal::has_degenerate_faces(this->m_idt.triangle_mesh())); + !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)); } }; @@ -967,8 +972,6 @@ estimate_geodesic_distances(const TriangleMesh& tm, typename boost::graph_traits::vertex_descriptor source, Mode) { - CGAL_precondition(!internal::has_degenerate_faces(tm)); - CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 hm(tm); hm.add_source(source); hm.estimate_geodesic_distances(vdm); @@ -982,8 +985,6 @@ estimate_geodesic_distances(const TriangleMesh& tm, VertexDistanceMap vdm, typename boost::graph_traits::vertex_descriptor source) { - CGAL_precondition(!internal::has_degenerate_faces(tm)); - CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 hm(tm); hm.add_source(source); hm.estimate_geodesic_distances(vdm); @@ -1018,8 +1019,6 @@ estimate_geodesic_distances(const TriangleMesh& tm, #endif ) { - CGAL_precondition(!internal::has_degenerate_faces(tm)); - CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 hm(tm); hm.add_sources(sources); hm.estimate_geodesic_distances(vdm); @@ -1035,8 +1034,6 @@ estimate_geodesic_distances(const TriangleMesh& tm, typename boost::has_range_const_iterator >::type* = 0) { - CGAL_precondition(!internal::has_degenerate_faces(tm)); - CGAL::Heat_method_3::Surface_mesh_geodesic_distances_3 hm(tm); hm.add_sources(sources); hm.estimate_geodesic_distances(vdm);