From 52bf9890863a2a56ee2c1c10fa5ae6d40883e7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 12 May 2023 11:34:31 +0200 Subject: [PATCH 1/8] Add a non-trivial test with all degenerate faces --- .../data_degeneracies/all_degen.off | 16 ++++++++++++++++ .../test_pmp_repair_degeneracies.cpp | 5 +++++ 2 files changed, 21 insertions(+) create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data_degeneracies/all_degen.off diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data_degeneracies/all_degen.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data_degeneracies/all_degen.off new file mode 100644 index 00000000000..f579551770c --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data_degeneracies/all_degen.off @@ -0,0 +1,16 @@ +OFF +7 7 0 +0 0 0 +1 1 0 +1 1 0 +2 2 0 +1 1 0 +2 2 0 +0.5 1 0 +3 0 2 1 +3 0 3 2 +3 4 3 5 +3 1 4 5 +3 1 2 6 +3 6 2 4 +3 6 4 1 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_repair_degeneracies.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_repair_degeneracies.cpp index de7e7a2d49e..7cca0c04e6f 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_repair_degeneracies.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_repair_degeneracies.cpp @@ -287,6 +287,11 @@ void test() 0, 1, // expected number of degenerate edges/faces in the selection 0, 0); // expected number of degenerate edges/faces in the mesh after partial removal + remove_degeneracies("data_degeneracies/all_degen.off", + std::initializer_list({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}), // edge selection + std::initializer_list({0, 1, 2, 3, 4, 5, 6}), // face selection + 4, 7, 4, 7, 0, 0); + remove_degeneracies("data_degeneracies/degtri_four.off", std::initializer_list({1}), std::initializer_list({3}), From 931270b66d79f8fd2d0b32a6318bd0d989a12f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 15 May 2023 12:35:52 +0200 Subject: [PATCH 2/8] Introduce CGAL::empty(), which only clears combinatorial information And leaves everything else like internal property maps and garbage. --- BGL/doc/BGL/PackageDescription.txt | 1 + BGL/include/CGAL/boost/graph/helpers.h | 85 ++++++++++++++++++-------- 2 files changed, 62 insertions(+), 24 deletions(-) diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index 6032e29a6c9..9524e2f8519 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -679,6 +679,7 @@ user might encounter. - `CGAL::make_grid()` - `CGAL::clear()` +- `CGAL::empty()` - `CGAL::copy_face_graph()` - `CGAL::set_triangulation_ids()` diff --git a/BGL/include/CGAL/boost/graph/helpers.h b/BGL/include/CGAL/boost/graph/helpers.h index 21644ebf18f..27677cdfe7d 100644 --- a/BGL/include/CGAL/boost/graph/helpers.h +++ b/BGL/include/CGAL/boost/graph/helpers.h @@ -837,25 +837,6 @@ bool is_hexahedron(typename boost::graph_traits::halfedge_descriptor namespace internal { -template -inline -std::enable_if_t::value, void> -clear_impl(FaceGraph& g) -{ g.clear(); } - -template -inline -std::enable_if_t::value, void> -clear_impl(FaceGraph& g) -{ - while(boost::begin(edges(g))!=boost::end(edges(g))) - remove_edge(*boost::begin(edges(g)), g); - while(boost::begin(faces(g))!=boost::end(faces(g))) - remove_face(*boost::begin(faces(g)), g); - while(boost::begin(vertices(g))!=boost::end(vertices(g))) - remove_vertex(*boost::begin(vertices(g)), g); -} - template void swap_vertices(typename boost::graph_traits::vertex_descriptor& p, typename boost::graph_traits::vertex_descriptor& q, @@ -960,24 +941,80 @@ void swap_edges(const typename boost::graph_traits::halfedge_descript * \ingroup PkgBGLHelperFct * * removes all vertices, faces and halfedges from a graph. Calls - * `remove_edge()`, `remove_vertex()`, and `remove_face()` for each - * edge, vertex or face. + * \link MutableHalfedgeGraph `remove_vertex()`\endlink, + * \link MutableHalfedgeGraph `remove_edge()`\endlink, and + * \link MutableFaceGraph `remove_face()`\endlink, for each vertex, edge, and face. + * + * @tparam FaceGraph model of `MutableHalfedgeGraph` and `MutableFaceGraph` + * + * @param g the graph to empty + * + * @sa `CGAL::clear()` + **/ +template +void empty(FaceGraph& g) +{ + while(std::begin(edges(g)) != std::end(edges(g))) + remove_edge(*std::begin(edges(g)), g); + while(std::begin(faces(g)) != std::end(faces(g))) + remove_face(*std::begin(faces(g)), g); + while(std::begin(vertices(g)) != std::end(vertices(g))) + remove_vertex(*std::begin(vertices(g)), g); + + CGAL_postcondition(std::distance(std::cbegin(vertices(g)), std::cend(vertices(g))) == 0); + CGAL_postcondition(std::distance(std::cbegin(edges(g)), std::cend(edges(g))) == 0); + CGAL_postcondition(std::distance(std::cbegin(faces(g)), std::cend(faces(g))) == 0); +} + +namespace internal { + +template +inline +std::enable_if_t::value, void> +clear_impl(FaceGraph& g) +{ + g.clear(); +} + +template +inline +std::enable_if_t::value, void> +clear_impl(FaceGraph& g) +{ + empty(g); +} + +} // namespace internal + +/** + * \ingroup PkgBGLHelperFct + * + * removes all vertices, faces and halfedges from a graph. Calls + * \link MutableHalfedgeGraph `remove_vertex()`\endlink, + * \link MutableHalfedgeGraph `remove_edge()`\endlink, and + * \link MutableFaceGraph `remove_face()`\endlink, for each vertex, edge, and face. * * If the graph has a member function `clear()`, it will be called * instead. * + * @warning If it exists, the `clear()` function of a graph might do more than + * simply remove elements. For example, `CGAL::Surface_mesh::clear()` collects garbage + * and removes *all* property maps added by a call to `CGAL::Surface_mesh::add_property_map()` for all simplex types. + * * @tparam FaceGraph model of `MutableHalfedgeGraph` and `MutableFaceGraph` * * @param g the graph to clear * + * @sa `CGAL::empty()` **/ template void clear(FaceGraph& g) { internal::clear_impl(g); - CGAL_postcondition(std::distance(boost::begin(edges(g)),boost::end(edges(g))) == 0); - CGAL_postcondition(std::distance(boost::begin(vertices(g)),boost::end(vertices(g))) == 0); - CGAL_postcondition(std::distance(boost::begin(faces(g)),boost::end(faces(g))) == 0); + + CGAL_postcondition(std::distance(std::cbegin(vertices(g)), std::cend(vertices(g))) == 0); + CGAL_postcondition(std::distance(std::cbegin(edges(g)), std::cend(edges(g))) == 0); + CGAL_postcondition(std::distance(std::cbegin(faces(g)), std::cend(faces(g))) == 0); } /** From 7a3ad05e05eba5ce4f1743b297be3291364ec9fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 15 May 2023 12:41:39 +0200 Subject: [PATCH 3/8] Replace some calls of clear() by empty() to preserve internal property maps --- .../CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h | 4 ++-- .../include/CGAL/Polygon_mesh_processing/clip.h | 2 +- .../Polygon_mesh_processing/connected_components.h | 2 +- .../CGAL/Polygon_mesh_processing/corefinement.h | 14 +++++++------- .../remesh_planar_patches.h | 3 +-- .../Polygon_mesh_processing/repair_degeneracies.h | 2 +- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h index 20982e9beaa..8b4605c33e9 100644 --- a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h +++ b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h @@ -657,7 +657,7 @@ public: std::cout << "> Extract possibly non-manifold wrap... ()" << std::endl; #endif - clear(output_mesh); + empty(output_mesh); CGAL_assertion_code(for(auto cit=m_dt.finite_cells_begin(), cend=m_dt.finite_cells_end(); cit!=cend; ++cit)) CGAL_assertion(cit->tds_data().is_clear()); @@ -745,7 +745,7 @@ public: CGAL_assertion_code(for(Vertex_handle v : m_dt.finite_vertex_handles())) CGAL_assertion(!is_non_manifold(v)); - clear(output_mesh); + empty(output_mesh); // boundary faces to polygon soup std::vector points; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h index ee92e8e3640..12d6485e755 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h @@ -738,7 +738,7 @@ bool clip(TriangleMesh& tm, case ON_NEGATIVE_SIDE: return true; // nothing to clip, the full mesh is on the negative side case ON_POSITIVE_SIDE: - clear(tm); // clear the mesh that is fully on the positive side + empty(tm); // clear the mesh that is fully on the positive side return true; default: break; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h index 525f020a342..82ccbaf3605 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h @@ -423,7 +423,7 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh, if(nb_components_to_keep == 0) { - CGAL::clear(pmesh); + empty(pmesh); return num; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h index 1100d638cfa..032ba38ed35 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h @@ -266,11 +266,11 @@ corefine_and_compute_boolean_operations( if (output[Corefinement::TM1_MINUS_TM2] != boost::none) if (&tm1 == *output[Corefinement::TM1_MINUS_TM2]) - clear(tm1); + empty(tm1); if (output[Corefinement::TM2_MINUS_TM1] != boost::none) if (&tm1 == *output[Corefinement::TM2_MINUS_TM1]) - clear(tm1); + empty(tm1); return CGAL::make_array(true, true, true, true); } @@ -282,7 +282,7 @@ corefine_and_compute_boolean_operations( { for (int i=0; i<4; ++i) if (output[i] != boost::none) - clear(*(*output[i])); + empty(*(*output[i])); return CGAL::make_array(true, true, true, true); } // tm2 is not empty @@ -293,9 +293,9 @@ corefine_and_compute_boolean_operations( parameters::vertex_point_map(vpm2), parameters::vertex_point_map(*std::get(vpm_out_tuple))); if (output[Corefinement::INTERSECTION] != boost::none) - clear(*(*output[Corefinement::INTERSECTION])); + empty(*(*output[Corefinement::INTERSECTION])); if (output[Corefinement::TM1_MINUS_TM2] != boost::none) - clear(*(*output[Corefinement::TM1_MINUS_TM2])); + empty(*(*output[Corefinement::TM1_MINUS_TM2])); if (output[Corefinement::TM2_MINUS_TM1] != boost::none) if (&tm2 != *output[Corefinement::TM2_MINUS_TM1]) copy_face_graph(tm2, @@ -315,9 +315,9 @@ corefine_and_compute_boolean_operations( parameters::vertex_point_map(vpm1), parameters::vertex_point_map(*std::get(vpm_out_tuple))); if (output[Corefinement::INTERSECTION] != boost::none) - clear(*(*output[Corefinement::INTERSECTION])); + empty(*(*output[Corefinement::INTERSECTION])); if (output[Corefinement::TM2_MINUS_TM1] != boost::none) - clear(*(*output[Corefinement::TM2_MINUS_TM1])); + empty(*(*output[Corefinement::TM2_MINUS_TM1])); if (output[Corefinement::TM1_MINUS_TM2] != boost::none) if (&tm1 != *output[Corefinement::TM1_MINUS_TM2]) copy_face_graph(tm1, diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh_planar_patches.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh_planar_patches.h index fd007d5915f..c7f36dca6ee 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh_planar_patches.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh_planar_patches.h @@ -1265,8 +1265,7 @@ bool decimate_meshes_with_common_interfaces_impl(TriangleMeshRange& meshes, } CGAL_assertion(is_polygon_soup_a_polygon_mesh(all_faces[mesh_id])); - //clear(tm); - tm.clear_without_removing_property_maps(); + empty(tm); polygon_soup_to_polygon_mesh(all_corners[mesh_id], all_faces[mesh_id], tm, parameters::default_values(), parameters::vertex_point_map(vpms[mesh_id])); } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h index 798499f430b..b4a7e06e587 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h @@ -1934,7 +1934,7 @@ bool remove_degenerate_faces(const FaceRange& face_range, if(degenerate_face_set.size() == faces_size) { - clear(tmesh); + empty(tmesh); return true; } From 34a9756836abc8c126d6651c4ac2f3c634791506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 15 May 2023 12:42:13 +0200 Subject: [PATCH 4/8] Use BGL API instead of assuming graph.clear() exists --- BGL/include/CGAL/boost/graph/IO/STL.h | 2 +- BGL/include/CGAL/boost/graph/IO/polygon_mesh_io.h | 8 ++++---- BGL/test/BGL/test_Face_filtered_graph.cpp | 2 +- BGL/test/BGL/test_bgl_read_write.cpp | 7 +++---- .../cc_compatible_orientations.cpp | 2 +- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/IO/STL.h b/BGL/include/CGAL/boost/graph/IO/STL.h index 7198d8640aa..f2058b59b6e 100644 --- a/BGL/include/CGAL/boost/graph/IO/STL.h +++ b/BGL/include/CGAL/boost/graph/IO/STL.h @@ -172,7 +172,7 @@ bool read_STL(const std::string& fname, { return true; } - g.clear(); + clear(g); } std::ifstream is(fname); CGAL::IO::set_mode(is, CGAL::IO::ASCII); diff --git a/BGL/include/CGAL/boost/graph/IO/polygon_mesh_io.h b/BGL/include/CGAL/boost/graph/IO/polygon_mesh_io.h index d60af3c9949..5934821c4be 100644 --- a/BGL/include/CGAL/boost/graph/IO/polygon_mesh_io.h +++ b/BGL/include/CGAL/boost/graph/IO/polygon_mesh_io.h @@ -45,25 +45,25 @@ bool read_polygon_mesh(std::istream& is, ok = read_OFF(is, g, np, false); if(ok) return true; - g.clear(); + clear(g); is.clear();//reset the error state is.seekg (0, is.beg); ok = read_OBJ(is, g, np, false); if(ok) return true; - g.clear(); + clear(g); is.clear(); is.seekg (0, is.beg); ok = read_PLY(is, g, np, false); if(ok) return true; - g.clear(); + clear(g); is.clear(); is.seekg (0, is.beg); ok = read_STL(is, g, np, false); if(ok) return true; - g.clear(); + clear(g); is.clear(); is.seekg (0, is.beg); ok = read_GOCAD(is, g, np, false); diff --git a/BGL/test/BGL/test_Face_filtered_graph.cpp b/BGL/test/BGL/test_Face_filtered_graph.cpp index 2bab2e1d83c..bc6d1c13880 100644 --- a/BGL/test/BGL/test_Face_filtered_graph.cpp +++ b/BGL/test/BGL/test_Face_filtered_graph.cpp @@ -489,7 +489,7 @@ void test_invalid_selections() assert(pinched_fg.is_selection_valid()); // this creates a non-manifold vertex (multiple umbrellas) - clear(mesh); + CGAL::clear(mesh); read_a_mesh(mesh, "data/genus3.off"); assert(is_valid_polygon_mesh(mesh)); diff --git a/BGL/test/BGL/test_bgl_read_write.cpp b/BGL/test/BGL/test_bgl_read_write.cpp index 694c8a9933f..962a53ba541 100644 --- a/BGL/test/BGL/test_bgl_read_write.cpp +++ b/BGL/test/BGL/test_bgl_read_write.cpp @@ -122,7 +122,7 @@ void test_bgl_OFF(const std::string filename) assert(ok); assert(num_vertices(fg) != 0 && num_faces(fg) != 0); is.close(); - fg.clear(); + CGAL::clear(fg); is.open(filename, std::ios::binary); ok = CGAL::IO::read_OFF(is, fg); @@ -286,7 +286,7 @@ void test_bgl_OFF(const std::string filename) for(auto f : faces(fg)) assert(get(fcm2, f) != CGAL::IO::Color()); - fg.clear(); + CGAL::clear(fg); is.close(); is.open("data/full.off"); @@ -478,7 +478,7 @@ void test_bgl_PLY(const std::string filename, assert(filename != CGAL::data_file_path("meshes/colored_tetra.ply") || (num_vertices(fg) == 4 && num_faces(fg) == 4)); if(!binary) { - fg.clear(); + CGAL::clear(fg); is.open(filename, std::ios::binary); bool ok = CGAL::IO::read_PLY(is, fg, CGAL::parameters::use_binary_mode(false)); is.close(); @@ -711,7 +711,6 @@ void test_bgl_GOCAD(const char* filename) assert(num_vertices(fg) != 0 && num_faces(fg) != 0); is.seekg(0); - fg.clear(); CGAL::clear(fg); std::pair name_and_color; ok = CGAL::IO::read_GOCAD(is, name_and_color, fg); diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/cc_compatible_orientations.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/cc_compatible_orientations.cpp index 8a47239c5aa..ceba3dfb22a 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/cc_compatible_orientations.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/cc_compatible_orientations.cpp @@ -43,7 +43,7 @@ void create_mesh_with_cc_to_orient(Mesh& mesh) } // load the soup into the mesh; - mesh.clear(); + CGAL::clear(mesh); PMP::polygon_soup_to_polygon_mesh(points, triangles, mesh); } From 7a2e5412e942a0acfd11d2bc0c81c380ba9867bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 15 May 2023 12:42:42 +0200 Subject: [PATCH 5/8] Clarify that empty() does not clean garbage or remove property maps --- BGL/include/CGAL/boost/graph/helpers.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BGL/include/CGAL/boost/graph/helpers.h b/BGL/include/CGAL/boost/graph/helpers.h index 27677cdfe7d..185a00239a3 100644 --- a/BGL/include/CGAL/boost/graph/helpers.h +++ b/BGL/include/CGAL/boost/graph/helpers.h @@ -945,6 +945,9 @@ void swap_edges(const typename boost::graph_traits::halfedge_descript * \link MutableHalfedgeGraph `remove_edge()`\endlink, and * \link MutableFaceGraph `remove_face()`\endlink, for each vertex, edge, and face. * + * @warning This function does not perform anything more than what is advertised above. It is + * up to the user to e.g. clean garbage or remove internal property maps (if relevant, and desired). + * * @tparam FaceGraph model of `MutableHalfedgeGraph` and `MutableFaceGraph` * * @param g the graph to empty From a69a2f54c6f36e2b56119e3290c0ccb0625a8d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 16 May 2023 14:21:27 +0200 Subject: [PATCH 6/8] Rename to avoid conflict with STL --- .../CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h | 4 ++-- BGL/doc/BGL/PackageDescription.txt | 2 +- BGL/include/CGAL/boost/graph/helpers.h | 8 ++++---- .../include/CGAL/Polygon_mesh_processing/clip.h | 2 +- .../Polygon_mesh_processing/connected_components.h | 2 +- .../CGAL/Polygon_mesh_processing/corefinement.h | 14 +++++++------- .../remesh_planar_patches.h | 2 +- .../Polygon_mesh_processing/repair_degeneracies.h | 2 +- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h index 8b4605c33e9..3fc3cac0d7a 100644 --- a/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h +++ b/Alpha_wrap_3/include/CGAL/Alpha_wrap_3/internal/Alpha_wrap_3.h @@ -657,7 +657,7 @@ public: std::cout << "> Extract possibly non-manifold wrap... ()" << std::endl; #endif - empty(output_mesh); + remove_all_elements(output_mesh); CGAL_assertion_code(for(auto cit=m_dt.finite_cells_begin(), cend=m_dt.finite_cells_end(); cit!=cend; ++cit)) CGAL_assertion(cit->tds_data().is_clear()); @@ -745,7 +745,7 @@ public: CGAL_assertion_code(for(Vertex_handle v : m_dt.finite_vertex_handles())) CGAL_assertion(!is_non_manifold(v)); - empty(output_mesh); + remove_all_elements(output_mesh); // boundary faces to polygon soup std::vector points; diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index 9524e2f8519..5e13aee9ea5 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -679,7 +679,7 @@ user might encounter. - `CGAL::make_grid()` - `CGAL::clear()` -- `CGAL::empty()` +- `CGAL::remove_all_elements()` - `CGAL::copy_face_graph()` - `CGAL::set_triangulation_ids()` diff --git a/BGL/include/CGAL/boost/graph/helpers.h b/BGL/include/CGAL/boost/graph/helpers.h index 185a00239a3..ee0247330bd 100644 --- a/BGL/include/CGAL/boost/graph/helpers.h +++ b/BGL/include/CGAL/boost/graph/helpers.h @@ -950,12 +950,12 @@ void swap_edges(const typename boost::graph_traits::halfedge_descript * * @tparam FaceGraph model of `MutableHalfedgeGraph` and `MutableFaceGraph` * - * @param g the graph to empty + * @param g the graph whose elements will be removed * * @sa `CGAL::clear()` **/ template -void empty(FaceGraph& g) +void remove_all_elements(FaceGraph& g) { while(std::begin(edges(g)) != std::end(edges(g))) remove_edge(*std::begin(edges(g)), g); @@ -984,7 +984,7 @@ inline std::enable_if_t::value, void> clear_impl(FaceGraph& g) { - empty(g); + remove_all_elements(g); } } // namespace internal @@ -1008,7 +1008,7 @@ clear_impl(FaceGraph& g) * * @param g the graph to clear * - * @sa `CGAL::empty()` + * @sa `CGAL::remove_all_elements()` **/ template void clear(FaceGraph& g) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h index 12d6485e755..2bed4379c25 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h @@ -738,7 +738,7 @@ bool clip(TriangleMesh& tm, case ON_NEGATIVE_SIDE: return true; // nothing to clip, the full mesh is on the negative side case ON_POSITIVE_SIDE: - empty(tm); // clear the mesh that is fully on the positive side + remove_all_elements(tm); // clear the mesh that is fully on the positive side return true; default: break; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h index 82ccbaf3605..1eb7acdd982 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h @@ -423,7 +423,7 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh, if(nb_components_to_keep == 0) { - empty(pmesh); + remove_all_elements(pmesh); return num; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h index 032ba38ed35..fa467c5a739 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h @@ -266,11 +266,11 @@ corefine_and_compute_boolean_operations( if (output[Corefinement::TM1_MINUS_TM2] != boost::none) if (&tm1 == *output[Corefinement::TM1_MINUS_TM2]) - empty(tm1); + remove_all_elements(tm1); if (output[Corefinement::TM2_MINUS_TM1] != boost::none) if (&tm1 == *output[Corefinement::TM2_MINUS_TM1]) - empty(tm1); + remove_all_elements(tm1); return CGAL::make_array(true, true, true, true); } @@ -282,7 +282,7 @@ corefine_and_compute_boolean_operations( { for (int i=0; i<4; ++i) if (output[i] != boost::none) - empty(*(*output[i])); + remove_all_elements(*(*output[i])); return CGAL::make_array(true, true, true, true); } // tm2 is not empty @@ -293,9 +293,9 @@ corefine_and_compute_boolean_operations( parameters::vertex_point_map(vpm2), parameters::vertex_point_map(*std::get(vpm_out_tuple))); if (output[Corefinement::INTERSECTION] != boost::none) - empty(*(*output[Corefinement::INTERSECTION])); + remove_all_elements(*(*output[Corefinement::INTERSECTION])); if (output[Corefinement::TM1_MINUS_TM2] != boost::none) - empty(*(*output[Corefinement::TM1_MINUS_TM2])); + remove_all_elements(*(*output[Corefinement::TM1_MINUS_TM2])); if (output[Corefinement::TM2_MINUS_TM1] != boost::none) if (&tm2 != *output[Corefinement::TM2_MINUS_TM1]) copy_face_graph(tm2, @@ -315,9 +315,9 @@ corefine_and_compute_boolean_operations( parameters::vertex_point_map(vpm1), parameters::vertex_point_map(*std::get(vpm_out_tuple))); if (output[Corefinement::INTERSECTION] != boost::none) - empty(*(*output[Corefinement::INTERSECTION])); + remove_all_elements(*(*output[Corefinement::INTERSECTION])); if (output[Corefinement::TM2_MINUS_TM1] != boost::none) - empty(*(*output[Corefinement::TM2_MINUS_TM1])); + remove_all_elements(*(*output[Corefinement::TM2_MINUS_TM1])); if (output[Corefinement::TM1_MINUS_TM2] != boost::none) if (&tm1 != *output[Corefinement::TM1_MINUS_TM2]) copy_face_graph(tm1, diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh_planar_patches.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh_planar_patches.h index c7f36dca6ee..7cb2b3e936e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh_planar_patches.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh_planar_patches.h @@ -1265,7 +1265,7 @@ bool decimate_meshes_with_common_interfaces_impl(TriangleMeshRange& meshes, } CGAL_assertion(is_polygon_soup_a_polygon_mesh(all_faces[mesh_id])); - empty(tm); + remove_all_elements(tm); polygon_soup_to_polygon_mesh(all_corners[mesh_id], all_faces[mesh_id], tm, parameters::default_values(), parameters::vertex_point_map(vpms[mesh_id])); } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h index b4a7e06e587..e41ea2bbf98 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h @@ -1934,7 +1934,7 @@ bool remove_degenerate_faces(const FaceRange& face_range, if(degenerate_face_set.size() == faces_size) { - empty(tmesh); + remove_all_elements(tmesh); return true; } From 146f9ecb21db4815354058f6e061ccffaf93df9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 19 Jul 2023 13:48:34 +0200 Subject: [PATCH 7/8] Add specializations for Surface_mesh and Polyhedron_3 --- BGL/include/CGAL/boost/graph/helpers.h | 3 +++ .../include/CGAL/boost/graph/graph_traits_Polyhedron_3.h | 6 ++++++ .../include/CGAL/boost/graph/graph_traits_Surface_mesh.h | 9 +++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/helpers.h b/BGL/include/CGAL/boost/graph/helpers.h index ee0247330bd..6b87731ad9b 100644 --- a/BGL/include/CGAL/boost/graph/helpers.h +++ b/BGL/include/CGAL/boost/graph/helpers.h @@ -945,6 +945,9 @@ void swap_edges(const typename boost::graph_traits::halfedge_descript * \link MutableHalfedgeGraph `remove_edge()`\endlink, and * \link MutableFaceGraph `remove_face()`\endlink, for each vertex, edge, and face. * + * Note that some graphs have a specialized version of this function to improve + * complexity. + * * @warning This function does not perform anything more than what is advertised above. It is * up to the user to e.g. clean garbage or remove internal property maps (if relevant, and desired). * diff --git a/Polyhedron/include/CGAL/boost/graph/graph_traits_Polyhedron_3.h b/Polyhedron/include/CGAL/boost/graph/graph_traits_Polyhedron_3.h index 8cff560f0a6..33a45710ab1 100644 --- a/Polyhedron/include/CGAL/boost/graph/graph_traits_Polyhedron_3.h +++ b/Polyhedron/include/CGAL/boost/graph/graph_traits_Polyhedron_3.h @@ -310,6 +310,12 @@ set_halfedge(typename boost::graph_traits< CGAL::Polyhedron_3 >::ver static_cast(*v).set_halfedge(h); } +template +void +remove_all_elements(CGAL::Polyhedron_3& g) +{ + g.clear(); +} // // HalfedgeGraph diff --git a/Surface_mesh/include/CGAL/boost/graph/graph_traits_Surface_mesh.h b/Surface_mesh/include/CGAL/boost/graph/graph_traits_Surface_mesh.h index d044c38a557..1a05f71bb9c 100644 --- a/Surface_mesh/include/CGAL/boost/graph/graph_traits_Surface_mesh.h +++ b/Surface_mesh/include/CGAL/boost/graph/graph_traits_Surface_mesh.h @@ -472,7 +472,6 @@ remove_vertex(typename boost::graph_traits >::vertex_descr sm.remove_vertex(v); } - template void remove_edge(typename boost::graph_traits >::vertex_descriptor u, @@ -491,7 +490,6 @@ remove_edge(typename boost::graph_traits >::edge_descripto sm.remove_edge(e); } - template void remove_edge(typename boost::graph_traits >::edge_iterator eiter, @@ -508,6 +506,13 @@ remove_face(typename boost::graph_traits >::face_descripto sm.remove_face(f); } +template +void +remove_all_elements(CGAL::Surface_mesh

& sm) +{ + sm.clear_without_removing_property_maps(); +} + template typename boost::graph_traits >::face_descriptor add_face(CGAL::Surface_mesh

& sm) From 15d7b65904e7a5cefcee2ef915e1ccf49e94c076 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 3 Apr 2024 13:59:04 +0100 Subject: [PATCH 8/8] Update change log --- Installation/CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 47998400268..14f6a9c0ee6 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -35,6 +35,10 @@ Release date: October 2023 - Removed the class templates `Gray_image_mesh_domain_3`, `Implicit_mesh_domain_3`, and `Labeled_image_mesh_domain_3` which are deprecated since CGAL-4.13. +### [CGAL and the Boost Graph Library (BGL)](https://doc.cgal.org/6.0/Manual/packages.html#PkgBGL) + +- Added the function `remove_all_elements()`, which removes vertices, halfedges, and faces + without collecting garbage and without removing properties. [Release 5.6](https://github.com/CGAL/cgal/releases/tag/v5.6) -----------