From d704fc056f52abae15128663923a723d969148bb Mon Sep 17 00:00:00 2001 From: Sven Oesau Date: Mon, 15 Dec 2025 09:51:36 +0100 Subject: [PATCH 01/13] tests for triangulate_hole_Polyhedron_3_no_delaunay_test and triangulate_hole_Polyhedron_3_test were also added in absence of Eigen3 causing the testsuite to abort --- .../test/Polygon_mesh_processing/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index 165451d56ad..a93d5475d9c 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -137,7 +137,7 @@ else() message(STATUS "NOTICE: Tests are not using Ceres.") endif() -if(CGAL_ENABLE_TESTING) +if(CGAL_ENABLE_TESTING AND TARGET CGAL::Eigen3_support) set_tests_properties( "execution of triangulate_hole_Polyhedron_3_no_delaunay_test" "execution of triangulate_hole_Polyhedron_3_test" From 534ad07bd4b37ecf4151f6b975dc6938fc237737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 18 Dec 2025 11:24:24 +0100 Subject: [PATCH 02/13] Add missing operators --- .../Triangulation_2/Concepts/TriangulationTraits_2.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h b/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h index 68d24483b34..827ac363719 100644 --- a/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h +++ b/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h @@ -248,6 +248,16 @@ Construct_triangle_2 construct_triangle_2_object(); /*! +*/ +Less_x_2 less_x_2_object(); + +/*! + +*/ +Less_y_2 less_y_2_object(); + +/*! + */ Compare_x_2 compare_x_2_object(); From 8511225edd392127c29f01b709e85b5233a5fbaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 18 Dec 2025 11:32:45 +0100 Subject: [PATCH 03/13] Use .bbox() to get the bounding box of a primitive if no pmap is provided The doc says that .bbox() must exist and Compute_bbox_2 is not part of the AABBGeomTraits_2 concept. --- AABB_tree/include/CGAL/AABB_traits_2.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/AABB_tree/include/CGAL/AABB_traits_2.h b/AABB_tree/include/CGAL/AABB_traits_2.h index 39a5b1b55c4..877565d1877 100644 --- a/AABB_tree/include/CGAL/AABB_traits_2.h +++ b/AABB_tree/include/CGAL/AABB_traits_2.h @@ -484,19 +484,19 @@ public: private: /** - * @brief Computes bounding box of one primitive + * @brief Computes the bounding box of a primitive * @param pr the primitive * @return the bounding box of the primitive \c pr */ template - Bounding_box compute_bbox(const Primitive& pr, const PM&)const + Bounding_box compute_bbox(const Primitive& pr, const PM&) const { return get(bbm, pr.id()); } - Bounding_box compute_bbox(const Primitive& pr, const Default&)const + Bounding_box compute_bbox(const Primitive& pr, const Default&) const { - return GeomTraits().construct_bbox_2_object()(internal::Primitive_helper::get_datum(pr, *this)); + return internal::Primitive_helper::get_datum(pr,*this).bbox(); } /// Comparison functions From 511c3f14a5f2981a7d51d086caeeb61c3dae5ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sat, 6 Dec 2025 01:06:23 +0100 Subject: [PATCH 04/13] Add missing space --- BGL/include/CGAL/boost/graph/Euler_operations.h | 1 + 1 file changed, 1 insertion(+) diff --git a/BGL/include/CGAL/boost/graph/Euler_operations.h b/BGL/include/CGAL/boost/graph/Euler_operations.h index e33ae5a6910..1f00fb1b2cb 100644 --- a/BGL/include/CGAL/boost/graph/Euler_operations.h +++ b/BGL/include/CGAL/boost/graph/Euler_operations.h @@ -1537,6 +1537,7 @@ does_satisfy_link_condition(typename boost::graph_traits::edge_descriptor * collapses an edge in a graph. * * \tparam Graph must be a model of `MutableFaceGraph` + * * Let `h` be the halfedge of `e`, and let `v0` and `v1` be the source and target vertices of `h`. * Let `p_h` and `p_o_h` be respectively the edges of `prev(h,g)` and `prev(opposite(h, g), g)`. * Let `o_n_h` and `o_n_o_h` be respectively the edges of `opposite(next(h,g))` and `opposite(next(opposite(h, g), g))`. From 171b13cfa95fb504fc8894dee0107097a7af26d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sat, 6 Dec 2025 01:07:33 +0100 Subject: [PATCH 05/13] Fix compilation error in debug code --- .../Polygon_mesh_processing/internal/Snapping/snap_vertices.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h index 5adbf99ff6f..a8a509a8d07 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h @@ -246,7 +246,7 @@ public: #ifdef CGAL_PMP_SNAP_DEBUG_PP std::cout << "squared distance between " << va << " [" << get(m_vpm_A, va) << "] and " - << vb << " [" << get(m_vpm_B, vb) << "]: " << sq_dist + << vb << " [" << get(m_vpm_B, vb) << "]: " << CGAL::squared_distance(get(m_vpm_A, va), get(m_vpm_B, vb)) << " (tol a/b: " << tol_a << " " << tol_b << ") larger? " << (res == CGAL::LARGER) << std::endl; #endif From 5badbdc7d75f13488aeda9a64e2219ad74d6d678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sat, 6 Dec 2025 01:07:47 +0100 Subject: [PATCH 06/13] Make it easier to copy-paste points --- .../internal/Snapping/snap_vertices.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h index a8a509a8d07..e3e776e9545 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h @@ -758,6 +758,10 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, // Vertex-Vertex snapping is performed by identify points which are already equal // and grouping them together so that they are moved together +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "(A) Positions" << std::endl; +#endif + // @todo all range building could be parallel (worth it?) Unique_positions unique_positions_A; for(halfedge_descriptor h : halfedge_range_A) @@ -766,7 +770,7 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, const FT tolerance = get(tolerance_map_A, v); #ifdef CGAL_PMP_SNAP_DEBUG_PP - std::cout << "Pos (A): " << v << " (" << get(vpm_A, v) << ")" << std::endl; + std::cout << " " << get(vpm_A, v) << std::endl; #endif Vertex_container nvc {{ h }}; @@ -784,6 +788,10 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, } } +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "(B) Positions" << std::endl; +#endif + // same for tm_B (@todo when doing boxes, avoid all that for self snapping + use self_intersection_d) Unique_positions unique_positions_B; for(halfedge_descriptor h : halfedge_range_B) @@ -792,7 +800,7 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, const FT tolerance = get(tolerance_map_B, v); #ifdef CGAL_PMP_SNAP_DEBUG_PP - std::cout << "Pos (B): " << v << " (" << get(vpm_B, v) << ")" << std::endl; + std::cout << " " << get(vpm_B, v) << std::endl; #endif Vertex_container nvc {{ h }}; From f285490e33891cba1be334495fc682a259650443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sat, 6 Dec 2025 01:08:24 +0100 Subject: [PATCH 07/13] Fix losing in_range markers when opoh is a border edge --- .../internal/Snapping/snap.h | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h index 62c893b7f4e..e75ab3f049f 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h @@ -121,6 +121,9 @@ void simplify_range(HalfedgeRange& halfedge_range, while(!edges_to_test.empty()) { const halfedge_descriptor h = *(edges_to_test.begin()); + CGAL_precondition(is_border(h, tm)); + CGAL_precondition(!is_border(opposite(h, tm), tm)); + edges_to_test.erase(edges_to_test.begin()); const vertex_descriptor vs = source(h, tm); @@ -137,7 +140,6 @@ void simplify_range(HalfedgeRange& halfedge_range, if(gt.compare_squared_distance_3_object()(ps,pt,CGAL::square(max_tol)) == SMALLER) { const halfedge_descriptor prev_h = prev(h, tm); - const halfedge_descriptor next_h = next(h, tm); const halfedge_descriptor prev_oh = prev(opposite(h, tm), tm); // check that the border has at least 4 edges not to create degenerate volumes @@ -190,19 +192,35 @@ void simplify_range(HalfedgeRange& halfedge_range, if(!CGAL::Euler::does_satisfy_link_condition(edge(h, tm), tm)) continue; + // Since `o_h` is not a border halfedge, `prev(opp(h))` gets replaced with `opp(next(opp(h)))`. + // But `prev(opp(h))` might have been be a border edge whereas `opp(next(opp(h)))` might not be. + // So, if `opp(prev(opp(h)))` was a border halfedge in the range, we must add `next(opp(h))` + // to the range. + bool was_opoh_border_in_range = false; + const halfedge_descriptor opoh = opposite(prev(opposite(h, tm), tm), tm); - if(is_border(opoh, tm)) + if(is_border(opoh, tm) && get(range_halfedges, opoh)) { + was_opoh_border_in_range = true; edges_to_test.erase(opoh); + } vertex_descriptor v = Euler::collapse_edge(edge(h, tm), tm); + CGAL_postcondition(bool(is_border(v, tm))); + CGAL_postcondition(target(prev_h, tm) == v); put(vpm, v, new_p); put(tolerance_map, v, new_tolerance); + const halfedge_descriptor next_ph = next(prev_h, tm); + if(was_opoh_border_in_range) { + put(range_halfedges, next_ph, true); + } + if(get(range_halfedges, prev_h)) edges_to_test.insert(prev_h); - if(next_h != opoh && get(range_halfedges, next_h)) - edges_to_test.insert(next_h); + if(get(range_halfedges, next_ph)) + edges_to_test.insert(next_ph); + ++collapsed_n; } } From 17c0072f92ffee5f84e8f331900440f7c71155f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sat, 6 Dec 2025 09:39:11 +0100 Subject: [PATCH 08/13] Fix comment --- .../Polygon_mesh_processing/internal/Snapping/snap_vertices.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h index e3e776e9545..d7ccabf700e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h @@ -755,8 +755,8 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, is_empty_range(halfedge_range_B.begin(), halfedge_range_B.end())) return 0; - // Vertex-Vertex snapping is performed by identify points which are already equal - // and grouping them together so that they are moved together + // Vertex-Vertex snapping identifies points which are already equal + // and groups them together so that they are moved together #ifdef CGAL_PMP_SNAP_DEBUG_PP std::cout << "(A) Positions" << std::endl; From 12d71ca7388fd7171926d7d74fa937d45df3292f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sat, 6 Dec 2025 09:39:43 +0100 Subject: [PATCH 09/13] Get rid of useless general case checking with num_halfedges(tm) means this only applies to something like union of triangular connected components. And if we change to counting the number of border halfedges, then we might as well just rely on the O(1) dynamic property map. --- .../internal/Snapping/snap.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h index e75ab3f049f..5936cea3db5 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h @@ -105,12 +105,19 @@ void simplify_range(HalfedgeRange& halfedge_range, typedef CGAL::dynamic_halfedge_property_t Halfedge_bool_tag; typedef typename boost::property_map::type Range_halfedges; - const bool all_hedges = (::CGAL::internal::exact_num_halfedges(tm)==halfedge_range.size()); +#ifdef CGAL_PMP_SNAP_DEBUG_OUTPUT + static int i = 0; + std::ofstream out_in("results/input_" + std::string((i++ == 0) ? "A" : "B") + ".polylines.txt"); + out_in.precision(17); +#endif - Range_halfedges range_halfedges = get(Halfedge_bool_tag(), tm, all_hedges); - if (!all_hedges) - for(halfedge_descriptor h : halfedge_range) - put(range_halfedges, h, true); + Range_halfedges range_halfedges = get(Halfedge_bool_tag(), tm, false); + for(halfedge_descriptor h : halfedge_range) { +#ifdef CGAL_PMP_SNAP_DEBUG_OUTPUT + out_in << "2 " << get(vpm, source(h, tm)) << " " << get(vpm, target(h, tm)) << "\n"; +#endif + put(range_halfedges, h, true); + } CGAL_postcondition_code(const std::size_t initial_n = halfedge_range.size();) From fb259cbbd36f6cb5978e6dc0342bbede9ba6e0a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sat, 6 Dec 2025 13:52:06 +0100 Subject: [PATCH 10/13] Better debug file name --- .../CGAL/Polygon_mesh_processing/internal/Snapping/snap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h index 5936cea3db5..4403e50fabe 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h @@ -107,7 +107,7 @@ void simplify_range(HalfedgeRange& halfedge_range, #ifdef CGAL_PMP_SNAP_DEBUG_OUTPUT static int i = 0; - std::ofstream out_in("results/input_" + std::string((i++ == 0) ? "A" : "B") + ".polylines.txt"); + std::ofstream out_in("results/before_simplification_" + std::to_string(i++) + ".polylines.txt"); out_in.precision(17); #endif From 6b514c19019ecf2459d6a7289f010c4f7cfd1fcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 9 Dec 2025 13:18:16 +0100 Subject: [PATCH 11/13] Better snap debug code --- .../internal/Snapping/snap.h | 53 ++++++++++++++----- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h index 4403e50fabe..c6009303d7a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h @@ -718,12 +718,18 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, halfedge_descriptor h_to_split = es.first; CGAL_assertion(is_border(h_to_split, tm_T)); +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << " -.-.-. Splitting " << edge(h_to_split, tm_T) << " |||| " + << " Vs " << source(h_to_split, tm_T) << " (" << tm_T.point(source(h_to_split, tm_T)) << ")" + << " --- Vt " << target(h_to_split, tm_T) << " (" << tm_T.point(target(h_to_split, tm_T)) << ")" << std::endl; +#endif + Vertices_with_new_position& splitters = es.second; if(splitters.size() > 1) { #ifdef CGAL_PMP_SNAP_DEBUG_PP - std::cout << " _______ Multiple splitting points on the same halfedge" << std::endl; + std::cout << " _______ Multiple splitting points on the same halfedge, sorting..." << std::endl; #endif const Point_ref hsp = get(vpm_T, source(h_to_split, tm_T)); @@ -746,20 +752,36 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, const vertex_descriptor splitter_v = target(splitter_h, tm_S); const Point new_position = is_source_mesh_fixed ? get(vpm_S, splitter_v) : vnp.second; +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "With point: " << new_position << " (first choice: " << vnp.second << ")" << std::endl; +#endif + bool do_split = true; // In case of self-snapping, avoid degenerate caps const bool is_same_mesh = (&tm_T == &tm_S); - if(is_same_mesh && target(next(opposite(h_to_split, tm_T), tm_T), tm_T) == splitter_v) + if(is_same_mesh && target(next(opposite(h_to_split, tm_T), tm_T), tm_T) == splitter_v) { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Reject split (A)" << std::endl; +#endif do_split = false; + } // Do not split if it would create a degenerate needle if((new_position == get(vpm_T, target(h_to_split, tm_T))) || - (new_position == get(vpm_T, source(h_to_split, tm_T)))) + (new_position == get(vpm_T, source(h_to_split, tm_T)))) { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Reject split (B)" << std::endl; +#endif do_split = false; + } - if(!first_split && new_position == previous_split_position) + if(!first_split && new_position == previous_split_position) { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Reject split (C)" << std::endl; +#endif do_split = false; + } // check if the new faces after split will not be degenerate const Point& p0 = new_position; @@ -784,13 +806,21 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, if(first_split_face) { - if(p0p2 <= 0 || collinear(p0,p1,p2) || collinear(p0,p2,p3)) + if(p0p2 <= 0 || collinear(p0,p1,p2) || collinear(p0,p2,p3)) { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Reject split (D)" << std::endl; +#endif do_split = false; + } } else { - if(p1p3 <= 0 || collinear(p0,p1,p3) || collinear(p1,p2,p3)) + if(p1p3 <= 0 || collinear(p0,p1,p3) || collinear(p1,p2,p3)) { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Reject split (E)" << std::endl; +#endif do_split = false; + } } if(do_split && !is_source_mesh_fixed) @@ -799,6 +829,9 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, { if(!is_border(h,tm_S) && collinear(get(vpm_S, source(h,tm_S)), new_position, get(vpm_S, target(next(h,tm_S),tm_S)))) { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Reject split (F)" << std::endl; +#endif do_split = false; break; } @@ -809,10 +842,6 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, } #ifdef CGAL_PMP_SNAP_DEBUG_PP - std::cout << " -.-.-. Splitting " << edge(h_to_split, tm_T) << " |||| " - << " Vs " << source(h_to_split, tm_T) << " (" << tm_T.point(source(h_to_split, tm_T)) << ")" - << " --- Vt " << target(h_to_split, tm_T) << " (" << tm_T.point(target(h_to_split, tm_T)) << ")" << std::endl; - std::cout << "With point: " << new_position << " (init: " << vnp.second << ")" << std::endl; std::cout << "Actually split? " << do_split << std::endl; #endif @@ -967,11 +996,11 @@ std::size_t snap_non_conformal_one_way(const HalfedgeRange& halfedge_range_S, for(halfedge_descriptor h : halfedge_range_T) { - CGAL_precondition(is_border(edge(h, tm_T), tm_T)); + CGAL_precondition(is_border_edge(h, tm_T)); if(get(locked_halfedges_T, h)) { #ifdef CGAL_PMP_SNAP_DEBUG_PP - std::cout << edge(h, tm_T) << " is locked and not a valid target" << std::endl; + std::cout << edge(h, tm_T) << " [" << source(h, tm_T) << " - " << target(h, tm_T) << "] is locked and not a valid target" << std::endl; #endif continue; } From 75244517cc90c0d7f581a6c3108bc0390037c2b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 11 Dec 2025 12:11:16 +0100 Subject: [PATCH 12/13] Be more robust to possible non-manifold configurations --- .../internal/Snapping/snap.h | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h index c6009303d7a..954e51b266e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h @@ -203,9 +203,10 @@ void simplify_range(HalfedgeRange& halfedge_range, // But `prev(opp(h))` might have been be a border edge whereas `opp(next(opp(h)))` might not be. // So, if `opp(prev(opp(h)))` was a border halfedge in the range, we must add `next(opp(h))` // to the range. - bool was_opoh_border_in_range = false; - const halfedge_descriptor opoh = opposite(prev(opposite(h, tm), tm), tm); + bool was_opoh_border_in_range = false; + const halfedge_descriptor noh = next(opposite(h, tm), tm); + if(is_border(opoh, tm) && get(range_halfedges, opoh)) { was_opoh_border_in_range = true; edges_to_test.erase(opoh); @@ -218,15 +219,17 @@ void simplify_range(HalfedgeRange& halfedge_range, put(vpm, v, new_p); put(tolerance_map, v, new_tolerance); - const halfedge_descriptor next_ph = next(prev_h, tm); - if(was_opoh_border_in_range) { - put(range_halfedges, next_ph, true); + if(was_opoh_border_in_range) + { + CGAL_assertion(is_border(noh, tm)); + put(range_halfedges, noh, true); } - if(get(range_halfedges, prev_h)) - edges_to_test.insert(prev_h); - if(get(range_halfedges, next_ph)) - edges_to_test.insert(next_ph); + for(halfedge_descriptor ih : halfedges_around_target(v, tm)) + { + if(get(range_halfedges, ih)) + edges_to_test.insert(ih); + } ++collapsed_n; } From 89229ae2de726a8a03d11ef0dc4f047648f78892 Mon Sep 17 00:00:00 2001 From: Mael Date: Fri, 12 Dec 2025 09:36:07 +0100 Subject: [PATCH 13/13] Fix unused variable warning --- .../CGAL/Polygon_mesh_processing/internal/Snapping/snap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h index 954e51b266e..12c338c4739 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h @@ -146,7 +146,7 @@ void simplify_range(HalfedgeRange& halfedge_range, if(gt.compare_squared_distance_3_object()(ps,pt,CGAL::square(max_tol)) == SMALLER) { - const halfedge_descriptor prev_h = prev(h, tm); + CGAL_precondition_code(const halfedge_descriptor prev_h = prev(h, tm);) const halfedge_descriptor prev_oh = prev(opposite(h, tm), tm); // check that the border has at least 4 edges not to create degenerate volumes