From 5bc5ec4f469806b9738da62e30516eb9ecbebf5c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 25 Sep 2023 17:58:03 +0200 Subject: [PATCH] fix cheese18 --merge-facets The explanation of the bug: `split_graph_into_polylines` can reverse the orientation of a polygon --- .../Constrained_Delaunay_triangulation_3.h | 6 ++--- .../test/Triangulation_3/cdt_3_from_off.cpp | 24 +++++++++++++++++-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/Triangulation_3/include/CGAL/Constrained_Delaunay_triangulation_3.h b/Triangulation_3/include/CGAL/Constrained_Delaunay_triangulation_3.h index d569f82fd04..13df3eddfb5 100644 --- a/Triangulation_3/include/CGAL/Constrained_Delaunay_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Constrained_Delaunay_triangulation_3.h @@ -534,7 +534,7 @@ public: const auto vb = *circ; const auto c_id = this->constraint_from_extremities(va, vb); if(c_id != Constraint_id{}) { - const bool constraint_c_id_is_reversed = true; + const bool constraint_c_id_is_reversed = va != (*this->constraint_hierarchy.vertices_in_constraint_begin(c_id)); border.push_back(Face_edge{c_id, constraint_c_id_is_reversed}); constraint_to_faces.emplace(c_id, polygon_contraint_id); } else { @@ -635,9 +635,7 @@ private: const auto v_end = this->constraint_hierarchy.vertices_in_constraint_end(c_id); CGAL_assertion(std::distance(v_begin, v_end) >= 2); auto va = *v_begin; - auto vb_it = v_end; - --vb_it; - auto vb = *vb_it; + auto vb = *std::prev(v_end); if(reversed) { using std::swap; swap(va, vb); diff --git a/Triangulation_3/test/Triangulation_3/cdt_3_from_off.cpp b/Triangulation_3/test/Triangulation_3/cdt_3_from_off.cpp index 3e91be160d6..70e8c330212 100644 --- a/Triangulation_3/test/Triangulation_3/cdt_3_from_off.cpp +++ b/Triangulation_3/test/Triangulation_3/cdt_3_from_off.cpp @@ -132,7 +132,7 @@ int main(int argc, char* argv[]) try { go(mesh, output_filename); } catch(CGAL::Failure_exception& e) { - if(e.expression().find(std::string("orientation(p0, p1, p2, p3) == POSITIVE")) != std::string::npos) + if(e.expression().find(std::string("handles.back() == va")) != std::string::npos) { std::cerr << "BAD MESH! " << mesh.number_of_faces() << " faces\n"; std::ofstream bad("bad.off"); @@ -302,8 +302,28 @@ int go(Mesh mesh, std::string output_filename) { CDT_3_try { if(merge_facets) { for(int i = 0; i < nb_patches; ++i) { - const auto& edges = patch_edges[i]; + auto& edges = patch_edges[i]; auto polylines = segment_soup_to_polylines(edges); + while(true) { + const auto non_closed_polylines_begin = + std::partition(polylines.begin(), polylines.end(), + [](const auto& polyline) { return polyline.front() == polyline.back(); }); + if(non_closed_polylines_begin == polylines.end()) + break; + edges.clear(); + for(auto it = non_closed_polylines_begin; it != polylines.end(); ++it) { + auto& polyline = *it; + for(auto it = polyline.begin(), end = polyline.end() - 1; it != end; ++it) { + edges.emplace_back(*it, *(it + 1)); + } + } + polylines.erase(non_closed_polylines_begin, polylines.end()); + auto other_polylines = segment_soup_to_polylines(edges); + polylines.insert(polylines.end(), + std::make_move_iterator(other_polylines.begin()), + std::make_move_iterator(other_polylines.end())); + } + std::optional face_index; for(auto& polyline: polylines) { assert(polyline.front() == polyline.back());