From fe407a701fa6d149abaf90b8c9b16a26f9abca4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 13 Apr 2018 14:54:29 +0200 Subject: [PATCH] add a function to merge vertices globally --- .../merge_border_vertices.h | 113 +++++++++++++----- .../test_merging_border_vertices.cpp | 44 ++++++- 2 files changed, 126 insertions(+), 31 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/merge_border_vertices.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/merge_border_vertices.h index 8b78ff256e5..76a0d132cca 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/merge_border_vertices.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/merge_border_vertices.h @@ -35,6 +35,46 @@ namespace CGAL{ namespace Polygon_mesh_processing{ +namespace internal { + +// warning: vertices will be altered (sorted) +template +void detect_identical_vertices(std::vector& vertices, + std::vector< std::vector >& identical_vertices, + Vpm vpm) +{ + typedef typename boost::property_traits::value_type Point_3; + + // sort vertices using their point to ease the detection + // of vertices with identical points + CGAL::Property_map_to_unary_function Get_point(vpm); + std::sort( vertices.begin(), vertices.end(), + boost::bind(std::less(), boost::bind(Get_point,_1), + boost::bind(Get_point, _2)) ); + std::size_t nbv=vertices.size(); + std::size_t i=1; + + while(i!=nbv) + { + if (get(vpm, vertices[i]) == get(vpm, vertices[i-1])) + { + identical_vertices.push_back( std::vector() ); + identical_vertices.back().push_back(vertices[i-1]); + identical_vertices.back().push_back(vertices[i]); + while(++i!=nbv) + { + if (get(vpm, vertices[i]) == get(vpm, vertices[i-1])) + identical_vertices.back().push_back(vertices[i]); + else + break; + } + } + ++i; + } +} + +} // end of internal + /// \todo document me /// It should probably go into BGL package template @@ -60,8 +100,8 @@ extract_boundary_cycles(PolygonMesh& pm, /// \ingroup PMP_repairing_grp /// \todo document me template -void merge_vertices(const VertexRange& vertices, - PolygonMesh& pm) +void merge_boundary_vertices(const VertexRange& vertices, + PolygonMesh& pm) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; @@ -102,7 +142,7 @@ void merge_duplicated_vertices_in_boundary_cycle(typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename GetVertexPointMap::const_type Vpm; - typedef typename boost::property_traits::value_type Point_3; + Vpm vpm = choose_param(get_param(np, internal_np::vertex_point), get_const_property_map(vertex_point, pm)); @@ -114,35 +154,11 @@ void merge_duplicated_vertices_in_boundary_cycle(typename boost::graph_traits Get_point(vpm); - std::sort( vertices.begin(), vertices.end(), - boost::bind(std::less(), boost::bind(Get_point,_1), - boost::bind(Get_point, _2)) ); - std::size_t nbv=vertices.size(); - std::size_t i=1; - std::vector< std::vector > identical_vertices; - while(i!=nbv) - { - if (get(vpm, vertices[i]) == get(vpm, vertices[i-1])) - { - identical_vertices.push_back( std::vector() ); - identical_vertices.back().push_back(vertices[i-1]); - identical_vertices.back().push_back(vertices[i]); - while(++i!=nbv) - { - if (get(vpm, vertices[i]) == get(vpm, vertices[i-1])) - identical_vertices.back().push_back(vertices[i]); - else - break; - } - } - ++i; - } + internal::detect_identical_vertices(vertices, identical_vertices, vpm); + BOOST_FOREACH(const std::vector& vrtcs, identical_vertices) - merge_vertices(vrtcs, pm); + merge_boundary_vertices(vrtcs, pm); } /// \ingroup PMP_repairing_grp @@ -160,6 +176,36 @@ void merge_duplicated_vertices_in_boundary_cycles( PolygonMesh& pm, merge_duplicated_vertices_in_boundary_cycle(h, pm, np); } + +/// \ingroup PMP_repairing_grp +/// \todo document me +template +void merge_duplicated_boundary_vertices( PolygonMesh& pm, + const NamedParameter& np) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename GetVertexPointMap::const_type Vpm; + + Vpm vpm = choose_param(get_param(np, internal_np::vertex_point), + get_const_property_map(vertex_point, pm)); + + std::vector border_vertices; + BOOST_FOREACH(halfedge_descriptor h, halfedges(pm)) + { + if(is_border(h, pm)) + border_vertices.push_back(target(h, pm)); + } + + std::vector< std::vector > identical_vertices; + internal::detect_identical_vertices(border_vertices, identical_vertices, vpm); + + BOOST_FOREACH(const std::vector& vrtcs, identical_vertices) + merge_boundary_vertices(vrtcs, pm); +} + + + template void merge_duplicated_vertices_in_boundary_cycles(PolygonMesh& pm) { @@ -174,6 +220,13 @@ void merge_duplicated_vertices_in_boundary_cycle( merge_duplicated_vertices_in_boundary_cycles(h, pm, parameters::all_default()); } +template +void merge_duplicated_boundary_vertices(PolygonMesh& pm) +{ + merge_duplicated_boundary_vertices(pm, parameters::all_default()); +} + + } } // end of CGAL::Polygon_mesh_processing #endif //CGAL_POLYGON_MESH_PROCESSING_MERGE_BORDER_VERTICES_H diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_merging_border_vertices.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_merging_border_vertices.cpp index fc749d88373..1abc453207a 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_merging_border_vertices.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_merging_border_vertices.cpp @@ -22,22 +22,64 @@ void test_merge_duplicated_vertices_in_boundary_cycles(const char* fname, exit(1); } - std::cout << "Testing " << fname << "\n"; + std::cout << "Testing merging in cycles " << fname << "\n"; std::cout << " input mesh has " << vertices(mesh).size() << " vertices.\n"; CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycles(mesh); std::cout << " output mesh has " << vertices(mesh).size() << " vertices.\n"; assert(expected_nb_vertices==0 || expected_nb_vertices == vertices(mesh).size()); + if (expected_nb_vertices==0) + { + std::cout << "writting output to out1.off\n"; + std::ofstream output("out1.off"); + output << std::setprecision(17); + output << mesh; + } +} + +void test_merge_duplicated_boundary_vertices(const char* fname, + std::size_t expected_nb_vertices) +{ + std::ifstream input(fname); + + Surface_mesh mesh; + if (!input || !(input >> mesh) || mesh.is_empty()) { + std::cerr << fname << " is not a valid off file.\n"; + exit(1); + } + + std::cout << "Testing merging globally " << fname << "\n"; + std::cout << " input mesh has " << vertices(mesh).size() << " vertices.\n"; + CGAL::Polygon_mesh_processing::merge_duplicated_boundary_vertices(mesh); + std::cout << " output mesh has " << vertices(mesh).size() << " vertices.\n"; + + assert(expected_nb_vertices == 0 || + expected_nb_vertices == vertices(mesh).size()); + if (expected_nb_vertices==0) + { + std::cout << "writting output to out2.off\n"; + std::ofstream output("out2.off"); + output << std::setprecision(17); + output << mesh; + } } int main(int argc, char** argv) { if (argc==1) + { test_merge_duplicated_vertices_in_boundary_cycles("data/merge_points.off", 43); + test_merge_duplicated_boundary_vertices("data/merge_points.off", 40); + } else + { for (int i=1; i< argc; ++i) + { test_merge_duplicated_vertices_in_boundary_cycles(argv[i], 0); + test_merge_duplicated_boundary_vertices(argv[i], 0); + } + } return 0; }