From 0675a0d55ec2f55a5d6a369fda5f047cf3735270 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 12 Mar 2021 17:00:44 +0100 Subject: [PATCH 01/28] WIP --- .../compare_meshes_example.cpp | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp new file mode 100644 index 00000000000..266bcda23cf --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp @@ -0,0 +1,123 @@ +#include +#include + +#include +#include + +#include +#include + +namespace CGAL{ +namespace Polygon_mesh_processing{ +namespace internal { +template +void diff(const TriangleMesh& m1, const TriangleMesh& m2, bool compute_common = false) +{ + std::map point_id_map; + std::vector m1_vertex_id(num_vertices(m1), -1); + std::vector m2_vertex_id(num_vertices(m2), -1); + + //iterate both meshes to set ids to all points, and set vertex/point_id maps. + std::size_t id =0; + for(auto v : vertices(m1)) + { + Point_3 p = m1->point(v); + auto res = point_id_map.insert(std::make_pair(p, id)); + if(res.second) + id++; + m1_vertex_id[(std::size_t)v]=res.first->second; + } + for(auto v : vertices(m2)) + { + Point_3 p = m2->point(v); + auto res = point_id_map.insert(std::make_pair(p, id)); + if(res.second) + id++; + m2_vertex_id[(std::size_t)v]=res.first->second; + } + + //fill a set with the "faces point-ids" of m1 and then iterate faces of m2 to compare. + std::set > m1_faces; + for(auto f : m1->faces()) + { + std::vector ids; + for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) + { + ids.push_back(m1_vertex_id[(std::size_t)v]); + } + std::sort(ids.begin(), ids.end()); + m1_faces.insert(ids); + } + + std::vector common_faces; + id = 0; + + for(auto f : faces(m2)) + { + std::vector ids; + for(auto v : CGAL::vertices_around_face(halfedge(f, m2), m2)) + { + ids.push_back(m2_vertex_id[(std::size_t)v]); + } + std::sort(ids.begin(), ids.end()); + if(!((m1_faces.find(ids) != m1_faces.end()) ^ compute_common)) + { + common_faces.push_back(f); + } + } +} + +} +template +void compare_meshes(const TriangleMesh& tm1, const TriangleMesh& tm2, + FacePairRange& common, FaceRange tm1_only, FaceRange tm2_only) +{ + + SMesh* m1_over_m2 = diff(m1, m2); + SMesh* m2_over_m1 = diff(m2, m1); + SMesh* common = diff(m2, m1, true); + + Scene_surface_mesh_item* m1_over_m2_item = new Scene_surface_mesh_item(m1_over_m2); + m1_over_m2_item->setColor(QColor(Qt::blue)); + m1_over_m2_item->setName(QString("%2 - %1").arg(m1_item->name()).arg(m2_item->name())); + CGAL::Three::Three::scene()->addItem(m1_over_m2_item); + Scene_surface_mesh_item* m2_over_m1_item = new Scene_surface_mesh_item(m2_over_m1); + m2_over_m1_item->setColor(QColor(Qt::red)); + m2_over_m1_item->setName(QString("%1 - %2").arg(m1_item->name()).arg(m2_item->name())); + CGAL::Three::Three::scene()->addItem(m2_over_m1_item); + Scene_surface_mesh_item* common_item = new Scene_surface_mesh_item(common); + common_item->setColor(QColor(Qt::green)); + CGAL::Three::Three::scene()->addItem(common_item); + common_item->setName(QString("%1 && %2").arg(m1_item->name()).arg(m2_item->name())); +} + +} +} +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef K::Point_3 Point; + +typedef CGAL::Surface_mesh Surface_mesh; +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits::face_descriptor face_descriptor; +namespace PMP = CGAL::Polygon_mesh_processing; + +int main(int argc, char* argv[]) +{ + const char* filename1 = (argc > 1) ? argv[1] : "data/eight.off"; + const char* filename2 = (argc > 2) ? argv[2] : "data/eight-bis.off"; + + Surface_mesh mesh1, mesh2; + if(!PMP::read_polygon_mesh(filename1, mesh1)) + { + std::cerr << "Invalid input." << std::endl; + return 1; + } + if(!PMP::read_polygon_mesh(filename2, mesh2)) + { + std::cerr << "Invalid input." << std::endl; + return 1; + } + + return 0; +} From 96a88df41b0df75978d96088d86b02a7ceb06b7c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 16 Mar 2021 16:00:10 +0100 Subject: [PATCH 02/28] Working example. --- .../Polygon_mesh_processing/CMakeLists.txt | 1 + .../compare_meshes_example.cpp | 109 +++++++++++------- 2 files changed, 68 insertions(+), 42 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index f979cf8cad3..991bfddca85 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -90,6 +90,7 @@ create_single_source_cgal_program("locate_example.cpp") create_single_source_cgal_program("orientation_pipeline_example.cpp") #create_single_source_cgal_program( "self_snapping_example.cpp") #create_single_source_cgal_program( "snapping_example.cpp") +create_single_source_cgal_program("compare_meshes_example.cpp") if(OpenMesh_FOUND) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp index 266bcda23cf..05b989e0b29 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp @@ -3,16 +3,33 @@ #include #include +#include +#include #include #include namespace CGAL{ namespace Polygon_mesh_processing{ -namespace internal { -template -void diff(const TriangleMesh& m1, const TriangleMesh& m2, bool compute_common = false) +//todo face_descriptor ça doit etre le facerange::value_type je pense. checker le c++20 de value_type par contre +template +void compare_meshes(const TriangleMesh& m1, const TriangleMesh& m2, + FacePairRange& common, FaceRange& tm1_only, FaceRange& tm2_only, + const NamedParameters1& np1,const NamedParameters2& np2) { + using parameters::choose_parameter; + using parameters::get_parameter; + typedef typename GetVertexPointMap < TriangleMesh, NamedParameters1>::const_type VPMap1; + typedef typename GetVertexPointMap < TriangleMesh, NamedParameters2>::const_type VPMap2; + VPMap1 vpm1 = choose_parameter(get_parameter(np1, internal_np::vertex_point), + get_const_property_map(vertex_point, m1)); + VPMap2 vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), + get_const_property_map(vertex_point, m2)); + typedef typename boost::property_traits::value_type Point_3; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + + std::map point_id_map; std::vector m1_vertex_id(num_vertices(m1), -1); std::vector m2_vertex_id(num_vertices(m2), -1); @@ -21,7 +38,7 @@ void diff(const TriangleMesh& m1, const TriangleMesh& m2, bool compute_common = std::size_t id =0; for(auto v : vertices(m1)) { - Point_3 p = m1->point(v); + const Point_3& p = get(vpm1, v); auto res = point_id_map.insert(std::make_pair(p, id)); if(res.second) id++; @@ -29,7 +46,7 @@ void diff(const TriangleMesh& m1, const TriangleMesh& m2, bool compute_common = } for(auto v : vertices(m2)) { - Point_3 p = m2->point(v); + const Point_3& p = get(vpm2, v); auto res = point_id_map.insert(std::make_pair(p, id)); if(res.second) id++; @@ -38,7 +55,7 @@ void diff(const TriangleMesh& m1, const TriangleMesh& m2, bool compute_common = //fill a set with the "faces point-ids" of m1 and then iterate faces of m2 to compare. std::set > m1_faces; - for(auto f : m1->faces()) + for(auto f : faces(m1)) { std::vector ids; for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) @@ -48,10 +65,7 @@ void diff(const TriangleMesh& m1, const TriangleMesh& m2, bool compute_common = std::sort(ids.begin(), ids.end()); m1_faces.insert(ids); } - - std::vector common_faces; - id = 0; - + std::map, face_descriptor> m2_faces_map; for(auto f : faces(m2)) { std::vector ids; @@ -60,39 +74,33 @@ void diff(const TriangleMesh& m1, const TriangleMesh& m2, bool compute_common = ids.push_back(m2_vertex_id[(std::size_t)v]); } std::sort(ids.begin(), ids.end()); - if(!((m1_faces.find(ids) != m1_faces.end()) ^ compute_common)) + m2_faces_map.insert({ids, f}); + if(m1_faces.find(ids) == m1_faces.end()) { + tm2_only.push_back(f); + } + } + + for(auto f : faces(m1)) + { + std::vector ids; + for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) { - common_faces.push_back(f); + ids.push_back(m1_vertex_id[(std::size_t)v]); + } + std::sort(ids.begin(), ids.end()); + auto m2_face_it = m2_faces_map.find(ids); + if(m2_face_it == m2_faces_map.end()) + { + tm1_only.push_back(f); + } + else + { + common.push_back(std::make_pair(f, m2_face_it->second)); } } } - -} -template -void compare_meshes(const TriangleMesh& tm1, const TriangleMesh& tm2, - FacePairRange& common, FaceRange tm1_only, FaceRange tm2_only) -{ - - SMesh* m1_over_m2 = diff(m1, m2); - SMesh* m2_over_m1 = diff(m2, m1); - SMesh* common = diff(m2, m1, true); - - Scene_surface_mesh_item* m1_over_m2_item = new Scene_surface_mesh_item(m1_over_m2); - m1_over_m2_item->setColor(QColor(Qt::blue)); - m1_over_m2_item->setName(QString("%2 - %1").arg(m1_item->name()).arg(m2_item->name())); - CGAL::Three::Three::scene()->addItem(m1_over_m2_item); - Scene_surface_mesh_item* m2_over_m1_item = new Scene_surface_mesh_item(m2_over_m1); - m2_over_m1_item->setColor(QColor(Qt::red)); - m2_over_m1_item->setName(QString("%1 - %2").arg(m1_item->name()).arg(m2_item->name())); - CGAL::Three::Three::scene()->addItem(m2_over_m1_item); - Scene_surface_mesh_item* common_item = new Scene_surface_mesh_item(common); - common_item->setColor(QColor(Qt::green)); - CGAL::Three::Three::scene()->addItem(common_item); - common_item->setName(QString("%1 && %2").arg(m1_item->name()).arg(m2_item->name())); -} - -} -} +}//pmp +}//cgal typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point; @@ -104,8 +112,8 @@ namespace PMP = CGAL::Polygon_mesh_processing; int main(int argc, char* argv[]) { - const char* filename1 = (argc > 1) ? argv[1] : "data/eight.off"; - const char* filename2 = (argc > 2) ? argv[2] : "data/eight-bis.off"; + const char* filename1 = (argc > 1) ? argv[1] : "data/tet.off"; + const char* filename2 = (argc > 2) ? argv[2] : "data/tet-bis.off"; Surface_mesh mesh1, mesh2; if(!PMP::read_polygon_mesh(filename1, mesh1)) @@ -118,6 +126,23 @@ int main(int argc, char* argv[]) std::cerr << "Invalid input." << std::endl; return 1; } - + std::vector > common; + std::vector m1_only, m2_only; + PMP::compare_meshes(mesh1, mesh2, common, m1_only, m2_only, CGAL::parameters::all_default(), CGAL::parameters::all_default()); + std::cout<<"Faces only in m1 : "< Date: Mon, 22 Mar 2021 14:02:18 +0100 Subject: [PATCH 03/28] doc + example + tests --- .../compare_meshes_example.cpp | 92 ------------- .../Polygon_mesh_processing/data/tet-bis.off | 35 +++++ .../Polygon_mesh_processing/data/tet.off | 35 +++++ .../CGAL/Polygon_mesh_processing/measure.h | 121 ++++++++++++++++++ .../data/cube_quad2.off | 41 ++++++ .../Polygon_mesh_processing/data/tri1.off | 61 +++++++++ .../Polygon_mesh_processing/data/tri2.off | 61 +++++++++ .../Polygon_mesh_processing/measures_test.cpp | 87 +++++++++++++ 8 files changed, 441 insertions(+), 92 deletions(-) create mode 100644 Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet-bis.off create mode 100644 Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data/cube_quad2.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri1.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri2.off diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp index 05b989e0b29..d821caf6fef 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp @@ -9,98 +9,6 @@ #include #include -namespace CGAL{ -namespace Polygon_mesh_processing{ -//todo face_descriptor ça doit etre le facerange::value_type je pense. checker le c++20 de value_type par contre -template -void compare_meshes(const TriangleMesh& m1, const TriangleMesh& m2, - FacePairRange& common, FaceRange& tm1_only, FaceRange& tm2_only, - const NamedParameters1& np1,const NamedParameters2& np2) -{ - using parameters::choose_parameter; - using parameters::get_parameter; - typedef typename GetVertexPointMap < TriangleMesh, NamedParameters1>::const_type VPMap1; - typedef typename GetVertexPointMap < TriangleMesh, NamedParameters2>::const_type VPMap2; - VPMap1 vpm1 = choose_parameter(get_parameter(np1, internal_np::vertex_point), - get_const_property_map(vertex_point, m1)); - VPMap2 vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), - get_const_property_map(vertex_point, m2)); - typedef typename boost::property_traits::value_type Point_3; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - - - - std::map point_id_map; - std::vector m1_vertex_id(num_vertices(m1), -1); - std::vector m2_vertex_id(num_vertices(m2), -1); - - //iterate both meshes to set ids to all points, and set vertex/point_id maps. - std::size_t id =0; - for(auto v : vertices(m1)) - { - const Point_3& p = get(vpm1, v); - auto res = point_id_map.insert(std::make_pair(p, id)); - if(res.second) - id++; - m1_vertex_id[(std::size_t)v]=res.first->second; - } - for(auto v : vertices(m2)) - { - const Point_3& p = get(vpm2, v); - auto res = point_id_map.insert(std::make_pair(p, id)); - if(res.second) - id++; - m2_vertex_id[(std::size_t)v]=res.first->second; - } - - //fill a set with the "faces point-ids" of m1 and then iterate faces of m2 to compare. - std::set > m1_faces; - for(auto f : faces(m1)) - { - std::vector ids; - for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) - { - ids.push_back(m1_vertex_id[(std::size_t)v]); - } - std::sort(ids.begin(), ids.end()); - m1_faces.insert(ids); - } - std::map, face_descriptor> m2_faces_map; - for(auto f : faces(m2)) - { - std::vector ids; - for(auto v : CGAL::vertices_around_face(halfedge(f, m2), m2)) - { - ids.push_back(m2_vertex_id[(std::size_t)v]); - } - std::sort(ids.begin(), ids.end()); - m2_faces_map.insert({ids, f}); - if(m1_faces.find(ids) == m1_faces.end()) { - tm2_only.push_back(f); - } - } - - for(auto f : faces(m1)) - { - std::vector ids; - for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) - { - ids.push_back(m1_vertex_id[(std::size_t)v]); - } - std::sort(ids.begin(), ids.end()); - auto m2_face_it = m2_faces_map.find(ids); - if(m2_face_it == m2_faces_map.end()) - { - tm1_only.push_back(f); - } - else - { - common.push_back(std::make_pair(f, m2_face_it->second)); - } - } -} -}//pmp -}//cgal typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point; diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet-bis.off b/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet-bis.off new file mode 100644 index 00000000000..18a3647c547 --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet-bis.off @@ -0,0 +1,35 @@ +# Output of a CGAL tool +#CBP +# polyhedral_surface 0 +# halfedges 0 +# triangulated 0 +# non_empty_facets 0 +# terrain 0 +# normalized_to_sphere 0 +# radius 0 +# rounded 0 +# rounded_bits 0 +# ENDCBP + +NOFF +4 4 0 + +# 4 vertices +# ------------------------------------------ + + +0 0 0 -0.57735 -0.57735 -0.57735 +1 0 0 0.935113 -0.250563 -0.250563 +0 1 0 -0.250563 0.935113 -0.250563 +0 0 1 -0.250563 -0.250563 0.935113 + +# 4 facets +# ------------------------------------------ + +3 2 1 0 +3 0 3 2 +3 2 3 1 +3 1 3 0 + + +# End of OFF # diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet.off b/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet.off new file mode 100644 index 00000000000..d198868a0c5 --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet.off @@ -0,0 +1,35 @@ +# Output of a CGAL tool +#CBP +# polyhedral_surface 0 +# halfedges 0 +# triangulated 0 +# non_empty_facets 0 +# terrain 0 +# normalized_to_sphere 0 +# radius 0 +# rounded 0 +# rounded_bits 0 +# ENDCBP + +NOFF +4 4 0 + +# 4 vertices +# ------------------------------------------ + + +0.0521823 0.0693697 0.0558329 -0.57735 -0.57735 -0.57735 +1 0 0 0.935113 -0.250563 -0.250563 +0 1 0 -0.250563 0.935113 -0.250563 +0 0 1 -0.250563 -0.250563 0.935113 + +# 4 facets +# ------------------------------------------ + +3 2 1 0 +3 0 3 2 +3 2 3 1 +3 1 3 0 + + +# End of OFF # diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 911087ac7b9..6ac978da837 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -820,6 +820,127 @@ centroid(const TriangleMesh& tmesh) return centroid(tmesh, CGAL::Polygon_mesh_processing::parameters::all_default()); } + +/** + * \ingroup measure_grp + * given two meshes, separates the faces that are only in one, the faces + * that are only in the other one, and the faces that are common to both. + * + * @tparam PolygonMesh a model of `HalfedgeListGraph` and `FaceListGraph` + * \tparam FaceRange a range of `boost::graph_traits::%face_descriptor` + * @tparam FacePairRange a range of `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` + * + * @tparam NamedParameters1 a sequence of \ref bgl_namedparameters "Named Parameters" + * @tparam NamedParameters2 a sequence of \ref bgl_namedparameters "Named Parameters" + * + * @param m1 the first `PolygonMesh` + * @param m2 the second `PolygonMesh` + * @param common the range containing the faces that are common to both meshes. + * @param m1_only the range containing the faces that are only in `m1` + * @param m2_only the range containing the faces that are only in `m2` + * @param np1 an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below + * @param np2 an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamNBegin{vertex_point_map} + * \cgalParamDescription{a property map associating points to the vertices of `m1` (`m2`)} + * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` + * as key type and `%Point_3` as value type} + * \cgalParamDefault{`boost::get(CGAL::vertex_point, m1 (m2))`} + * \cgalParamNEnd + * \cgalNamedParamsEnd + * + */ +template +void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, + FacePairRange& common, FaceRange& m1_only, FaceRange& m2_only, + const NamedParameters1& np1,const NamedParameters2& np2) +{ + using parameters::choose_parameter; + using parameters::get_parameter; + typedef typename GetVertexPointMap < PolygonMesh, NamedParameters1>::const_type VPMap1; + typedef typename GetVertexPointMap < PolygonMesh, NamedParameters2>::const_type VPMap2; + typedef typename GetInitializedVertexIndexMap::type VIMap1; + typedef typename GetInitializedVertexIndexMap::type VIMap2; + VPMap1 vpm1 = choose_parameter(get_parameter(np1, internal_np::vertex_point), + get_const_property_map(vertex_point, m1)); + VPMap2 vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), + get_const_property_map(vertex_point, m2)); + VIMap1 vim1 = get_initialized_vertex_index_map(m1, np1); + VIMap1 vim2 = get_initialized_vertex_index_map(m2, np2); + typedef typename boost::property_traits::value_type Point_3; + typedef typename FaceRange::value_type face_descriptor; + + std::map point_id_map; + std::vector m1_vertex_id(num_vertices(m1), -1); + std::vector m2_vertex_id(num_vertices(m2), -1); + + //iterate both meshes to set ids to all points, and set vertex/point_id maps. + std::size_t id =0; + for(auto v : vertices(m1)) + { + const Point_3& p = get(vpm1, v); + auto res = point_id_map.insert(std::make_pair(p, id)); + if(res.second) + id++; + m1_vertex_id[(std::size_t)get(vim1, v)]=res.first->second; + } + for(auto v : vertices(m2)) + { + const Point_3& p = get(vpm2, v); + auto res = point_id_map.insert(std::make_pair(p, id)); + if(res.second) + id++; + m2_vertex_id[(std::size_t)get(vim2, v)]=res.first->second; + } + + //fill a set with the "faces point-ids" of m1 and then iterate faces of m2 to compare. + std::set > m1_faces; + for(auto f : faces(m1)) + { + std::vector ids; + for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) + { + ids.push_back(m1_vertex_id[(std::size_t)get(vim1, v)]); + } + std::sort(ids.begin(), ids.end()); + m1_faces.insert(ids); + } + std::map, face_descriptor> m2_faces_map; + for(auto f : faces(m2)) + { + std::vector ids; + for(auto v : CGAL::vertices_around_face(halfedge(f, m2), m2)) + { + ids.push_back(m2_vertex_id[(std::size_t)get(vim2, v)]); + } + std::sort(ids.begin(), ids.end()); + m2_faces_map.insert({ids, f}); + if(m1_faces.find(ids) == m1_faces.end()) { + m2_only.push_back(f); + } + } + + for(auto f : faces(m1)) + { + std::vector ids; + for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) + { + ids.push_back(m1_vertex_id[(std::size_t)get(vim1, v)]); + } + std::sort(ids.begin(), ids.end()); + auto m2_face_it = m2_faces_map.find(ids); + if(m2_face_it == m2_faces_map.end()) + { + m1_only.push_back(f); + } + else + { + common.push_back(std::make_pair(f, m2_face_it->second)); + } + } +} + } // namespace Polygon_mesh_processing } // namespace CGAL diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/cube_quad2.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/cube_quad2.off new file mode 100644 index 00000000000..295769c43c5 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/cube_quad2.off @@ -0,0 +1,41 @@ +# Output of a CGAL tool +#CBP +# polyhedral_surface 0 +# halfedges 0 +# triangulated 0 +# non_empty_facets 0 +# terrain 0 +# normalized_to_sphere 0 +# radius 0 +# rounded 0 +# rounded_bits 0 +# ENDCBP + +NOFF +8 6 0 + +# 8 vertices +# ------------------------------------------ + + +-1 -1 -1 -0.57735 -0.57735 -0.57735 +-1 1 -1 -0.57735 0.57735 -0.57735 +1 1 -1 0.57735 0.57735 -0.57735 +1 -1 -1 0.57735 -0.57735 -0.57735 +-1.53485 -0.408879 0.387354 -0.57735 -0.57735 0.57735 +-1 1 1 -0.57735 0.57735 0.57735 +1 1 1 0.57735 0.57735 0.57735 +1 -1 1 0.57735 -0.57735 0.57735 + +# 6 facets +# ------------------------------------------ + +4 0 3 7 4 +4 3 2 6 7 +4 2 1 5 6 +4 1 0 4 5 +4 4 7 6 5 +4 0 1 2 3 + + +# End of OFF # diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri1.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri1.off new file mode 100644 index 00000000000..799cae68183 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri1.off @@ -0,0 +1,61 @@ +# Output of a CGAL tool +#CBP +# polyhedral_surface 0 +# halfedges 0 +# triangulated 0 +# non_empty_facets 0 +# terrain 0 +# normalized_to_sphere 0 +# radius 0 +# rounded 0 +# rounded_bits 0 +# ENDCBP + +NOFF +16 18 0 + +# 16 vertices +# ------------------------------------------ + + +0 0 0 0 -0.707107 0.707107 +0.333333 0 0 0 -0.707107 0.707107 +0.666667 0 0 0 -0.707107 0.707107 +1 0 0 0 -0.707107 0.707107 +0 0.333333 0.333333 0 -0.707107 0.707107 +0.333333 0.333333 0.333333 0 -0.707107 0.707107 +0.666667 0.333333 0.333333 0 -0.707107 0.707107 +1 0.333333 0.333333 0 -0.707107 0.707107 +0 0.666667 0.666667 0 -0.707107 0.707107 +0.333333 0.666667 0.666667 0 -0.707107 0.707107 +0.666667 0.666667 0.666667 0 -0.707107 0.707107 +1 0.666667 0.666667 0 -0.707107 0.707107 +0 1 1 0 -0.707107 0.707107 +0.333333 1 1 0 -0.707107 0.707107 +0.666667 1 1 0 -0.707107 0.707107 +1 1 1 0 -0.707107 0.707107 + +# 18 facets +# ------------------------------------------ + +3 0 1 4 +3 1 5 4 +3 4 5 8 +3 5 9 8 +3 8 9 12 +3 9 13 12 +3 1 2 5 +3 2 6 5 +3 5 6 9 +3 6 10 9 +3 9 10 13 +3 10 14 13 +3 2 3 6 +3 3 7 6 +3 6 7 10 +3 7 11 10 +3 10 11 14 +3 11 15 14 + + +# End of OFF # diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri2.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri2.off new file mode 100644 index 00000000000..7746b80a1c1 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri2.off @@ -0,0 +1,61 @@ +# Output of a CGAL tool +#CBP +# polyhedral_surface 0 +# halfedges 0 +# triangulated 0 +# non_empty_facets 0 +# terrain 0 +# normalized_to_sphere 0 +# radius 0 +# rounded 0 +# rounded_bits 0 +# ENDCBP + +NOFF +16 18 0 + +# 16 vertices +# ------------------------------------------ + + +0 0 0 0 -0.707107 0.707107 +0.333333 0 0 0 -0.707107 0.707107 +0.666667 0 0 0 -0.707107 0.707107 +1 0 0 0 -0.707107 0.707107 +0 0.333333 0.333333 0 -0.707107 0.707107 +0.333333 0.333333 0.333333 0 -0.707107 0.707107 +0.670394 0.279285 0.333333 0 -0.707107 0.707107 +1 0.333333 0.333333 0 -0.707107 0.707107 +0 0.666667 0.666667 0 -0.707107 0.707107 +0.333333 0.666667 0.666667 0 -0.707107 0.707107 +0.666667 0.666667 0.666667 0 -0.707107 0.707107 +1 0.666667 0.666667 0 -0.707107 0.707107 +0 1 1 0 -0.707107 0.707107 +0.377961 1.08385 1 0 -0.707107 0.707107 +0.735637 1.01488 0.948966 0 -0.707107 0.707107 +0.963486 1.09061 1 0 -0.707107 0.707107 + +# 18 facets +# ------------------------------------------ + +3 0 1 4 +3 1 5 4 +3 4 5 8 +3 5 9 8 +3 8 9 12 +3 9 13 12 +3 1 2 5 +3 2 6 5 +3 5 6 9 +3 6 10 9 +3 9 10 13 +3 10 14 13 +3 2 3 6 +3 3 7 6 +3 6 7 10 +3 7 11 10 +3 10 11 14 +3 11 15 14 + + +# End of OFF # diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp index b1537349cc1..c85f69ffb14 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp @@ -203,6 +203,89 @@ void test_centroid(const char* filename) } +template +void test_compare() +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + namespace PMP = CGAL::Polygon_mesh_processing; + + PolygonMesh mesh1, mesh2; + std::vector > common; + std::vector m1_only, m2_only; + /************************* + * triangulated and open * + * **********************/ + + std::ifstream input("data/tri1.off"); + if(! (input >> mesh1)) + { + std::cerr << "Invalid input." << std::endl; + assert (false); + return; + } + input.close(); + input.open("data/tri2.off"); + if(! (input >> mesh2)) + { + std::cerr << "Invalid input." << std::endl; + assert (false); + return; + } + input.close(); + PMP::compare_meshes(mesh1, mesh2, common, m1_only, m2_only, CGAL::parameters::all_default(), CGAL::parameters::all_default()); + assert(common.size() == 7); + assert(m1_only.size() == 11); + assert(m2_only.size() == 11); + /************************* + **** quad and closed **** + * **********************/ + CGAL::clear(mesh1); + CGAL::clear(mesh2); + common.clear(); + m1_only.clear(); + m2_only.clear(); + input.open("data/cube_quad.off"); + if(! (input >> mesh1)) + { + std::cerr << "Invalid input." << std::endl; + assert (false); + return; + } + input.close(); + input.open("data/cube_quad2.off"); + if(! (input >> mesh2)) + { + std::cerr << "Invalid input." << std::endl; + assert (false); + return; + } + input.close(); + std::unordered_map fim1; + std::unordered_map fim2; + std::size_t id = 0; + for(const auto& f : faces(mesh1)) + { + fim1.insert(std::make_pair(f, id++)); + } + id = 0; + for(const auto& f : faces(mesh2)) + { + fim2.insert(std::make_pair(f, id++)); + } + PMP::compare_meshes(mesh1, mesh2, common, m1_only, m2_only, CGAL::parameters::all_default(), CGAL::parameters::all_default()); + assert(common.size() == 3); + assert(m1_only.size() == 3); + assert(fim1[m1_only[0]] == 0); + assert(fim1[m1_only[1]] == 3); + assert(fim1[m1_only[2]] == 4); + assert(m2_only.size() == 3); + assert(fim2[m2_only[0]] == 0); + assert(fim2[m2_only[1]] == 3); + assert(fim2[m2_only[2]] == 4); + +} + int main(int argc, char* argv[]) { const char* filename_polyhedron = @@ -219,6 +302,10 @@ int main(int argc, char* argv[]) // leading to a stackoverflow when the destructor is called. test_centroid,Epic>(filename_surface_mesh); + test_compare >(); + test_compare >(); + test_compare >(); + test_compare >(); std::cerr << "All done." << std::endl; return 0; } From 836a7b8ae858f296fb9ad1d9bdbeb61e6af91056 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 22 Mar 2021 14:13:10 +0100 Subject: [PATCH 04/28] update CHANGES.md --- Installation/CHANGES.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 5787fc1441b..26086f5a684 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -1,5 +1,14 @@ Release History =============== +[Release 5.4](https://github.com/CGAL/cgal/releases/tag/v5.4) +----------- + +Release date: December 2021 + +### [Polygon Mesh Processing](https://doc.cgal.org/5.4/Manual/packages.html#PkgPolygonMeshProcessing) + +- Added the function `CGAL::Polygon_mesh_processing::compare_meshes()` which allows, given two meshes, to geometrically detect which faces are only in the first, only in the second, or in both meshes. + [Release 5.3](https://github.com/CGAL/cgal/releases/tag/v5.3) ----------- From 7d4a66167136586a3dc3387265ba77ee1ab27ea1 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 22 Mar 2021 14:59:01 +0100 Subject: [PATCH 05/28] Overloads, plugin and data sets --- .../Polygon_mesh_processing/data/tet-bis.off | 33 +---- .../Polygon_mesh_processing/data/tet.off | 33 +---- .../CGAL/Polygon_mesh_processing/measure.h | 15 ++ .../data/cube_quad2.off | 41 ++---- .../Polygon_mesh_processing/data/tri1.off | 57 +++----- .../Polygon_mesh_processing/data/tri2.off | 57 +++----- .../Diff_between_meshes_plugin.cpp | 136 +++++------------- 7 files changed, 102 insertions(+), 270 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet-bis.off b/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet-bis.off index 18a3647c547..7ea52d418d4 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet-bis.off +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet-bis.off @@ -1,35 +1,12 @@ -# Output of a CGAL tool -#CBP -# polyhedral_surface 0 -# halfedges 0 -# triangulated 0 -# non_empty_facets 0 -# terrain 0 -# normalized_to_sphere 0 -# radius 0 -# rounded 0 -# rounded_bits 0 -# ENDCBP - -NOFF +OFF 4 4 0 -# 4 vertices -# ------------------------------------------ - - -0 0 0 -0.57735 -0.57735 -0.57735 -1 0 0 0.935113 -0.250563 -0.250563 -0 1 0 -0.250563 0.935113 -0.250563 -0 0 1 -0.250563 -0.250563 0.935113 - -# 4 facets -# ------------------------------------------ +0 0 0 +1 0 0 +0 1 0 +0 0 1 3 2 1 0 3 0 3 2 3 2 3 1 3 1 3 0 - - -# End of OFF # diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet.off b/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet.off index d198868a0c5..0e1fcb3bab7 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet.off +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet.off @@ -1,35 +1,12 @@ -# Output of a CGAL tool -#CBP -# polyhedral_surface 0 -# halfedges 0 -# triangulated 0 -# non_empty_facets 0 -# terrain 0 -# normalized_to_sphere 0 -# radius 0 -# rounded 0 -# rounded_bits 0 -# ENDCBP - -NOFF +OFF 4 4 0 -# 4 vertices -# ------------------------------------------ - - -0.0521823 0.0693697 0.0558329 -0.57735 -0.57735 -0.57735 -1 0 0 0.935113 -0.250563 -0.250563 -0 1 0 -0.250563 0.935113 -0.250563 -0 0 1 -0.250563 -0.250563 0.935113 - -# 4 facets -# ------------------------------------------ +0.0521823 0.0693697 0.0558329 +1 0 0 +0 1 0 +0 0 1 3 2 1 0 3 0 3 2 3 2 3 1 3 1 3 0 - - -# End of OFF # diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 6ac978da837..f84a1d872ce 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -941,6 +941,21 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, } } +template +void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, + FacePairRange& common, FaceRange& m1_only, FaceRange& m2_only, + const NamedParameters& np) +{ + compare_meshes(m1, m2, common, m1_only, m2_only, np, parameters::all_default()); +} + +template +void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, + FacePairRange& common, FaceRange& m1_only, FaceRange& m2_only) +{ + compare_meshes(m1, m2, common, m1_only, m2_only, parameters::all_default(), parameters::all_default()); +} + } // namespace Polygon_mesh_processing } // namespace CGAL diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/cube_quad2.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/cube_quad2.off index 295769c43c5..45cb8852a90 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/cube_quad2.off +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/cube_quad2.off @@ -1,34 +1,14 @@ -# Output of a CGAL tool -#CBP -# polyhedral_surface 0 -# halfedges 0 -# triangulated 0 -# non_empty_facets 0 -# terrain 0 -# normalized_to_sphere 0 -# radius 0 -# rounded 0 -# rounded_bits 0 -# ENDCBP - -NOFF +OFF 8 6 0 -# 8 vertices -# ------------------------------------------ - - --1 -1 -1 -0.57735 -0.57735 -0.57735 --1 1 -1 -0.57735 0.57735 -0.57735 -1 1 -1 0.57735 0.57735 -0.57735 -1 -1 -1 0.57735 -0.57735 -0.57735 --1.53485 -0.408879 0.387354 -0.57735 -0.57735 0.57735 --1 1 1 -0.57735 0.57735 0.57735 -1 1 1 0.57735 0.57735 0.57735 -1 -1 1 0.57735 -0.57735 0.57735 - -# 6 facets -# ------------------------------------------ +-1 -1 -1 +-1 1 -1 +1 1 -1 +1 -1 -1 +-1.53485 -0.408879 0.387354 +-1 1 1 +1 1 1 +1 -1 1 4 0 3 7 4 4 3 2 6 7 @@ -36,6 +16,3 @@ NOFF 4 1 0 4 5 4 4 7 6 5 4 0 1 2 3 - - -# End of OFF # diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri1.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri1.off index 799cae68183..2aada48783f 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri1.off +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri1.off @@ -1,42 +1,22 @@ -# Output of a CGAL tool -#CBP -# polyhedral_surface 0 -# halfedges 0 -# triangulated 0 -# non_empty_facets 0 -# terrain 0 -# normalized_to_sphere 0 -# radius 0 -# rounded 0 -# rounded_bits 0 -# ENDCBP - -NOFF +OFF 16 18 0 -# 16 vertices -# ------------------------------------------ - - -0 0 0 0 -0.707107 0.707107 -0.333333 0 0 0 -0.707107 0.707107 -0.666667 0 0 0 -0.707107 0.707107 -1 0 0 0 -0.707107 0.707107 -0 0.333333 0.333333 0 -0.707107 0.707107 -0.333333 0.333333 0.333333 0 -0.707107 0.707107 -0.666667 0.333333 0.333333 0 -0.707107 0.707107 -1 0.333333 0.333333 0 -0.707107 0.707107 -0 0.666667 0.666667 0 -0.707107 0.707107 -0.333333 0.666667 0.666667 0 -0.707107 0.707107 -0.666667 0.666667 0.666667 0 -0.707107 0.707107 -1 0.666667 0.666667 0 -0.707107 0.707107 -0 1 1 0 -0.707107 0.707107 -0.333333 1 1 0 -0.707107 0.707107 -0.666667 1 1 0 -0.707107 0.707107 -1 1 1 0 -0.707107 0.707107 - -# 18 facets -# ------------------------------------------ +0 0 0 +0.333333 0 0 +0.666667 0 0 +1 0 0 +0 0.333333 0.333333 +0.333333 0.333333 0.333333 +0.666667 0.333333 0.333333 +1 0.333333 0.333333 +0 0.666667 0.666667 +0.333333 0.666667 0.666667 +0.666667 0.666667 0.666667 +1 0.666667 0.666667 +0 1 1 +0.333333 1 1 +0.666667 1 1 +1 1 1 3 0 1 4 3 1 5 4 @@ -56,6 +36,3 @@ NOFF 3 7 11 10 3 10 11 14 3 11 15 14 - - -# End of OFF # diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri2.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri2.off index 7746b80a1c1..462ea37293a 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri2.off +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri2.off @@ -1,42 +1,22 @@ -# Output of a CGAL tool -#CBP -# polyhedral_surface 0 -# halfedges 0 -# triangulated 0 -# non_empty_facets 0 -# terrain 0 -# normalized_to_sphere 0 -# radius 0 -# rounded 0 -# rounded_bits 0 -# ENDCBP - -NOFF +OFF 16 18 0 -# 16 vertices -# ------------------------------------------ - - -0 0 0 0 -0.707107 0.707107 -0.333333 0 0 0 -0.707107 0.707107 -0.666667 0 0 0 -0.707107 0.707107 -1 0 0 0 -0.707107 0.707107 -0 0.333333 0.333333 0 -0.707107 0.707107 -0.333333 0.333333 0.333333 0 -0.707107 0.707107 -0.670394 0.279285 0.333333 0 -0.707107 0.707107 -1 0.333333 0.333333 0 -0.707107 0.707107 -0 0.666667 0.666667 0 -0.707107 0.707107 -0.333333 0.666667 0.666667 0 -0.707107 0.707107 -0.666667 0.666667 0.666667 0 -0.707107 0.707107 -1 0.666667 0.666667 0 -0.707107 0.707107 -0 1 1 0 -0.707107 0.707107 -0.377961 1.08385 1 0 -0.707107 0.707107 -0.735637 1.01488 0.948966 0 -0.707107 0.707107 -0.963486 1.09061 1 0 -0.707107 0.707107 - -# 18 facets -# ------------------------------------------ +0 0 0 +0.333333 0 0 +0.666667 0 0 +1 0 0 +0 0.333333 0.333333 +0.333333 0.333333 0.333333 +0.670394 0.279285 0.333333 +1 0.333333 0.333333 +0 0.666667 0.666667 +0.333333 0.666667 0.666667 +0.666667 0.666667 0.666667 +1 0.666667 0.666667 +0 1 1 +0.377961 1.08385 1 +0.735637 1.01488 0.948966 +0.963486 1.09061 1 3 0 1 4 3 1 5 4 @@ -56,6 +36,3 @@ NOFF 3 7 11 10 3 10 11 14 3 11 15 14 - - -# End of OFF # diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp index 3147fca83cf..a4cb6d7875e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp @@ -8,10 +8,12 @@ #include "Scene_surface_mesh_item.h" #include +#include #include #include #include +#include #include "Messages_interface.h" using namespace CGAL::Three; @@ -48,7 +50,6 @@ public Q_SLOTS: private: CGAL::Three::Scene_interface* scene; QAction* actionDiff; - SMesh* diff(SMesh* m1, SMesh* m2, bool compute_common); }; // end Polyhedron_demo_diff_between_meshes_plugin @@ -67,95 +68,12 @@ QList Polyhedron_demo_diff_between_meshes_plugin::actions() const { return QList() << actionDiff; } -SMesh* Polyhedron_demo_diff_between_meshes_plugin::diff(SMesh* m1, SMesh* m2, bool compute_common = false) -{ - std::map point_id_map; - std::vector m1_vertex_id(num_vertices(*m1), -1); - std::vector m2_vertex_id(num_vertices(*m2), -1); - - //iterate both meshes to set ids to all points, and set vertex/point_id maps. - std::size_t id =0; - for(auto v : m1->vertices()) - { - Point_3 p = m1->point(v); - auto res = point_id_map.insert(std::make_pair(p, id)); - if(res.second) - id++; - m1_vertex_id[(std::size_t)v]=res.first->second; - } - for(auto v : m2->vertices()) - { - Point_3 p = m2->point(v); - auto res = point_id_map.insert(std::make_pair(p, id)); - if(res.second) - id++; - m2_vertex_id[(std::size_t)v]=res.first->second; - } - - //fill a set with the "faces point-ids" of m1 and then iterate faces of m2 to compare. - std::set > m1_faces; - for(auto f : m1->faces()) - { - std::vector ids; - for(auto v : CGAL::vertices_around_face(halfedge(f, *m1), *m1)) - { - ids.push_back(m1_vertex_id[(std::size_t)v]); - } - std::sort(ids.begin(), ids.end()); - m1_faces.insert(ids); - } - - std::vector common_faces; - std::vector common_points; - std::map id_map; - id = 0; - - for(auto f : m2->faces()) - { - std::vector ids; - for(auto v : CGAL::vertices_around_face(halfedge(f, *m2), *m2)) - { - ids.push_back(m2_vertex_id[(std::size_t)v]); - } - std::sort(ids.begin(), ids.end()); - if(!((m1_faces.find(ids) != m1_faces.end()) ^ compute_common)) - { - common_faces.push_back(f); - for(auto v : CGAL::vertices_around_face(halfedge(f, *m2), *m2)) - { - auto res = id_map.insert(std::make_pair(v,id)); - if(res.second) - { - common_points.push_back(m2->point(v)); - id++; - } - } - } - } - - //iterate m1_faces and fill a polygon vector using the id_map previously filled. - std::vector > polygons(common_faces.size()); - id = 0; - for(auto f : common_faces) - { - for(auto v : vertices_around_face(halfedge(f, *m2),*m2)) - { - polygons[id].push_back(id_map[v]); - } - ++id; - } - - SMesh* common = new SMesh(); - CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh( - common_points, polygons, *common); - return common; - -} - void Polyhedron_demo_diff_between_meshes_plugin::diff() { + typedef CGAL::Face_filtered_graph Filtered_graph; + QCursor c(Qt::WaitCursor); CGAL::Three::Three::CursorScopeGuard guard(c); @@ -166,22 +84,36 @@ void Polyhedron_demo_diff_between_meshes_plugin::diff() *m2_item = qobject_cast( scene->item(scene->selectionIndices().back())); - SMesh* m1=m1_item->face_graph(), - *m2=m2_item->face_graph(); + SMesh m1=*m1_item->face_graph(), + m2=*m2_item->face_graph(); + std::vector m1_only, m2_only; + std::vector > common; + CGAL::Polygon_mesh_processing::compare_meshes(m1, m2, common, m1_only, m2_only); - SMesh* m1_over_m2 = diff(m1, m2); - SMesh* m2_over_m1 = diff(m2, m1); - SMesh* common = diff(m2, m1, true); + Filtered_graph filter1(m1, m1_only); + SMesh mesh1_only, mesh2_only, common_mesh; + CGAL::copy_face_graph(filter1, mesh1_only); - Scene_surface_mesh_item* m1_over_m2_item = new Scene_surface_mesh_item(m1_over_m2); - m1_over_m2_item->setColor(QColor(Qt::blue)); - m1_over_m2_item->setName(QString("%2 - %1").arg(m1_item->name()).arg(m2_item->name())); - CGAL::Three::Three::scene()->addItem(m1_over_m2_item); - Scene_surface_mesh_item* m2_over_m1_item = new Scene_surface_mesh_item(m2_over_m1); - m2_over_m1_item->setColor(QColor(Qt::red)); - m2_over_m1_item->setName(QString("%1 - %2").arg(m1_item->name()).arg(m2_item->name())); - CGAL::Three::Three::scene()->addItem(m2_over_m1_item); - Scene_surface_mesh_item* common_item = new Scene_surface_mesh_item(common); + Scene_surface_mesh_item* mesh1_only_item = new Scene_surface_mesh_item(mesh1_only); + mesh1_only_item->setColor(QColor(Qt::blue)); + mesh1_only_item->setName(QString("%1_only").arg(m1_item->name())); + CGAL::Three::Three::scene()->addItem(mesh1_only_item); + + Filtered_graph filter2(m2, m2_only); + CGAL::copy_face_graph(filter2, mesh2_only); + Scene_surface_mesh_item* mesh2_only_item = new Scene_surface_mesh_item(mesh2_only); + mesh2_only_item->setColor(QColor(Qt::red)); + mesh2_only_item->setName(QString("%1_only").arg(m2_item->name())); + CGAL::Three::Three::scene()->addItem(mesh2_only_item); + m1_only.clear(); + m1_only.reserve(common.size()); + for(const auto& f_pair : common) + { + m1_only.push_back(f_pair.first); + } + Filtered_graph filter_common(m1, m1_only); + CGAL::copy_face_graph(filter_common, common_mesh); + Scene_surface_mesh_item* common_item = new Scene_surface_mesh_item(common_mesh); common_item->setColor(QColor(Qt::green)); CGAL::Three::Three::scene()->addItem(common_item); common_item->setName(QString("%1 && %2").arg(m1_item->name()).arg(m2_item->name())); @@ -189,8 +121,8 @@ void Polyhedron_demo_diff_between_meshes_plugin::diff() Scene_group_item* group = new Scene_group_item(); group->setName("Diff result"); CGAL::Three::Three::scene()->addItem(group); - CGAL::Three::Three::scene()->changeGroup(m1_over_m2_item, group); - CGAL::Three::Three::scene()->changeGroup(m2_over_m1_item, group); + CGAL::Three::Three::scene()->changeGroup(mesh1_only_item, group); + CGAL::Three::Three::scene()->changeGroup(mesh2_only_item, group); CGAL::Three::Three::scene()->changeGroup(common_item, group); m1_item->setVisible(false); From c1895e74b65198871e16fd12ab76d0e426a970d6 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 22 Mar 2021 14:59:40 +0100 Subject: [PATCH 06/28] mutbale ranges in doc --- .../include/CGAL/Polygon_mesh_processing/measure.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index f84a1d872ce..7ffe2acffd9 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -827,8 +827,8 @@ centroid(const TriangleMesh& tmesh) * that are only in the other one, and the faces that are common to both. * * @tparam PolygonMesh a model of `HalfedgeListGraph` and `FaceListGraph` - * \tparam FaceRange a range of `boost::graph_traits::%face_descriptor` - * @tparam FacePairRange a range of `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` + * \tparam FaceRange a mutable range of `boost::graph_traits::%face_descriptor` + * @tparam FacePairRange a mutable range of `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` * * @tparam NamedParameters1 a sequence of \ref bgl_namedparameters "Named Parameters" * @tparam NamedParameters2 a sequence of \ref bgl_namedparameters "Named Parameters" From 22e13faee98ad4bfcd4e17ac055dfbceda3fc695 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 22 Mar 2021 16:28:10 +0100 Subject: [PATCH 07/28] 1st pass after review --- .../CGAL/Polygon_mesh_processing/measure.h | 45 ++++++++++++------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 7ffe2acffd9..87fe506d7e8 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -28,6 +28,7 @@ #include // needed for CGAL::exact(FT)/CGAL::exact(Lazy_exact_nt) +#include #include #include @@ -825,6 +826,7 @@ centroid(const TriangleMesh& tmesh) * \ingroup measure_grp * given two meshes, separates the faces that are only in one, the faces * that are only in the other one, and the faces that are common to both. + * The orientation of the faces is ignored during the comparison. * * @tparam PolygonMesh a model of `HalfedgeListGraph` and `FaceListGraph` * \tparam FaceRange a mutable range of `boost::graph_traits::%face_descriptor` @@ -835,9 +837,9 @@ centroid(const TriangleMesh& tmesh) * * @param m1 the first `PolygonMesh` * @param m2 the second `PolygonMesh` - * @param common the range containing the faces that are common to both meshes. - * @param m1_only the range containing the faces that are only in `m1` - * @param m2_only the range containing the faces that are only in `m2` + * @param common output range containing the faces that are common to both meshes. + * @param m1_only output range containing the faces that are only in `m1` + * @param m2_only output range containing the faces that are only in `m2` * @param np1 an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below * @param np2 an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below * @@ -845,9 +847,20 @@ centroid(const TriangleMesh& tmesh) * \cgalParamNBegin{vertex_point_map} * \cgalParamDescription{a property map associating points to the vertices of `m1` (`m2`)} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` - * as key type and `%Point_3` as value type} + * as key type and `%Point_3` as value type. `%Point_3` must be LessThanComparable.} * \cgalParamDefault{`boost::get(CGAL::vertex_point, m1 (m2))`} * \cgalParamNEnd + * + * \cgalParamNBegin{vertex_index_map} + * \cgalParamDescription{a property map associating to each vertex of `m1` (`m2`) a unique index between `0` and `num_vertices(m1 (m2)) - 1`} + * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` + * as key type and `std::size_t` as value type} + * \cgalParamDefault{an automatically indexed internal map} + * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize + * a face index property map, either using the internal property map if it exists + * or using an external map. The latter might result in - slightly - worsened performance + * in case of non-constant complexity for index access.} + * \cgalParamNEnd * \cgalNamedParamsEnd * */ @@ -860,8 +873,8 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, using parameters::get_parameter; typedef typename GetVertexPointMap < PolygonMesh, NamedParameters1>::const_type VPMap1; typedef typename GetVertexPointMap < PolygonMesh, NamedParameters2>::const_type VPMap2; - typedef typename GetInitializedVertexIndexMap::type VIMap1; - typedef typename GetInitializedVertexIndexMap::type VIMap2; + typedef typename GetInitializedVertexIndexMap::const_type VIMap1; + typedef typename GetInitializedVertexIndexMap::const_type VIMap2; VPMap1 vpm1 = choose_parameter(get_parameter(np1, internal_np::vertex_point), get_const_property_map(vertex_point, m1)); VPMap2 vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), @@ -883,7 +896,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, auto res = point_id_map.insert(std::make_pair(p, id)); if(res.second) id++; - m1_vertex_id[(std::size_t)get(vim1, v)]=res.first->second; + m1_vertex_id[static_cast(get(vim1, v))]=res.first->second; } for(auto v : vertices(m2)) { @@ -891,28 +904,28 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, auto res = point_id_map.insert(std::make_pair(p, id)); if(res.second) id++; - m2_vertex_id[(std::size_t)get(vim2, v)]=res.first->second; + m2_vertex_id[static_cast(get(vim2, v))]=res.first->second; } //fill a set with the "faces point-ids" of m1 and then iterate faces of m2 to compare. - std::set > m1_faces; + std::set > m1_faces; for(auto f : faces(m1)) { - std::vector ids; + boost::container::small_vector ids; for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) { - ids.push_back(m1_vertex_id[(std::size_t)get(vim1, v)]); + ids.push_back(m1_vertex_id[static_cast(get(vim1, v))]); } std::sort(ids.begin(), ids.end()); m1_faces.insert(ids); } - std::map, face_descriptor> m2_faces_map; + std::map, face_descriptor> m2_faces_map; for(auto f : faces(m2)) { - std::vector ids; + boost::container::small_vector ids; for(auto v : CGAL::vertices_around_face(halfedge(f, m2), m2)) { - ids.push_back(m2_vertex_id[(std::size_t)get(vim2, v)]); + ids.push_back(m2_vertex_id[static_cast(get(vim2, v))]); } std::sort(ids.begin(), ids.end()); m2_faces_map.insert({ids, f}); @@ -923,10 +936,10 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, for(auto f : faces(m1)) { - std::vector ids; + boost::container::small_vector ids; for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) { - ids.push_back(m1_vertex_id[(std::size_t)get(vim1, v)]); + ids.push_back(m1_vertex_id[static_cast(get(vim1, v))]); } std::sort(ids.begin(), ids.end()); auto m2_face_it = m2_faces_map.find(ids); From 27701711e77239b3403e227c28e8b80e08700157 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 23 Mar 2021 09:25:06 +0100 Subject: [PATCH 08/28] Only 2 loops for faces --- .../CGAL/Polygon_mesh_processing/measure.h | 51 +++++++++---------- .../Polygon_mesh_processing/measures_test.cpp | 5 +- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 87fe506d7e8..6e36010f15a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -885,6 +885,8 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, typedef typename FaceRange::value_type face_descriptor; std::map point_id_map; + //0 = never seen, 1 = seen only once, 2 = seen in both meshes + std::vector shared_vertices(num_vertices(m1) + num_vertices(m2), 0); std::vector m1_vertex_id(num_vertices(m1), -1); std::vector m2_vertex_id(num_vertices(m2), -1); @@ -897,6 +899,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, if(res.second) id++; m1_vertex_id[static_cast(get(vim1, v))]=res.first->second; + ++shared_vertices[res.first->second]; } for(auto v : vertices(m2)) { @@ -905,52 +908,46 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, if(res.second) id++; m2_vertex_id[static_cast(get(vim2, v))]=res.first->second; + ++shared_vertices[res.first->second]; } //fill a set with the "faces point-ids" of m1 and then iterate faces of m2 to compare. - std::set > m1_faces; + std::map, face_descriptor> m1_faces_map; for(auto f : faces(m1)) { + bool all_shared = true; boost::container::small_vector ids; for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) { - ids.push_back(m1_vertex_id[static_cast(get(vim1, v))]); + std::size_t vid = m1_vertex_id[static_cast(get(vim1, v))]; + ids.push_back(vid); + if(shared_vertices[vid] != 2) + all_shared = false; } std::sort(ids.begin(), ids.end()); - m1_faces.insert(ids); + if(all_shared) + m1_faces_map.insert({ids, f}); + else + m1_only.push_back(f); } - std::map, face_descriptor> m2_faces_map; for(auto f : faces(m2)) { boost::container::small_vector ids; + bool all_shared = true; for(auto v : CGAL::vertices_around_face(halfedge(f, m2), m2)) { - ids.push_back(m2_vertex_id[static_cast(get(vim2, v))]); + std::size_t vid = m2_vertex_id[static_cast(get(vim2, v))]; + ids.push_back(vid); + if(shared_vertices[vid] != 2) + { + all_shared = false; + } } std::sort(ids.begin(), ids.end()); - m2_faces_map.insert({ids, f}); - if(m1_faces.find(ids) == m1_faces.end()) { - m2_only.push_back(f); - } - } - - for(auto f : faces(m1)) - { - boost::container::small_vector ids; - for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) - { - ids.push_back(m1_vertex_id[static_cast(get(vim1, v))]); - } - std::sort(ids.begin(), ids.end()); - auto m2_face_it = m2_faces_map.find(ids); - if(m2_face_it == m2_faces_map.end()) - { - m1_only.push_back(f); - } + if(all_shared) + common.push_back(std::make_pair(m1_faces_map[ids], f)); else - { - common.push_back(std::make_pair(f, m2_face_it->second)); - } + m2_only.push_back(f); } } diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp index c85f69ffb14..352c15be8aa 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp @@ -212,6 +212,7 @@ void test_compare() PolygonMesh mesh1, mesh2; std::vector > common; + common.clear(); std::vector m1_only, m2_only; /************************* * triangulated and open * @@ -288,7 +289,7 @@ void test_compare() int main(int argc, char* argv[]) { - const char* filename_polyhedron = +/* const char* filename_polyhedron = (argc > 1) ? argv[1] : "data/mech-holes-shark.off"; test_polyhedron,Epic>(filename_polyhedron); test_polyhedron,Epec>(filename_polyhedron); @@ -301,7 +302,7 @@ int main(int argc, char* argv[]) // It won't work with Epec for large meshes as it builds up a deep DAG // leading to a stackoverflow when the destructor is called. test_centroid,Epic>(filename_surface_mesh); - +*/ test_compare >(); test_compare >(); test_compare >(); From 8c5fcd92098f60214c540f3ae4d4b04c4e16dc52 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 23 Mar 2021 09:45:48 +0100 Subject: [PATCH 09/28] Replace by bitset --- .../include/CGAL/Polygon_mesh_processing/measure.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 6e36010f15a..0690212befb 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -885,8 +886,8 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, typedef typename FaceRange::value_type face_descriptor; std::map point_id_map; - //0 = never seen, 1 = seen only once, 2 = seen in both meshes - std::vector shared_vertices(num_vertices(m1) + num_vertices(m2), 0); + + boost::dynamic_bitset<> shared_vertices(num_vertices(m1) + num_vertices(m2)); std::vector m1_vertex_id(num_vertices(m1), -1); std::vector m2_vertex_id(num_vertices(m2), -1); @@ -899,7 +900,6 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, if(res.second) id++; m1_vertex_id[static_cast(get(vim1, v))]=res.first->second; - ++shared_vertices[res.first->second]; } for(auto v : vertices(m2)) { @@ -907,8 +907,9 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, auto res = point_id_map.insert(std::make_pair(p, id)); if(res.second) id++; + else + shared_vertices.set(res.first->second); m2_vertex_id[static_cast(get(vim2, v))]=res.first->second; - ++shared_vertices[res.first->second]; } //fill a set with the "faces point-ids" of m1 and then iterate faces of m2 to compare. @@ -921,7 +922,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, { std::size_t vid = m1_vertex_id[static_cast(get(vim1, v))]; ids.push_back(vid); - if(shared_vertices[vid] != 2) + if(!shared_vertices.test(vid)) all_shared = false; } std::sort(ids.begin(), ids.end()); @@ -938,7 +939,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, { std::size_t vid = m2_vertex_id[static_cast(get(vim2, v))]; ids.push_back(vid); - if(shared_vertices[vid] != 2) + if(!shared_vertices.test(vid)) { all_shared = false; } From dd90a3ce84c28523aa9fec3991ca822093d29063 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 23 Mar 2021 10:14:21 +0100 Subject: [PATCH 10/28] OutputIterators --- .../compare_meshes_example.cpp | 2 +- .../CGAL/Polygon_mesh_processing/measure.h | 35 +++++++++++-------- .../Polygon_mesh_processing/measures_test.cpp | 4 +-- .../Diff_between_meshes_plugin.cpp | 2 +- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp index d821caf6fef..ad60ec7091d 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp @@ -36,7 +36,7 @@ int main(int argc, char* argv[]) } std::vector > common; std::vector m1_only, m2_only; - PMP::compare_meshes(mesh1, mesh2, common, m1_only, m2_only, CGAL::parameters::all_default(), CGAL::parameters::all_default()); + PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::all_default(), CGAL::parameters::all_default()); std::cout<<"Faces only in m1 : "<::%face_descriptor` - * @tparam FacePairRange a mutable range of `std::pair::%face_descriptor, boost::graph_traits::%face_descriptor>` + * @tparam OutputFaceIterator model of `OutputIterator` + holding `boost::graph_traits::%face_descriptor` + for faces that are only in one mesh. + * @tparam OutputFacePairIterator model of `OutputIterator` + holding `std::pair::%face_descriptor, + boost::graph_traits::%face_descriptor` + for faces that are shared by both meshes. * * @tparam NamedParameters1 a sequence of \ref bgl_namedparameters "Named Parameters" * @tparam NamedParameters2 a sequence of \ref bgl_namedparameters "Named Parameters" * * @param m1 the first `PolygonMesh` * @param m2 the second `PolygonMesh` - * @param common output range containing the faces that are common to both meshes. - * @param m1_only output range containing the faces that are only in `m1` - * @param m2_only output range containing the faces that are only in `m2` + * @param common output iterator collecting the faces that are common to both meshes. + * @param m1_only output iterator collecting the faces that are only in `m1` + * @param m2_only output iterator collecting the faces that are only in `m2` * @param np1 an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below * @param np2 an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below * @@ -865,9 +870,9 @@ centroid(const TriangleMesh& tmesh) * \cgalNamedParamsEnd * */ -template +template void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, - FacePairRange& common, FaceRange& m1_only, FaceRange& m2_only, + OutputFacePairIterator common, OutputFaceIterator m1_only, OutputFaceIterator m2_only, const NamedParameters1& np1,const NamedParameters2& np2) { using parameters::choose_parameter; @@ -883,7 +888,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, VIMap1 vim1 = get_initialized_vertex_index_map(m1, np1); VIMap1 vim2 = get_initialized_vertex_index_map(m2, np2); typedef typename boost::property_traits::value_type Point_3; - typedef typename FaceRange::value_type face_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; std::map point_id_map; @@ -929,7 +934,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, if(all_shared) m1_faces_map.insert({ids, f}); else - m1_only.push_back(f); + *m1_only++ = f; } for(auto f : faces(m2)) { @@ -946,23 +951,23 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, } std::sort(ids.begin(), ids.end()); if(all_shared) - common.push_back(std::make_pair(m1_faces_map[ids], f)); + *common++ = std::make_pair(m1_faces_map[ids], f); else - m2_only.push_back(f); + *m2_only++ = f; } } -template +template void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, - FacePairRange& common, FaceRange& m1_only, FaceRange& m2_only, + OutputFacePairIterator common, OutputFaceIterator m1_only, OutputFaceIterator m2_only, const NamedParameters& np) { compare_meshes(m1, m2, common, m1_only, m2_only, np, parameters::all_default()); } -template +template void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, - FacePairRange& common, FaceRange& m1_only, FaceRange& m2_only) + OutputFacePairIterator common, OutputFaceIterator m1_only, OutputFaceIterator m2_only) { compare_meshes(m1, m2, common, m1_only, m2_only, parameters::all_default(), parameters::all_default()); } diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp index 352c15be8aa..b0609f34987 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp @@ -234,7 +234,7 @@ void test_compare() return; } input.close(); - PMP::compare_meshes(mesh1, mesh2, common, m1_only, m2_only, CGAL::parameters::all_default(), CGAL::parameters::all_default()); + PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::all_default(), CGAL::parameters::all_default()); assert(common.size() == 7); assert(m1_only.size() == 11); assert(m2_only.size() == 11); @@ -274,7 +274,7 @@ void test_compare() { fim2.insert(std::make_pair(f, id++)); } - PMP::compare_meshes(mesh1, mesh2, common, m1_only, m2_only, CGAL::parameters::all_default(), CGAL::parameters::all_default()); + PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::all_default(), CGAL::parameters::all_default()); assert(common.size() == 3); assert(m1_only.size() == 3); assert(fim1[m1_only[0]] == 0); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp index a4cb6d7875e..c3c5d59302a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp @@ -88,7 +88,7 @@ void Polyhedron_demo_diff_between_meshes_plugin::diff() m2=*m2_item->face_graph(); std::vector m1_only, m2_only; std::vector > common; - CGAL::Polygon_mesh_processing::compare_meshes(m1, m2, common, m1_only, m2_only); + CGAL::Polygon_mesh_processing::compare_meshes(m1, m2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only)); Filtered_graph filter1(m1, m1_only); SMesh mesh1_only, mesh2_only, common_mesh; From 8f92a01b1203e49a4d37bc00a9099ba854e5c4f0 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 23 Mar 2021 10:38:19 +0100 Subject: [PATCH 11/28] clean-up --- .../CGAL/Polygon_mesh_processing/measure.h | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 0b175578eab..f753c3e8064 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -892,9 +892,9 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, std::map point_id_map; - boost::dynamic_bitset<> shared_vertices(num_vertices(m1) + num_vertices(m2)); - std::vector m1_vertex_id(num_vertices(m1), -1); - std::vector m2_vertex_id(num_vertices(m2), -1); + boost::dynamic_bitset<> shared_vertices(vertices(m1).size() + vertices(m2).size()); + std::vector m1_vertex_id(vertices(m1).size(), -1); + std::vector m2_vertex_id(vertices(m2).size(), -1); //iterate both meshes to set ids to all points, and set vertex/point_id maps. std::size_t id =0; @@ -904,7 +904,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, auto res = point_id_map.insert(std::make_pair(p, id)); if(res.second) id++; - m1_vertex_id[static_cast(get(vim1, v))]=res.first->second; + m1_vertex_id[get(vim1, v)]=res.first->second; } for(auto v : vertices(m2)) { @@ -914,7 +914,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, id++; else shared_vertices.set(res.first->second); - m2_vertex_id[static_cast(get(vim2, v))]=res.first->second; + m2_vertex_id[get(vim2, v)]=res.first->second; } //fill a set with the "faces point-ids" of m1 and then iterate faces of m2 to compare. @@ -925,14 +925,19 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, boost::container::small_vector ids; for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) { - std::size_t vid = m1_vertex_id[static_cast(get(vim1, v))]; + std::size_t vid = m1_vertex_id[get(vim1, v)]; ids.push_back(vid); if(!shared_vertices.test(vid)) + { all_shared = false; + break; + } } - std::sort(ids.begin(), ids.end()); if(all_shared) + { + std::sort(ids.begin(), ids.end()); m1_faces_map.insert({ids, f}); + } else *m1_only++ = f; } @@ -942,16 +947,19 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, bool all_shared = true; for(auto v : CGAL::vertices_around_face(halfedge(f, m2), m2)) { - std::size_t vid = m2_vertex_id[static_cast(get(vim2, v))]; + std::size_t vid = m2_vertex_id[get(vim2, v)]; ids.push_back(vid); if(!shared_vertices.test(vid)) { all_shared = false; + break; } } - std::sort(ids.begin(), ids.end()); if(all_shared) + { + std::sort(ids.begin(), ids.end()); *common++ = std::make_pair(m1_faces_map[ids], f); + } else *m2_only++ = f; } From aa2b52715601087aa69eab6762bda8a8107dcadb Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 23 Mar 2021 11:13:47 +0100 Subject: [PATCH 12/28] Fix holes situation --- .../CGAL/Polygon_mesh_processing/measure.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index f753c3e8064..6a87d56e85f 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -958,11 +958,25 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, if(all_shared) { std::sort(ids.begin(), ids.end()); - *common++ = std::make_pair(m1_faces_map[ids], f); + auto it = m1_faces_map.find(ids); + if(it != m1_faces_map.end()) + { + *common++ = std::make_pair(m1_faces_map[ids], f); + m1_faces_map.erase(it); + } + else + { + *m2_only++ = f; + } } else *m2_only++ = f; } + //all real shared vertices have benn removed from the map, so all that remains must go in m1_only + for(const auto& it : m1_faces_map) + { + *m1_only++ = it.second; + } } template From 277117613bfb9c346e7e70f17e906b0ee05ea343 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 23 Mar 2021 11:49:47 +0100 Subject: [PATCH 13/28] Add a NP for orientation requirement --- .../CGAL/Polygon_mesh_processing/measure.h | 30 ++++++++++++++++--- .../Diff_between_meshes_plugin.cpp | 16 +++++++++- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 6a87d56e85f..c74e18103d7 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -34,6 +34,7 @@ #include #include +#include #ifdef DOXYGEN_RUNNING #define CGAL_PMP_NP_TEMPLATE_PARAMETERS NamedParameters @@ -51,7 +52,20 @@ public: }; namespace Polygon_mesh_processing { - +namespace pmp_internal { +void rearrange_face_ids(boost::container::small_vector& ids, bool orientation_counts) +{ + if(!orientation_counts) + { + std::sort(ids.begin(), ids.end()); + } + else + { + auto min_elem = std::min_element(ids.begin(), ids.end()); + std::rotate(ids.begin(), min_elem, ids.end()); + } +} +}//end pmp_internal /** * \ingroup measure_grp * computes the length of an edge of a given polygon mesh. @@ -827,7 +841,6 @@ centroid(const TriangleMesh& tmesh) * \ingroup measure_grp * given two meshes, separates the faces that are only in one, the faces * that are only in the other one, and the faces that are common to both. - * The orientation of the faces is ignored during the comparison. * * @tparam PolygonMesh a model of `HalfedgeListGraph` and `FaceListGraph` * @tparam OutputFaceIterator model of `OutputIterator` @@ -867,6 +880,14 @@ centroid(const TriangleMesh& tmesh) * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd + * \cgalParamNBegin{require_same_orientation} + * \cgalParamDescription{Parameter (np1 only) to indicate if face orientation should be taken + * into account when determining whether two faces are duplicates, + * that is, whether e.g. the triangles `0,1,2` and `0,2,1` are duplicates.} + * \cgalParamType{Boolean} + * \cgalParamDefault{`false`} + *\cgalParamNEnd + * \cgalNamedParamsEnd * */ @@ -887,6 +908,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, get_const_property_map(vertex_point, m2)); VIMap1 vim1 = get_initialized_vertex_index_map(m1, np1); VIMap1 vim2 = get_initialized_vertex_index_map(m2, np2); + const bool same_orientation = choose_parameter(get_parameter(np1, internal_np::require_same_orientation), false); typedef typename boost::property_traits::value_type Point_3; typedef typename boost::graph_traits::face_descriptor face_descriptor; @@ -935,7 +957,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, } if(all_shared) { - std::sort(ids.begin(), ids.end()); + pmp_internal::rearrange_face_ids(ids, same_orientation); m1_faces_map.insert({ids, f}); } else @@ -957,7 +979,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, } if(all_shared) { - std::sort(ids.begin(), ids.end()); + pmp_internal::rearrange_face_ids(ids, same_orientation); auto it = m1_faces_map.find(ids); if(it != m1_faces_map.end()) { diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp index c3c5d59302a..11d61ac8916 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp @@ -75,6 +75,14 @@ void Polyhedron_demo_diff_between_meshes_plugin::diff() typedef CGAL::Face_filtered_graph Filtered_graph; QCursor c(Qt::WaitCursor); + + QMessageBox msgBox; + msgBox.setText("Require the Same Orientation ?"); + msgBox.setInformativeText("Should face orientation count for duplicate detection ?"); + msgBox.setStandardButtons(QMessageBox::Yes| QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + int ret = msgBox.exec(); + bool same_orientation = (ret == QMessageBox::Yes); CGAL::Three::Three::CursorScopeGuard guard(c); //Get the two meshes. No need to check their existance, applicable() @@ -88,7 +96,13 @@ void Polyhedron_demo_diff_between_meshes_plugin::diff() m2=*m2_item->face_graph(); std::vector m1_only, m2_only; std::vector > common; - CGAL::Polygon_mesh_processing::compare_meshes(m1, m2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only)); + CGAL::Polygon_mesh_processing::compare_meshes( + m1, + m2, + std::back_inserter(common), + std::back_inserter(m1_only), + std::back_inserter(m2_only), + CGAL::parameters::require_same_orientation(same_orientation)); Filtered_graph filter1(m1, m1_only); SMesh mesh1_only, mesh2_only, common_mesh; From f4da3182d787db9be8676f4f0ecd9c2d809dbc7d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 23 Mar 2021 12:04:25 +0100 Subject: [PATCH 14/28] add new tests --- .../data/tri1-hole.off | 37 ++++++++++++ .../Polygon_mesh_processing/data/tri2-out.off | 38 +++++++++++++ .../Polygon_mesh_processing/measures_test.cpp | 57 +++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri1-hole.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri2-out.off diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri1-hole.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri1-hole.off new file mode 100644 index 00000000000..7ba3bb6021b --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri1-hole.off @@ -0,0 +1,37 @@ +OFF +16 17 0 + +0 0 0 +0.333333 0 0 +0.666667 0 0 +1 0 0 +0 0.333333 0.333333 +0.333333 0.333333 0.333333 +0.666667 0.333333 0.333333 +1 0.333333 0.333333 +0 0.666667 0.666667 +0.333333 0.666667 0.666667 +0.666667 0.666667 0.666667 +1 0.666667 0.666667 +0 1 1 +0.333333 1 1 +0.666667 1 1 +1 1 1 + +3 0 1 4 +3 1 5 4 +3 4 5 8 +3 5 9 8 +3 8 9 12 +3 9 13 12 +3 2 6 5 +3 5 6 9 +3 6 10 9 +3 9 10 13 +3 10 14 13 +3 2 3 6 +3 3 7 6 +3 6 7 10 +3 7 11 10 +3 10 11 14 +3 11 15 14 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri2-out.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri2-out.off new file mode 100644 index 00000000000..1127abddf90 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tri2-out.off @@ -0,0 +1,38 @@ +OFF +16 18 0 + +0 0 0 +0.33333299999999999 0 0 +0.66666700000000001 0 0 +1 0 0 +0 0.33333299999999999 0.33333299999999999 +0.33333299999999999 0.33333299999999999 0.33333299999999999 +0.67039400000000005 0.27928500000000001 0.33333299999999999 +1 0.33333299999999999 0.33333299999999999 +0 0.66666700000000001 0.66666700000000001 +0.33333299999999999 0.66666700000000001 0.66666700000000001 +0.66666700000000001 0.66666700000000001 0.66666700000000001 +1 0.66666700000000001 0.66666700000000001 +0 1 1 +0.37796099999999999 1.08385 1 +0.73563699999999999 1.01488 0.94896599999999998 +0.96348599999999995 1.0906100000000001 1 + +3 4 1 0 +3 4 5 1 +3 8 5 4 +3 8 9 5 +3 12 9 8 +3 12 13 9 +3 5 2 1 +3 5 6 2 +3 9 6 5 +3 9 10 6 +3 13 10 9 +3 13 14 10 +3 6 3 2 +3 6 7 3 +3 10 7 6 +3 10 11 7 +3 14 11 10 +3 14 15 11 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp index b0609f34987..ed8d1b30019 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp @@ -284,6 +284,63 @@ void test_compare() assert(fim2[m2_only[0]] == 0); assert(fim2[m2_only[1]] == 3); assert(fim2[m2_only[2]] == 4); + /************************* + **** tri and hole**** + * **********************/ + CGAL::clear(mesh1); + CGAL::clear(mesh2); + common.clear(); + m1_only.clear(); + m2_only.clear(); + input.open("data/tri1.off"); + if(! (input >> mesh1)) + { + std::cerr << "Invalid input." << std::endl; + assert (false); + return; + } + input.close(); + input.open("data/tri1-hole.off"); + if(! (input >> mesh2)) + { + std::cerr << "Invalid input." << std::endl; + assert (false); + return; + } + input.close(); + PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::all_default(), CGAL::parameters::all_default()); + assert(common.size() == 17); + assert(m1_only.size() == 1); + assert(m2_only.size() == 0); + + /************************* + **** tri and orient**** + * **********************/ + CGAL::clear(mesh1); + CGAL::clear(mesh2); + common.clear(); + m1_only.clear(); + m2_only.clear(); + input.open("data/tri2.off"); + if(! (input >> mesh1)) + { + std::cerr << "Invalid input." << std::endl; + assert (false); + return; + } + input.close(); + input.open("data/tri2-out.off"); + if(! (input >> mesh2)) + { + std::cerr << "Invalid input." << std::endl; + assert (false); + return; + } + input.close(); + PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::require_same_orientation(true), CGAL::parameters::all_default()); + assert(common.size() == 0); + assert(m1_only.size() == 18); + assert(m2_only.size() == 18); } From cc4d27439957c82608efc5e4a397fe4a4a2f3e0d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 23 Mar 2021 12:10:34 +0100 Subject: [PATCH 15/28] Clarify np --- .../include/CGAL/Polygon_mesh_processing/measure.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index c74e18103d7..6b4416c72fe 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -882,8 +882,9 @@ centroid(const TriangleMesh& tmesh) * \cgalParamNEnd * \cgalParamNBegin{require_same_orientation} * \cgalParamDescription{Parameter (np1 only) to indicate if face orientation should be taken - * into account when determining whether two faces are duplicates, - * that is, whether e.g. the triangles `0,1,2` and `0,2,1` are duplicates.} + * into account when determining whether two faces are duplicates. + * If `true`, then the triangles `0,1,2` and `0,2,1` will not be considered + * as "shared" between the two meshes.} * \cgalParamType{Boolean} * \cgalParamDefault{`false`} *\cgalParamNEnd From c3036b1e3e350a9f4bbc9b3e879fb6ebbeba9ee8 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 23 Mar 2021 12:11:43 +0100 Subject: [PATCH 16/28] clean-up --- .../include/CGAL/Polygon_mesh_processing/measure.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 6b4416c72fe..0bd7dc17237 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -915,9 +915,9 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, std::map point_id_map; - boost::dynamic_bitset<> shared_vertices(vertices(m1).size() + vertices(m2).size()); std::vector m1_vertex_id(vertices(m1).size(), -1); std::vector m2_vertex_id(vertices(m2).size(), -1); + boost::dynamic_bitset<> shared_vertices(m1_vertex_id.size() + m2_vertex_id.size()); //iterate both meshes to set ids to all points, and set vertex/point_id maps. std::size_t id =0; @@ -984,7 +984,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, auto it = m1_faces_map.find(ids); if(it != m1_faces_map.end()) { - *common++ = std::make_pair(m1_faces_map[ids], f); + *common++ = std::make_pair(it->second, f); m1_faces_map.erase(it); } else @@ -995,7 +995,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, else *m2_only++ = f; } - //all real shared vertices have benn removed from the map, so all that remains must go in m1_only + //all real shared vertices have been removed from the map, so all that remains must go in m1_only for(const auto& it : m1_faces_map) { *m1_only++ = it.second; From 5f4437bef1c15a926797bb1adf641794cd516e08 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 23 Mar 2021 12:43:53 +0100 Subject: [PATCH 17/28] Fix missing inline and doc --- .../doc/Polygon_mesh_processing/PackageDescription.txt | 1 + .../include/CGAL/Polygon_mesh_processing/measure.h | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt index 860b966cdcd..acdaa96e9ca 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt @@ -198,6 +198,7 @@ The page \ref bgl_namedparameters "Named Parameters" describes their usage. - \link measure_grp `CGAL::Polygon_mesh_processing::edge_length()` \endlink - \link measure_grp `CGAL::Polygon_mesh_processing::face_border_length()` \endlink - \link measure_grp `CGAL::Polygon_mesh_processing::centroid()` \endlink +- \link measure_grp `CGAL::Polygon_mesh_processing::compare_meshes()` \endlink \cgalCRPSection{Distance Functions} - `CGAL::Polygon_mesh_processing::approximate_Hausdorff_distance()` diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 0bd7dc17237..1e6e12d84e0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -52,8 +52,10 @@ public: }; namespace Polygon_mesh_processing { + namespace pmp_internal { -void rearrange_face_ids(boost::container::small_vector& ids, bool orientation_counts) + +inline void rearrange_face_ids(boost::container::small_vector& ids, bool orientation_counts) { if(!orientation_counts) { From 9e6eaa504a8ae59398efb7f4ccf1cd368a9f288c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 23 Mar 2021 13:42:10 +0100 Subject: [PATCH 18/28] Orientation requirements always on, as it won't work without it on non triangle meshes --- .../compare_meshes_example.cpp | 2 +- .../CGAL/Polygon_mesh_processing/measure.h | 24 ++++--------------- .../Polygon_mesh_processing/measures_test.cpp | 7 +++--- .../Diff_between_meshes_plugin.cpp | 11 +-------- 4 files changed, 10 insertions(+), 34 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp index ad60ec7091d..08d3553947a 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp @@ -36,7 +36,7 @@ int main(int argc, char* argv[]) } std::vector > common; std::vector m1_only, m2_only; - PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::all_default(), CGAL::parameters::all_default()); + PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only)); std::cout<<"Faces only in m1 : "<& ids, bool orientation_counts) +inline void rearrange_face_ids(boost::container::small_vector& ids) { - if(!orientation_counts) - { - std::sort(ids.begin(), ids.end()); - } - else - { auto min_elem = std::min_element(ids.begin(), ids.end()); std::rotate(ids.begin(), min_elem, ids.end()); - } } }//end pmp_internal /** @@ -843,6 +836,7 @@ centroid(const TriangleMesh& tmesh) * \ingroup measure_grp * given two meshes, separates the faces that are only in one, the faces * that are only in the other one, and the faces that are common to both. + * Faces with different orientations will be considered as not shared. * * @tparam PolygonMesh a model of `HalfedgeListGraph` and `FaceListGraph` * @tparam OutputFaceIterator model of `OutputIterator` @@ -882,15 +876,6 @@ centroid(const TriangleMesh& tmesh) * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd - * \cgalParamNBegin{require_same_orientation} - * \cgalParamDescription{Parameter (np1 only) to indicate if face orientation should be taken - * into account when determining whether two faces are duplicates. - * If `true`, then the triangles `0,1,2` and `0,2,1` will not be considered - * as "shared" between the two meshes.} - * \cgalParamType{Boolean} - * \cgalParamDefault{`false`} - *\cgalParamNEnd - * \cgalNamedParamsEnd * */ @@ -911,7 +896,6 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, get_const_property_map(vertex_point, m2)); VIMap1 vim1 = get_initialized_vertex_index_map(m1, np1); VIMap1 vim2 = get_initialized_vertex_index_map(m2, np2); - const bool same_orientation = choose_parameter(get_parameter(np1, internal_np::require_same_orientation), false); typedef typename boost::property_traits::value_type Point_3; typedef typename boost::graph_traits::face_descriptor face_descriptor; @@ -960,7 +944,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, } if(all_shared) { - pmp_internal::rearrange_face_ids(ids, same_orientation); + pmp_internal::rearrange_face_ids(ids); m1_faces_map.insert({ids, f}); } else @@ -982,7 +966,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, } if(all_shared) { - pmp_internal::rearrange_face_ids(ids, same_orientation); + pmp_internal::rearrange_face_ids(ids); auto it = m1_faces_map.find(ids); if(it != m1_faces_map.end()) { diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp index ed8d1b30019..3ce828e8faa 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp @@ -337,7 +337,8 @@ void test_compare() return; } input.close(); - PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::require_same_orientation(true), CGAL::parameters::all_default()); + PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), + std::back_inserter(m2_only)); assert(common.size() == 0); assert(m1_only.size() == 18); assert(m2_only.size() == 18); @@ -346,7 +347,7 @@ void test_compare() int main(int argc, char* argv[]) { -/* const char* filename_polyhedron = + const char* filename_polyhedron = (argc > 1) ? argv[1] : "data/mech-holes-shark.off"; test_polyhedron,Epic>(filename_polyhedron); test_polyhedron,Epec>(filename_polyhedron); @@ -359,7 +360,6 @@ int main(int argc, char* argv[]) // It won't work with Epec for large meshes as it builds up a deep DAG // leading to a stackoverflow when the destructor is called. test_centroid,Epic>(filename_surface_mesh); -*/ test_compare >(); test_compare >(); test_compare >(); @@ -367,3 +367,4 @@ int main(int argc, char* argv[]) std::cerr << "All done." << std::endl; return 0; } + diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp index 11d61ac8916..1fba8c28759 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp @@ -75,14 +75,6 @@ void Polyhedron_demo_diff_between_meshes_plugin::diff() typedef CGAL::Face_filtered_graph Filtered_graph; QCursor c(Qt::WaitCursor); - - QMessageBox msgBox; - msgBox.setText("Require the Same Orientation ?"); - msgBox.setInformativeText("Should face orientation count for duplicate detection ?"); - msgBox.setStandardButtons(QMessageBox::Yes| QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - int ret = msgBox.exec(); - bool same_orientation = (ret == QMessageBox::Yes); CGAL::Three::Three::CursorScopeGuard guard(c); //Get the two meshes. No need to check their existance, applicable() @@ -101,8 +93,7 @@ void Polyhedron_demo_diff_between_meshes_plugin::diff() m2, std::back_inserter(common), std::back_inserter(m1_only), - std::back_inserter(m2_only), - CGAL::parameters::require_same_orientation(same_orientation)); + std::back_inserter(m2_only)); Filtered_graph filter1(m1, m1_only); SMesh mesh1_only, mesh2_only, common_mesh; From ca5867f17255faf921562f2347b5a0d0de6537f3 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 25 Mar 2021 13:27:16 +0100 Subject: [PATCH 19/28] Changes after review --- Installation/CHANGES.md | 16 +++---- .../compare_meshes_example.cpp | 14 +++---- .../Polygon_mesh_processing/data/tet-bis.off | 12 ------ .../Polygon_mesh_processing/data/tet.off | 12 ------ .../CGAL/Polygon_mesh_processing/measure.h | 42 +++++++++---------- 5 files changed, 34 insertions(+), 62 deletions(-) delete mode 100644 Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet-bis.off delete mode 100644 Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet.off diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 26086f5a684..51f5f044456 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -7,7 +7,7 @@ Release date: December 2021 ### [Polygon Mesh Processing](https://doc.cgal.org/5.4/Manual/packages.html#PkgPolygonMeshProcessing) -- Added the function `CGAL::Polygon_mesh_processing::compare_meshes()` which allows, given two meshes, to geometrically detect which faces are only in the first, only in the second, or in both meshes. +- Added the function `CGAL::Polygon_mesh_processing::compare_meshes()` that given two polygon meshes identifies faces present in only one of the two meshes as well as faces present in both. [Release 5.3](https://github.com/CGAL/cgal/releases/tag/v5.3) @@ -439,7 +439,7 @@ Release date: November 2019 - LLVM Clang version 8.0 or later (on Linux or MacOS), and - Apple Clang compiler versions 7.0.2 and 10.0.1 (on MacOS). - Since CGAL 4.9, CGAL can be used as a header-only library, with - dependencies. Since CGAL 5.0, that is now the default, unless + dependencies. Since CGAL 5.0, that is now the default, unless specified differently in the (optional) CMake configuration. - The section "Getting Started with CGAL" of the documentation has been updated and reorganized. @@ -2279,14 +2279,14 @@ Release date: October 2014 - Changes in the set of supported platforms: - The Microsoft Windows Visual C++ compiler 2008 (VC9) is no longer supported since CGAL-4.5. -- Since CGAL version 4.0, Eigen was the recommended third-party +- Since CGAL version 4.0, Eigen was the recommended third-party library to use with *Planar Parameterization of Triangulated Surface Meshes*, *Surface Reconstruction from Point Sets*, *Approximation of Ridges and Umbilics on Triangulated Surface Meshes*, and *Estimation of Local Differential Properties of Point-Sampled Surfaces* - packages. From CGAL version 4.5, Taucs, Blas and Lapack are no + packages. From CGAL version 4.5, Taucs, Blas and Lapack are no longer supported. -- CGAL is now compatible with the new CMake version 3.0. +- CGAL is now compatible with the new CMake version 3.0. ### Triangulated Surface Mesh Deformation (new package) @@ -2425,7 +2425,7 @@ Release date: April 2014 - Additional supported platforms: - The Apple Clang compiler version 5.0 is now supported on - OS X Mavericks. + OS X Mavericks. - The Microsoft Windows Visual C++ compiler 2013 (VC12) is now supported. @@ -2563,7 +2563,7 @@ Release date: October 2013 transparent to the user thanks to the implicit constructor added to `CGAL::Object`. However, it is recommended to upgrade your code. The previous behavior can be restored by defining the macro - `CGAL_INTERSECTION_VERSION` to 1. + `CGAL_INTERSECTION_VERSION` to 1. #### 2D Arrangements @@ -2824,7 +2824,7 @@ Release date: October 2012 - Additional supported platforms: - The Apple Clang compiler versions 3.1 and 3.2 are now supported - on Mac OS X. + on Mac OS X. - Improved configuration for essential and optional external third party software - Added more general script to create CMakeLists.txt files: diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp index 08d3553947a..3f9d726b405 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp @@ -1,10 +1,12 @@ #include #include +#include +#include #include -#include #include #include +#include #include #include @@ -20,8 +22,7 @@ namespace PMP = CGAL::Polygon_mesh_processing; int main(int argc, char* argv[]) { - const char* filename1 = (argc > 1) ? argv[1] : "data/tet.off"; - const char* filename2 = (argc > 2) ? argv[2] : "data/tet-bis.off"; + const char* filename1 = (argc > 1) ? argv[1] : "data/P.off"; Surface_mesh mesh1, mesh2; if(!PMP::read_polygon_mesh(filename1, mesh1)) @@ -29,11 +30,8 @@ int main(int argc, char* argv[]) std::cerr << "Invalid input." << std::endl; return 1; } - if(!PMP::read_polygon_mesh(filename2, mesh2)) - { - std::cerr << "Invalid input." << std::endl; - return 1; - } + mesh2 = mesh1; + CGAL::Euler::add_center_vertex(*halfedges(mesh2).begin(),mesh2); std::vector > common; std::vector m1_only, m2_only; PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only)); diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet-bis.off b/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet-bis.off deleted file mode 100644 index 7ea52d418d4..00000000000 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet-bis.off +++ /dev/null @@ -1,12 +0,0 @@ -OFF -4 4 0 - -0 0 0 -1 0 0 -0 1 0 -0 0 1 - -3 2 1 0 -3 0 3 2 -3 2 3 1 -3 1 3 0 diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet.off b/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet.off deleted file mode 100644 index 0e1fcb3bab7..00000000000 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/data/tet.off +++ /dev/null @@ -1,12 +0,0 @@ -OFF -4 4 0 - -0.0521823 0.0693697 0.0558329 -1 0 0 -0 1 0 -0 0 1 - -3 2 1 0 -3 0 3 2 -3 2 3 1 -3 1 3 0 diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 0ae79f683c4..739d3990e32 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -834,18 +834,16 @@ centroid(const TriangleMesh& tmesh) /** * \ingroup measure_grp - * given two meshes, separates the faces that are only in one, the faces - * that are only in the other one, and the faces that are common to both. - * Faces with different orientations will be considered as not shared. + * identifies faces only present in `m1` and `m2` as well as the faces present + * in both polygon meshes. Two faces are identical if they have the same + * orientation and the same points. * * @tparam PolygonMesh a model of `HalfedgeListGraph` and `FaceListGraph` - * @tparam OutputFaceIterator model of `OutputIterator` - holding `boost::graph_traits::%face_descriptor` - for faces that are only in one mesh. - * @tparam OutputFacePairIterator model of `OutputIterator` + * @tparam FaceOutputIterator model of `OutputIterator` + holding `boost::graph_traits::%face_descriptor`. + * @tparam FacePairOutputIterator model of `OutputIterator` holding `std::pair::%face_descriptor, - boost::graph_traits::%face_descriptor` - for faces that are shared by both meshes. + boost::graph_traits::%face_descriptor`. * * @tparam NamedParameters1 a sequence of \ref bgl_namedparameters "Named Parameters" * @tparam NamedParameters2 a sequence of \ref bgl_namedparameters "Named Parameters" @@ -879,10 +877,10 @@ centroid(const TriangleMesh& tmesh) * \cgalNamedParamsEnd * */ -template +template void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, - OutputFacePairIterator common, OutputFaceIterator m1_only, OutputFaceIterator m2_only, - const NamedParameters1& np1,const NamedParameters2& np2) + FacePairOutputIterator common, FaceOutputIterator m1_only, FaceOutputIterator m2_only, + const NamedParameters1& np1, const NamedParameters2& np2) { using parameters::choose_parameter; using parameters::get_parameter; @@ -895,7 +893,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, VPMap2 vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), get_const_property_map(vertex_point, m2)); VIMap1 vim1 = get_initialized_vertex_index_map(m1, np1); - VIMap1 vim2 = get_initialized_vertex_index_map(m2, np2); + VIMap2 vim2 = get_initialized_vertex_index_map(m2, np2); typedef typename boost::property_traits::value_type Point_3; typedef typename boost::graph_traits::face_descriptor face_descriptor; @@ -905,14 +903,14 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, std::vector m2_vertex_id(vertices(m2).size(), -1); boost::dynamic_bitset<> shared_vertices(m1_vertex_id.size() + m2_vertex_id.size()); - //iterate both meshes to set ids to all points, and set vertex/point_id maps. - std::size_t id =0; + //iterate both meshes to set ids of all points, and set vertex/point_id maps. + std::size_t id = 0; for(auto v : vertices(m1)) { const Point_3& p = get(vpm1, v); auto res = point_id_map.insert(std::make_pair(p, id)); if(res.second) - id++; + ++id; m1_vertex_id[get(vim1, v)]=res.first->second; } for(auto v : vertices(m2)) @@ -920,7 +918,7 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, const Point_3& p = get(vpm2, v); auto res = point_id_map.insert(std::make_pair(p, id)); if(res.second) - id++; + ++id; else shared_vertices.set(res.first->second); m2_vertex_id[get(vim2, v)]=res.first->second; @@ -981,24 +979,24 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, else *m2_only++ = f; } - //all real shared vertices have been removed from the map, so all that remains must go in m1_only + //all shared faces have been removed from the map, so all that remains must go in m1_only for(const auto& it : m1_faces_map) { *m1_only++ = it.second; } } -template +template void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, - OutputFacePairIterator common, OutputFaceIterator m1_only, OutputFaceIterator m2_only, + FacePairOutputIterator common, FaceOutputIterator m1_only, FaceOutputIterator m2_only, const NamedParameters& np) { compare_meshes(m1, m2, common, m1_only, m2_only, np, parameters::all_default()); } -template +template void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, - OutputFacePairIterator common, OutputFaceIterator m1_only, OutputFaceIterator m2_only) + FacePairOutputIterator common, FaceOutputIterator m1_only, FaceOutputIterator m2_only) { compare_meshes(m1, m2, common, m1_only, m2_only, parameters::all_default(), parameters::all_default()); } From 34e2180b22a57441eda3bc6caba7aee5ba5b3ce5 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 1 Apr 2021 13:36:57 +0200 Subject: [PATCH 20/28] rename match_faces --- Installation/CHANGES.md | 2 +- .../PackageDescription.txt | 2 +- .../compare_meshes_example.cpp | 2 +- .../CGAL/Polygon_mesh_processing/measure.h | 20 +++++++++---------- .../Polygon_mesh_processing/measures_test.cpp | 8 ++++---- .../Diff_between_meshes_plugin.cpp | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 51f5f044456..141e0c86abf 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -7,7 +7,7 @@ Release date: December 2021 ### [Polygon Mesh Processing](https://doc.cgal.org/5.4/Manual/packages.html#PkgPolygonMeshProcessing) -- Added the function `CGAL::Polygon_mesh_processing::compare_meshes()` that given two polygon meshes identifies faces present in only one of the two meshes as well as faces present in both. +- Added the function `CGAL::Polygon_mesh_processing::match_faces()` that given two polygon meshes identifies faces present in only one of the two meshes as well as faces present in both. [Release 5.3](https://github.com/CGAL/cgal/releases/tag/v5.3) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt index acdaa96e9ca..8e64ce9b07f 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt @@ -198,7 +198,7 @@ The page \ref bgl_namedparameters "Named Parameters" describes their usage. - \link measure_grp `CGAL::Polygon_mesh_processing::edge_length()` \endlink - \link measure_grp `CGAL::Polygon_mesh_processing::face_border_length()` \endlink - \link measure_grp `CGAL::Polygon_mesh_processing::centroid()` \endlink -- \link measure_grp `CGAL::Polygon_mesh_processing::compare_meshes()` \endlink +- \link measure_grp `CGAL::Polygon_mesh_processing::match_faces()` \endlink \cgalCRPSection{Distance Functions} - `CGAL::Polygon_mesh_processing::approximate_Hausdorff_distance()` diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp index 3f9d726b405..40748393a9e 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp @@ -34,7 +34,7 @@ int main(int argc, char* argv[]) CGAL::Euler::add_center_vertex(*halfedges(mesh2).begin(),mesh2); std::vector > common; std::vector m1_only, m2_only; - PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only)); + PMP::match_faces(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only)); std::cout<<"Faces only in m1 : "< -void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, - FacePairOutputIterator common, FaceOutputIterator m1_only, FaceOutputIterator m2_only, - const NamedParameters1& np1, const NamedParameters2& np2) +void match_faces(const PolygonMesh& m1, const PolygonMesh& m2, + FacePairOutputIterator common, FaceOutputIterator m1_only, FaceOutputIterator m2_only, + const NamedParameters1& np1, const NamedParameters2& np2) { using parameters::choose_parameter; using parameters::get_parameter; @@ -987,18 +987,18 @@ void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, } template -void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, - FacePairOutputIterator common, FaceOutputIterator m1_only, FaceOutputIterator m2_only, - const NamedParameters& np) +void match_faces(const PolygonMesh& m1, const PolygonMesh& m2, + FacePairOutputIterator common, FaceOutputIterator m1_only, FaceOutputIterator m2_only, + const NamedParameters& np) { - compare_meshes(m1, m2, common, m1_only, m2_only, np, parameters::all_default()); + match_faces(m1, m2, common, m1_only, m2_only, np, parameters::all_default()); } template -void compare_meshes(const PolygonMesh& m1, const PolygonMesh& m2, - FacePairOutputIterator common, FaceOutputIterator m1_only, FaceOutputIterator m2_only) +void match_faces(const PolygonMesh& m1, const PolygonMesh& m2, + FacePairOutputIterator common, FaceOutputIterator m1_only, FaceOutputIterator m2_only) { - compare_meshes(m1, m2, common, m1_only, m2_only, parameters::all_default(), parameters::all_default()); + match_faces(m1, m2, common, m1_only, m2_only, parameters::all_default(), parameters::all_default()); } } // namespace Polygon_mesh_processing diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp index 3ce828e8faa..701b9a2a3a6 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp @@ -234,7 +234,7 @@ void test_compare() return; } input.close(); - PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::all_default(), CGAL::parameters::all_default()); + PMP::match_faces(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::all_default(), CGAL::parameters::all_default()); assert(common.size() == 7); assert(m1_only.size() == 11); assert(m2_only.size() == 11); @@ -274,7 +274,7 @@ void test_compare() { fim2.insert(std::make_pair(f, id++)); } - PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::all_default(), CGAL::parameters::all_default()); + PMP::match_faces(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::all_default(), CGAL::parameters::all_default()); assert(common.size() == 3); assert(m1_only.size() == 3); assert(fim1[m1_only[0]] == 0); @@ -308,7 +308,7 @@ void test_compare() return; } input.close(); - PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::all_default(), CGAL::parameters::all_default()); + PMP::match_faces(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only), CGAL::parameters::all_default(), CGAL::parameters::all_default()); assert(common.size() == 17); assert(m1_only.size() == 1); assert(m2_only.size() == 0); @@ -337,7 +337,7 @@ void test_compare() return; } input.close(); - PMP::compare_meshes(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), + PMP::match_faces(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only)); assert(common.size() == 0); assert(m1_only.size() == 18); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp index 1fba8c28759..095002379b7 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp @@ -88,7 +88,7 @@ void Polyhedron_demo_diff_between_meshes_plugin::diff() m2=*m2_item->face_graph(); std::vector m1_only, m2_only; std::vector > common; - CGAL::Polygon_mesh_processing::compare_meshes( + CGAL::Polygon_mesh_processing::match_faces( m1, m2, std::back_inserter(common), From 0dd0b965868811fe106c768f829050c9596f0a26 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 1 Apr 2021 15:39:45 +0200 Subject: [PATCH 21/28] Don't add empty items in plugin --- .../Diff_between_meshes_plugin.cpp | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp index 095002379b7..8ab19827c47 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Diff_between_meshes_plugin.cpp @@ -98,18 +98,25 @@ void Polyhedron_demo_diff_between_meshes_plugin::diff() Filtered_graph filter1(m1, m1_only); SMesh mesh1_only, mesh2_only, common_mesh; CGAL::copy_face_graph(filter1, mesh1_only); - - Scene_surface_mesh_item* mesh1_only_item = new Scene_surface_mesh_item(mesh1_only); - mesh1_only_item->setColor(QColor(Qt::blue)); - mesh1_only_item->setName(QString("%1_only").arg(m1_item->name())); - CGAL::Three::Three::scene()->addItem(mesh1_only_item); + Scene_surface_mesh_item* mesh1_only_item = nullptr; + if(mesh1_only.faces().size() > 0) + { + mesh1_only_item = new Scene_surface_mesh_item(mesh1_only); + mesh1_only_item->setColor(QColor(Qt::blue)); + mesh1_only_item->setName(QString("%1_only").arg(m1_item->name())); + CGAL::Three::Three::scene()->addItem(mesh1_only_item); + } Filtered_graph filter2(m2, m2_only); CGAL::copy_face_graph(filter2, mesh2_only); - Scene_surface_mesh_item* mesh2_only_item = new Scene_surface_mesh_item(mesh2_only); - mesh2_only_item->setColor(QColor(Qt::red)); - mesh2_only_item->setName(QString("%1_only").arg(m2_item->name())); - CGAL::Three::Three::scene()->addItem(mesh2_only_item); + Scene_surface_mesh_item* mesh2_only_item = nullptr; + if(mesh2_only.faces().size() > 0) + { + mesh2_only_item = new Scene_surface_mesh_item(mesh2_only); + mesh2_only_item->setColor(QColor(Qt::red)); + mesh2_only_item->setName(QString("%1_only").arg(m2_item->name())); + CGAL::Three::Three::scene()->addItem(mesh2_only_item); + } m1_only.clear(); m1_only.reserve(common.size()); for(const auto& f_pair : common) @@ -118,17 +125,23 @@ void Polyhedron_demo_diff_between_meshes_plugin::diff() } Filtered_graph filter_common(m1, m1_only); CGAL::copy_face_graph(filter_common, common_mesh); - Scene_surface_mesh_item* common_item = new Scene_surface_mesh_item(common_mesh); - common_item->setColor(QColor(Qt::green)); - CGAL::Three::Three::scene()->addItem(common_item); - common_item->setName(QString("%1 && %2").arg(m1_item->name()).arg(m2_item->name())); - + Scene_surface_mesh_item* common_item = nullptr; + if(common_mesh.faces().size() > 0) + { + common_item = new Scene_surface_mesh_item(common_mesh); + common_item->setColor(QColor(Qt::green)); + CGAL::Three::Three::scene()->addItem(common_item); + common_item->setName(QString("%1 && %2").arg(m1_item->name()).arg(m2_item->name())); + } Scene_group_item* group = new Scene_group_item(); group->setName("Diff result"); CGAL::Three::Three::scene()->addItem(group); - CGAL::Three::Three::scene()->changeGroup(mesh1_only_item, group); - CGAL::Three::Three::scene()->changeGroup(mesh2_only_item, group); - CGAL::Three::Three::scene()->changeGroup(common_item, group); + if(mesh1_only_item) + CGAL::Three::Three::scene()->changeGroup(mesh1_only_item, group); + if(mesh2_only_item) + CGAL::Three::Three::scene()->changeGroup(mesh2_only_item, group); + if(common_item) + CGAL::Three::Three::scene()->changeGroup(common_item, group); m1_item->setVisible(false); m2_item->setVisible(false); From ce9bf321dfb3fcf7b2ebde1d731d746eb3cffc79 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 23 Apr 2021 16:16:53 +0200 Subject: [PATCH 22/28] use num_vertices() instead of vertices().size() (garbage probleme in SMesh) --- .../include/CGAL/Polygon_mesh_processing/measure.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 5a3298dbe7d..2b5745cc64d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -899,8 +899,8 @@ void match_faces(const PolygonMesh& m1, const PolygonMesh& m2, std::map point_id_map; - std::vector m1_vertex_id(vertices(m1).size(), -1); - std::vector m2_vertex_id(vertices(m2).size(), -1); + std::vector m1_vertex_id(num_vertices(m1), -1); + std::vector m2_vertex_id(num_vertices(m2), -1); boost::dynamic_bitset<> shared_vertices(m1_vertex_id.size() + m2_vertex_id.size()); //iterate both meshes to set ids of all points, and set vertex/point_id maps. From b4787adc1983208d7d1da521fd9d88b991d01d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 29 Apr 2021 10:35:26 +0200 Subject: [PATCH 23/28] allow difference mesh types --- .../compare_meshes_example.cpp | 40 +++++++----- .../CGAL/Polygon_mesh_processing/measure.h | 65 +++++++++++-------- 2 files changed, 60 insertions(+), 45 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp index 40748393a9e..5babc6b1ffb 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -16,39 +17,42 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point; typedef CGAL::Surface_mesh Surface_mesh; -typedef boost::graph_traits::vertex_descriptor vertex_descriptor; -typedef boost::graph_traits::face_descriptor face_descriptor; +typedef CGAL::Polyhedron_3 Polyhedron; +typedef boost::graph_traits::face_descriptor face_descriptor_1; +typedef boost::graph_traits::face_descriptor face_descriptor_2; namespace PMP = CGAL::Polygon_mesh_processing; int main(int argc, char* argv[]) { const char* filename1 = (argc > 1) ? argv[1] : "data/P.off"; - Surface_mesh mesh1, mesh2; + Surface_mesh mesh1; + Polyhedron mesh2; if(!PMP::read_polygon_mesh(filename1, mesh1)) { std::cerr << "Invalid input." << std::endl; return 1; } - mesh2 = mesh1; + CGAL::copy_face_graph(mesh1, mesh2); CGAL::Euler::add_center_vertex(*halfedges(mesh2).begin(),mesh2); - std::vector > common; - std::vector m1_only, m2_only; + std::vector > common; + std::vector m1_only; + std::vector m2_only; + PMP::match_faces(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only)); - std::cout<<"Faces only in m1 : "<::%face_descriptor`. + * @tparam PolygonMesh1 a model of `HalfedgeListGraph` and `FaceListGraph` + * @tparam PolygonMesh2 a model of `HalfedgeListGraph` and `FaceListGraph` + * @tparam FaceOutputIterator1 model of `OutputIterator` + holding `boost::graph_traits::%face_descriptor`. + * @tparam FaceOutputIterator2 model of `OutputIterator` + holding `boost::graph_traits::%face_descriptor`. * @tparam FacePairOutputIterator model of `OutputIterator` - holding `std::pair::%face_descriptor, - boost::graph_traits::%face_descriptor`. + holding `std::pair::%face_descriptor, + boost::graph_traits::%face_descriptor`. * * @tparam NamedParameters1 a sequence of \ref bgl_namedparameters "Named Parameters" * @tparam NamedParameters2 a sequence of \ref bgl_namedparameters "Named Parameters" * - * @param m1 the first `PolygonMesh` - * @param m2 the second `PolygonMesh` + * @param m1 the first `PolygonMesh1` + * @param m2 the second `PolygonMesh2` * @param common output iterator collecting the faces that are common to both meshes. * @param m1_only output iterator collecting the faces that are only in `m1` * @param m2_only output iterator collecting the faces that are only in `m2` @@ -858,36 +861,43 @@ centroid(const TriangleMesh& tmesh) * * \cgalNamedParamsBegin * \cgalParamNBegin{vertex_point_map} - * \cgalParamDescription{a property map associating points to the vertices of `m1` (`m2`)} - * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` + * \cgalParamDescription{a property map associating points to the vertices of `m1`} + * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` * as key type and `%Point_3` as value type. `%Point_3` must be LessThanComparable.} - * \cgalParamDefault{`boost::get(CGAL::vertex_point, m1 (m2))`} + * \cgalParamDefault{`boost::get(CGAL::vertex_point, m1)`} + * \cgalParamExtra{The same holds for `m2` and `PolygonMesh2` and the point type must be the same for both meshes.} * \cgalParamNEnd * * \cgalParamNBegin{vertex_index_map} - * \cgalParamDescription{a property map associating to each vertex of `m1` (`m2`) a unique index between `0` and `num_vertices(m1 (m2)) - 1`} + * \cgalParamDescription{a property map associating to each vertex of `m1` a unique index between `0` and `num_vertices(m1) - 1`, and similarly for `m2`.} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance - * in case of non-constant complexity for index access.} + * in case of non-constant complexity for index access. The same holds for `m2` and `PolygonMesh2`.} * \cgalParamNEnd * \cgalNamedParamsEnd * */ -template -void match_faces(const PolygonMesh& m1, const PolygonMesh& m2, - FacePairOutputIterator common, FaceOutputIterator m1_only, FaceOutputIterator m2_only, +template< typename PolygonMesh1, + typename PolygonMesh2, + typename FaceOutputIterator1, + typename FaceOutputIterator2, + typename FacePairOutputIterator, + typename NamedParameters1, + typename NamedParameters2 > +void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, + FacePairOutputIterator common, FaceOutputIterator1 m1_only, FaceOutputIterator2 m2_only, const NamedParameters1& np1, const NamedParameters2& np2) { using parameters::choose_parameter; using parameters::get_parameter; - typedef typename GetVertexPointMap < PolygonMesh, NamedParameters1>::const_type VPMap1; - typedef typename GetVertexPointMap < PolygonMesh, NamedParameters2>::const_type VPMap2; - typedef typename GetInitializedVertexIndexMap::const_type VIMap1; - typedef typename GetInitializedVertexIndexMap::const_type VIMap2; + typedef typename GetVertexPointMap < PolygonMesh1, NamedParameters1>::const_type VPMap1; + typedef typename GetVertexPointMap < PolygonMesh2, NamedParameters2>::const_type VPMap2; + typedef typename GetInitializedVertexIndexMap::const_type VIMap1; + typedef typename GetInitializedVertexIndexMap::const_type VIMap2; VPMap1 vpm1 = choose_parameter(get_parameter(np1, internal_np::vertex_point), get_const_property_map(vertex_point, m1)); VPMap2 vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), @@ -895,7 +905,8 @@ void match_faces(const PolygonMesh& m1, const PolygonMesh& m2, VIMap1 vim1 = get_initialized_vertex_index_map(m1, np1); VIMap2 vim2 = get_initialized_vertex_index_map(m2, np2); typedef typename boost::property_traits::value_type Point_3; - typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor_1; + typedef typename boost::graph_traits::face_descriptor face_descriptor_2; std::map point_id_map; @@ -925,7 +936,7 @@ void match_faces(const PolygonMesh& m1, const PolygonMesh& m2, } //fill a set with the "faces point-ids" of m1 and then iterate faces of m2 to compare. - std::map, face_descriptor> m1_faces_map; + std::map, face_descriptor_1> m1_faces_map; for(auto f : faces(m1)) { bool all_shared = true; @@ -986,17 +997,17 @@ void match_faces(const PolygonMesh& m1, const PolygonMesh& m2, } } -template -void match_faces(const PolygonMesh& m1, const PolygonMesh& m2, - FacePairOutputIterator common, FaceOutputIterator m1_only, FaceOutputIterator m2_only, +template +void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, + FacePairOutputIterator common, FaceOutputIterator1 m1_only, FaceOutputIterator2 m2_only, const NamedParameters& np) { match_faces(m1, m2, common, m1_only, m2_only, np, parameters::all_default()); } -template -void match_faces(const PolygonMesh& m1, const PolygonMesh& m2, - FacePairOutputIterator common, FaceOutputIterator m1_only, FaceOutputIterator m2_only) +template +void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, + FacePairOutputIterator common, FaceOutputIterator1 m1_only, FaceOutputIterator2 m2_only) { match_faces(m1, m2, common, m1_only, m2_only, parameters::all_default(), parameters::all_default()); } From d0608093ec9ef3e0a90bee0a7981ddfa233eed6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 29 Apr 2021 17:46:14 +0200 Subject: [PATCH 24/28] remove unused typedef --- .../include/CGAL/Polygon_mesh_processing/measure.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 88f5bbb934c..f6cf6936f42 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -906,7 +906,6 @@ void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, VIMap2 vim2 = get_initialized_vertex_index_map(m2, np2); typedef typename boost::property_traits::value_type Point_3; typedef typename boost::graph_traits::face_descriptor face_descriptor_1; - typedef typename boost::graph_traits::face_descriptor face_descriptor_2; std::map point_id_map; From acd6bb3c5772ed78535d23e2c2c2ba952214cec5 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 20 May 2021 09:00:29 +0200 Subject: [PATCH 25/28] Fix namespace and remove unused typedef --- .../examples/Polygon_mesh_processing/compare_meshes_example.cpp | 2 +- .../test/Polygon_mesh_processing/measures_test.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp index 5babc6b1ffb..dd86d8d5c04 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp @@ -28,7 +28,7 @@ int main(int argc, char* argv[]) Surface_mesh mesh1; Polyhedron mesh2; - if(!PMP::read_polygon_mesh(filename1, mesh1)) + if(!PMP::IO::read_polygon_mesh(filename1, mesh1)) { std::cerr << "Invalid input." << std::endl; return 1; diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp index 701b9a2a3a6..ef332cd6136 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp @@ -206,7 +206,6 @@ void test_centroid(const char* filename) template void test_compare() { - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; namespace PMP = CGAL::Polygon_mesh_processing; From 553445a7715895252661887ca4643bbeb8ed041c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 26 May 2021 11:16:09 +0200 Subject: [PATCH 26/28] Changes after review 1 --- Installation/CHANGES.md | 2 +- .../Polygon_mesh_processing/CMakeLists.txt | 2 +- ...are_meshes_example.cpp => match_faces.cpp} | 10 ++-- .../CGAL/Polygon_mesh_processing/measure.h | 59 ++++++++++--------- .../Polygon_mesh_processing/measures_test.cpp | 21 ++++--- 5 files changed, 50 insertions(+), 44 deletions(-) rename Polygon_mesh_processing/examples/Polygon_mesh_processing/{compare_meshes_example.cpp => match_faces.cpp} (88%) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 40fe84474fb..6265fd05190 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -7,7 +7,7 @@ Release date: December 2021 ### [Polygon Mesh Processing](https://doc.cgal.org/5.4/Manual/packages.html#PkgPolygonMeshProcessing) -- Added the function `CGAL::Polygon_mesh_processing::match_faces()` that given two polygon meshes identifies faces present in only one of the two meshes as well as faces present in both. +- Added the function `CGAL::Polygon_mesh_processing::match_faces()`, which, given two polygon meshes, identifies their common faces as well as as faces present in only either of them. [Release 5.3](https://github.com/CGAL/cgal/releases/tag/v5.3) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index e52fa4e4ccf..ad9c683900e 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -90,7 +90,7 @@ create_single_source_cgal_program("locate_example.cpp") create_single_source_cgal_program("orientation_pipeline_example.cpp") #create_single_source_cgal_program( "self_snapping_example.cpp") #create_single_source_cgal_program( "snapping_example.cpp") -create_single_source_cgal_program("compare_meshes_example.cpp") +create_single_source_cgal_program("match_faces.cpp") if(OpenMesh_FOUND) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/match_faces.cpp similarity index 88% rename from Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp rename to Polygon_mesh_processing/examples/Polygon_mesh_processing/match_faces.cpp index dd86d8d5c04..9eeae6b6d00 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/match_faces.cpp @@ -41,15 +41,15 @@ int main(int argc, char* argv[]) PMP::match_faces(mesh1, mesh2, std::back_inserter(common), std::back_inserter(m1_only), std::back_inserter(m2_only)); - std::cout<<"Faces only in m1 :"<& ids) { - auto min_elem = std::min_element(ids.begin(), ids.end()); - std::rotate(ids.begin(), min_elem, ids.end()); + auto min_elem = std::min_element(ids.begin(), ids.end()); + std::rotate(ids.begin(), min_elem, ids.end()); } -}//end pmp_internal +}//namespace pmp_internal /** * \ingroup measure_grp * computes the length of an edge of a given polygon mesh. @@ -835,7 +835,7 @@ centroid(const TriangleMesh& tmesh) /** * \ingroup measure_grp * identifies faces only present in `m1` and `m2` as well as the faces present - * in both polygon meshes. Two faces are identical if they have the same + * in both polygon meshes. Two faces are matching if they have the same * orientation and the same points. * * @tparam PolygonMesh1 a model of `HalfedgeListGraph` and `FaceListGraph` @@ -851,8 +851,8 @@ centroid(const TriangleMesh& tmesh) * @tparam NamedParameters1 a sequence of \ref bgl_namedparameters "Named Parameters" * @tparam NamedParameters2 a sequence of \ref bgl_namedparameters "Named Parameters" * - * @param m1 the first `PolygonMesh1` - * @param m2 the second `PolygonMesh2` + * @param m1 the first `PolygonMesh` + * @param m2 the second `PolygonMesh` * @param common output iterator collecting the faces that are common to both meshes. * @param m1_only output iterator collecting the faces that are only in `m1` * @param m2_only output iterator collecting the faces that are only in `m2` @@ -863,7 +863,7 @@ centroid(const TriangleMesh& tmesh) * \cgalParamNBegin{vertex_point_map} * \cgalParamDescription{a property map associating points to the vertices of `m1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` - * as key type and `%Point_3` as value type. `%Point_3` must be LessThanComparable.} + * as key type and `%Point_3` as value type. `%Point_3` must be `LessThanComparable`.} * \cgalParamDefault{`boost::get(CGAL::vertex_point, m1)`} * \cgalParamExtra{The same holds for `m2` and `PolygonMesh2` and the point type must be the same for both meshes.} * \cgalParamNEnd @@ -883,29 +883,32 @@ centroid(const TriangleMesh& tmesh) */ template< typename PolygonMesh1, typename PolygonMesh2, + typename FacePairOutputIterator, typename FaceOutputIterator1, typename FaceOutputIterator2, - typename FacePairOutputIterator, typename NamedParameters1, typename NamedParameters2 > void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, FacePairOutputIterator common, FaceOutputIterator1 m1_only, FaceOutputIterator2 m2_only, const NamedParameters1& np1, const NamedParameters2& np2) { - using parameters::choose_parameter; - using parameters::get_parameter; - typedef typename GetVertexPointMap < PolygonMesh1, NamedParameters1>::const_type VPMap1; - typedef typename GetVertexPointMap < PolygonMesh2, NamedParameters2>::const_type VPMap2; + typedef typename GetVertexPointMap::const_type VPMap1; + typedef typename GetVertexPointMap::const_type VPMap2; typedef typename GetInitializedVertexIndexMap::const_type VIMap1; typedef typename GetInitializedVertexIndexMap::const_type VIMap2; - VPMap1 vpm1 = choose_parameter(get_parameter(np1, internal_np::vertex_point), - get_const_property_map(vertex_point, m1)); - VPMap2 vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), - get_const_property_map(vertex_point, m2)); - VIMap1 vim1 = get_initialized_vertex_index_map(m1, np1); - VIMap2 vim2 = get_initialized_vertex_index_map(m2, np2); - typedef typename boost::property_traits::value_type Point_3; - typedef typename boost::graph_traits::face_descriptor face_descriptor_1; + typedef typename boost::property_traits::value_type Point_3; + typedef typename boost::graph_traits::face_descriptor face_descriptor_1; + + using parameters::choose_parameter; + using parameters::get_parameter; + + const VPMap1 vpm1 = choose_parameter(get_parameter(np1, internal_np::vertex_point), + get_const_property_map(vertex_point, m1)); + const VPMap2 vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), + get_const_property_map(vertex_point, m2)); + + const VIMap1 vim1 = get_initialized_vertex_index_map(m1, np1); + const VIMap2 vim2 = get_initialized_vertex_index_map(m2, np2); std::map point_id_map; @@ -918,20 +921,20 @@ void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, for(auto v : vertices(m1)) { const Point_3& p = get(vpm1, v); - auto res = point_id_map.insert(std::make_pair(p, id)); + auto res = point_id_map.emplace(p, id); if(res.second) ++id; - m1_vertex_id[get(vim1, v)]=res.first->second; + m1_vertex_id[get(vim1, v)] = res.first->second; } for(auto v : vertices(m2)) { const Point_3& p = get(vpm2, v); - auto res = point_id_map.insert(std::make_pair(p, id)); + auto res = point_id_map.emplace(p, id); if(res.second) ++id; else shared_vertices.set(res.first->second); - m2_vertex_id[get(vim2, v)]=res.first->second; + m2_vertex_id[get(vim2, v)] = res.first->second; } //fill a set with the "faces point-ids" of m1 and then iterate faces of m2 to compare. @@ -942,7 +945,7 @@ void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, boost::container::small_vector ids; for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) { - std::size_t vid = m1_vertex_id[get(vim1, v)]; + std::size_t vid = m1_vertex_id[get(vim1, v)]; ids.push_back(vid); if(!shared_vertices.test(vid)) { @@ -953,7 +956,7 @@ void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, if(all_shared) { pmp_internal::rearrange_face_ids(ids); - m1_faces_map.insert({ids, f}); + m1_faces_map.emplace(ids, f); } else *m1_only++ = f; @@ -996,7 +999,7 @@ void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, } } -template +template void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, FacePairOutputIterator common, FaceOutputIterator1 m1_only, FaceOutputIterator2 m2_only, const NamedParameters& np) @@ -1004,7 +1007,7 @@ void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, match_faces(m1, m2, common, m1_only, m2_only, np, parameters::all_default()); } -template +template void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, FacePairOutputIterator common, FaceOutputIterator1 m1_only, FaceOutputIterator2 m2_only) { diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp index ef332cd6136..7522600665f 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp @@ -203,16 +203,19 @@ void test_centroid(const char* filename) } -template +template void test_compare() { - typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor1; + typedef typename boost::graph_traits::face_descriptor face_descriptor2; namespace PMP = CGAL::Polygon_mesh_processing; - PolygonMesh mesh1, mesh2; - std::vector > common; + PolygonMesh1 mesh1; + PolygonMesh2 mesh2; + std::vector > common; common.clear(); - std::vector m1_only, m2_only; + std::vector m1_only; + std::vector m2_only; /************************* * triangulated and open * * **********************/ @@ -261,8 +264,8 @@ void test_compare() return; } input.close(); - std::unordered_map fim1; - std::unordered_map fim2; + std::unordered_map fim1; + std::unordered_map fim2; std::size_t id = 0; for(const auto& f : faces(mesh1)) { @@ -361,8 +364,8 @@ int main(int argc, char* argv[]) test_centroid,Epic>(filename_surface_mesh); test_compare >(); test_compare >(); - test_compare >(); - test_compare >(); + test_compare, CGAL::Polyhedron_3 >(); + test_compare, CGAL::Polyhedron_3 >(); std::cerr << "All done." << std::endl; return 0; } From c6c540503c0cc4718fcc31d65cb91884a5727956 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 26 May 2021 11:46:03 +0200 Subject: [PATCH 27/28] changes after review 2 --- .../CGAL/Polygon_mesh_processing/measure.h | 15 +++++++++------ .../Polygon_mesh_processing/measures_test.cpp | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h index 3360484c567..f65caaaa87a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/measure.h @@ -53,14 +53,14 @@ public: namespace Polygon_mesh_processing { -namespace pmp_internal { +namespace internal { inline void rearrange_face_ids(boost::container::small_vector& ids) { auto min_elem = std::min_element(ids.begin(), ids.end()); std::rotate(ids.begin(), min_elem, ids.end()); } -}//namespace pmp_internal +}//namespace internal /** * \ingroup measure_grp * computes the length of an edge of a given polygon mesh. @@ -906,6 +906,9 @@ void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, get_const_property_map(vertex_point, m1)); const VPMap2 vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), get_const_property_map(vertex_point, m2)); + CGAL_static_assertion_msg((boost::is_same::value_type, + typename boost::property_traits::value_type>::value), + "Both vertex point maps must have the same point type."); const VIMap1 vim1 = get_initialized_vertex_index_map(m1, np1); const VIMap2 vim2 = get_initialized_vertex_index_map(m2, np2); @@ -920,7 +923,7 @@ void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, std::size_t id = 0; for(auto v : vertices(m1)) { - const Point_3& p = get(vpm1, v); + const typename boost::property_traits::reference p = get(vpm1, v); auto res = point_id_map.emplace(p, id); if(res.second) ++id; @@ -928,7 +931,7 @@ void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, } for(auto v : vertices(m2)) { - const Point_3& p = get(vpm2, v); + const typename boost::property_traits::reference p = get(vpm2, v); auto res = point_id_map.emplace(p, id); if(res.second) ++id; @@ -955,7 +958,7 @@ void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, } if(all_shared) { - pmp_internal::rearrange_face_ids(ids); + internal::rearrange_face_ids(ids); m1_faces_map.emplace(ids, f); } else @@ -977,7 +980,7 @@ void match_faces(const PolygonMesh1& m1, const PolygonMesh2& m2, } if(all_shared) { - pmp_internal::rearrange_face_ids(ids); + internal::rearrange_face_ids(ids); auto it = m1_faces_map.find(ids); if(it != m1_faces_map.end()) { diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp index 7522600665f..b8db4721474 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/measures_test.cpp @@ -362,8 +362,8 @@ int main(int argc, char* argv[]) // It won't work with Epec for large meshes as it builds up a deep DAG // leading to a stackoverflow when the destructor is called. test_centroid,Epic>(filename_surface_mesh); - test_compare >(); - test_compare >(); + test_compare, CGAL::Surface_mesh >(); + test_compare, CGAL::Surface_mesh >(); test_compare, CGAL::Polyhedron_3 >(); test_compare, CGAL::Polyhedron_3 >(); std::cerr << "All done." << std::endl; From 523b54e4f70ee13212d09302270810bd6b76597d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 26 May 2021 15:22:27 +0200 Subject: [PATCH 28/28] Fix changes.md --- Installation/CHANGES.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 6265fd05190..dd07172543d 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -9,7 +9,6 @@ Release date: December 2021 - Added the function `CGAL::Polygon_mesh_processing::match_faces()`, which, given two polygon meshes, identifies their common faces as well as as faces present in only either of them. - [Release 5.3](https://github.com/CGAL/cgal/releases/tag/v5.3) ----------- @@ -468,7 +467,7 @@ Release date: November 2019 - LLVM Clang version 8.0 or later (on Linux or MacOS), and - Apple Clang compiler versions 7.0.2 and 10.0.1 (on MacOS). - Since CGAL 4.9, CGAL can be used as a header-only library, with - dependencies. Since CGAL 5.0, that is now the default, unless + dependencies. Since CGAL 5.0, that is now the default, unless specified differently in the (optional) CMake configuration. - The section "Getting Started with CGAL" of the documentation has been updated and reorganized. @@ -2308,14 +2307,14 @@ Release date: October 2014 - Changes in the set of supported platforms: - The Microsoft Windows Visual C++ compiler 2008 (VC9) is no longer supported since CGAL-4.5. -- Since CGAL version 4.0, Eigen was the recommended third-party +- Since CGAL version 4.0, Eigen was the recommended third-party library to use with *Planar Parameterization of Triangulated Surface Meshes*, *Surface Reconstruction from Point Sets*, *Approximation of Ridges and Umbilics on Triangulated Surface Meshes*, and *Estimation of Local Differential Properties of Point-Sampled Surfaces* - packages. From CGAL version 4.5, Taucs, Blas and Lapack are no + packages. From CGAL version 4.5, Taucs, Blas and Lapack are no longer supported. -- CGAL is now compatible with the new CMake version 3.0. +- CGAL is now compatible with the new CMake version 3.0. ### Triangulated Surface Mesh Deformation (new package) @@ -2454,7 +2453,7 @@ Release date: April 2014 - Additional supported platforms: - The Apple Clang compiler version 5.0 is now supported on - OS X Mavericks. + OS X Mavericks. - The Microsoft Windows Visual C++ compiler 2013 (VC12) is now supported. @@ -2592,7 +2591,7 @@ Release date: October 2013 transparent to the user thanks to the implicit constructor added to `CGAL::Object`. However, it is recommended to upgrade your code. The previous behavior can be restored by defining the macro - `CGAL_INTERSECTION_VERSION` to 1. + `CGAL_INTERSECTION_VERSION` to 1. #### 2D Arrangements @@ -2853,7 +2852,7 @@ Release date: October 2012 - Additional supported platforms: - The Apple Clang compiler versions 3.1 and 3.2 are now supported - on Mac OS X. + on Mac OS X. - Improved configuration for essential and optional external third party software - Added more general script to create CMakeLists.txt files: