From 1a2c0613646e88f09c2f45c08a17769d296ea71f Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 24 Sep 2025 17:10:26 +0200 Subject: [PATCH] add another way to reduce to two sets with union-find --- ...ing_constrained_Delaunay_triangulation_3.h | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_3.h b/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_3.h index 7e900f2c954..add29daf565 100644 --- a/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_3.h +++ b/Constrained_triangulation_3/include/CGAL/Conforming_constrained_Delaunay_triangulation_3.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include @@ -74,6 +76,7 @@ #include #include #include +#include #include #if CGAL_CXX20 && __has_include() # include @@ -2122,6 +2125,84 @@ private: }); CGAL_assume(vertex_above != Vertex_handle{}); + if(vertices_of_cavity_union_find.number_of_sets() > 2) { + const auto border_edges_set = std::invoke([&] { + using Ordered_pair = std::pair; + using Hash = boost::hash; + CGAL::unordered_flat_set border_edges_set; + for(auto edge : border_edges) { + auto [va, vb] = tr().vertices(edge); + border_edges_set.insert(make_sorted_pair(va, vb)); + } + return border_edges_set; + }); + CGAL::unordered_flat_set> remaining_facets_of_border(facets_of_border.begin(), + facets_of_border.end()); + + std::stack stack; + std::optional::handle> reference_handle_of_the_connected_component; + stack.push(border_facet_above); + remaining_facets_of_border.erase(border_facet_above); + while(!stack.empty()) { + const auto facet = stack.top(); + stack.pop(); + const auto [cell, facet_index] = facet; // border facet seen from the outside of the cavity + CGAL_assertion(intersecting_cells.count(cell) == 0); //REMOVE + CGAL_assertion(intersecting_cells.count(cell->neighbor(facet_index)) > 0); //REMOVE + const auto vertices = tr().vertices(facet); + for(auto v : vertices) { + if(is_marked(v, Vertex_marker::CAVITY)) { + if(!reference_handle_of_the_connected_component) { + reference_handle_of_the_connected_component = vertices_of_cavity_handles[v]; + } else { + vertices_of_cavity_union_find.unify_sets(*reference_handle_of_the_connected_component, + vertices_of_cavity_handles[v]); + } + } + } + for(int i = 0; i < 3; ++i) { + const auto va = vertices[i]; + const auto vb = vertices[tr().ccw(i)]; + + if((is_marked(va, Vertex_marker::CAVITY) || is_marked(vb, Vertex_marker::CAVITY)) && + border_edges_set.count(make_sorted_pair(va, vb)) == 0) + { + // loop around the edge [va, vb] to get another facet on the border of the cavity + auto previous_cell = cell; + auto other_cell = cell->neighbor(facet_index); + do { + CGAL_assertion(intersecting_cells.count(other_cell) >= 0); // REMOVE + auto index_va = other_cell->index(va); + auto index_vb = other_cell->index(vb); + auto other_facet_index = tr().next_around_edge(index_vb, index_va); + previous_cell = other_cell; + other_cell = previous_cell->neighbor(other_facet_index); + + } while(intersecting_cells.count(other_cell) > 0); + const Facet neighbor_facet{other_cell, other_cell->index(previous_cell)}; + CGAL_assertion(facets_of_border.count(neighbor_facet) > 0); + if(remaining_facets_of_border.erase(neighbor_facet) > 0) { + stack.push(neighbor_facet); + } + } + } + + // if the stack is empty but there are still facets to process, we start again to recover + // another connected component of the cavity border + if(stack.empty() && !remaining_facets_of_border.empty()) { + stack.push(*remaining_facets_of_border.begin()); + remaining_facets_of_border.erase(remaining_facets_of_border.begin()); + reference_handle_of_the_connected_component.reset(); + } + } + } + CGAL_assertion_msg(vertices_of_cavity_union_find.number_of_sets() <= 2, + std::invoke([&] { + std::stringstream ss; + ss << "Error: cavity has " << vertices_of_cavity_union_find.number_of_sets() + << " sub-cavities (should be <=2)\n"; + return ss.str(); + }).c_str()); const auto vertex_above_handle = vertices_of_cavity_handles[vertex_above]; const auto vertex_below_handle = std::invoke([&] {