-
Notifications
You must be signed in to change notification settings - Fork 1.6k
PMP: compare_meshes #5544
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
sloriot
merged 29 commits into
CGAL:master
from
maxGimeno:PMP-compare_faces_from_meshes-maxGimeno
Jul 19, 2021
Merged
PMP: compare_meshes #5544
Changes from 26 commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
0675a0d
WIP
maxGimeno 96a88df
Working example.
maxGimeno 67aaf04
doc + example + tests
maxGimeno 836a7b8
update CHANGES.md
maxGimeno 7d4a661
Overloads, plugin and data sets
maxGimeno c1895e7
mutbale ranges in doc
maxGimeno 22e13fa
1st pass after review
maxGimeno 2770171
Only 2 loops for faces
maxGimeno 8c5fcd9
Replace by bitset
maxGimeno dd90a3c
OutputIterators
maxGimeno 8f92a01
clean-up
maxGimeno aa2b527
Fix holes situation
maxGimeno 2771176
Add a NP for orientation requirement
maxGimeno f4da318
add new tests
maxGimeno cc4d274
Clarify np
maxGimeno c3036b1
clean-up
maxGimeno 5f4437b
Fix missing inline and doc
maxGimeno 9e6eaa5
Orientation requirements always on, as it won't work without it on no…
maxGimeno ca5867f
Changes after review
maxGimeno 34e2180
rename match_faces
maxGimeno 0dd0b96
Don't add empty items in plugin
maxGimeno ce9bf32
use num_vertices() instead of vertices().size() (garbage probleme in …
maxGimeno b4787ad
allow difference mesh types
sloriot d060809
remove unused typedef
sloriot 797c5ad
Merge remote-tracking branch 'cgal/master' into PMP-compare_faces_fro…
maxGimeno acd6bb3
Fix namespace and remove unused typedef
maxGimeno 553445a
Changes after review 1
maxGimeno c6c5405
changes after review 2
maxGimeno 523b54e
Fix changes.md
maxGimeno File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
Polygon_mesh_processing/examples/Polygon_mesh_processing/compare_meshes_example.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| #include <CGAL/Exact_predicates_inexact_constructions_kernel.h> | ||
| #include <CGAL/Surface_mesh.h> | ||
| #include <CGAL/Polyhedron_3.h> | ||
|
|
||
| #include <CGAL/boost/graph/copy_face_graph.h> | ||
| #include <CGAL/boost/graph/Euler_operations.h> | ||
| #include <CGAL/Polygon_mesh_processing/measure.h> | ||
| #include <CGAL/boost/graph/Named_function_parameters.h> | ||
| #include <CGAL/boost/graph/named_params_helper.h> | ||
| #include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h> | ||
|
|
||
| #include <fstream> | ||
| #include <iostream> | ||
|
|
||
| typedef CGAL::Exact_predicates_inexact_constructions_kernel K; | ||
|
|
||
| typedef K::Point_3 Point; | ||
|
|
||
| typedef CGAL::Surface_mesh<Point> Surface_mesh; | ||
| typedef CGAL::Polyhedron_3<K> Polyhedron; | ||
| typedef boost::graph_traits<Surface_mesh>::face_descriptor face_descriptor_1; | ||
| typedef boost::graph_traits<Polyhedron>::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; | ||
| Polyhedron mesh2; | ||
| if(!PMP::IO::read_polygon_mesh(filename1, mesh1)) | ||
| { | ||
| std::cerr << "Invalid input." << std::endl; | ||
| return 1; | ||
| } | ||
| CGAL::copy_face_graph(mesh1, mesh2); | ||
| CGAL::Euler::add_center_vertex(*halfedges(mesh2).begin(),mesh2); | ||
| std::vector<std::pair<face_descriptor_1, face_descriptor_2> > common; | ||
| std::vector<face_descriptor_1> m1_only; | ||
| std::vector<face_descriptor_2> 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 :"<<std::endl; | ||
| for(const auto& f : m1_only) | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| std::cout << " " << f; | ||
|
|
||
| std::cout<<"\n\nFaces only in m2:"<<std::endl; | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| for(const auto& f : m2_only) | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| std::cout << " " << &(*f); | ||
|
|
||
| std::cout<<"\n\nFaces in both:"<<std::endl; | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| for(const auto& f_pair : common) | ||
| std::cout << " (" << f_pair.first << ", " << &(*f_pair.second); | ||
| std::cout << std::endl; | ||
|
|
||
| return 0; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,10 +28,13 @@ | |
|
|
||
| #include <CGAL/Lazy.h> // needed for CGAL::exact(FT)/CGAL::exact(Lazy_exact_nt<T>) | ||
|
|
||
| #include <boost/container/small_vector.hpp> | ||
| #include <boost/unordered_set.hpp> | ||
| #include <boost/graph/graph_traits.hpp> | ||
| #include <boost/dynamic_bitset.hpp> | ||
|
|
||
| #include <utility> | ||
| #include <algorithm> | ||
|
|
||
| #ifdef DOXYGEN_RUNNING | ||
| #define CGAL_PMP_NP_TEMPLATE_PARAMETERS NamedParameters | ||
|
|
@@ -50,6 +53,14 @@ class GetGeomTraits<CGAL_PMP_NP_CLASS, NP> | |
|
|
||
| namespace Polygon_mesh_processing { | ||
|
|
||
| namespace pmp_internal { | ||
|
|
||
| inline void rearrange_face_ids(boost::container::small_vector<std::size_t, 4>& ids) | ||
| { | ||
| auto min_elem = std::min_element(ids.begin(), ids.end()); | ||
| std::rotate(ids.begin(), min_elem, ids.end()); | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| }//end pmp_internal | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| /** | ||
| * \ingroup measure_grp | ||
| * computes the length of an edge of a given polygon mesh. | ||
|
|
@@ -820,6 +831,186 @@ centroid(const TriangleMesh& tmesh) | |
| return centroid(tmesh, CGAL::Polygon_mesh_processing::parameters::all_default()); | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * \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 | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| * orientation and the same points. | ||
| * | ||
| * @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<PolygonMesh1>::%face_descriptor`. | ||
| * @tparam FaceOutputIterator2 model of `OutputIterator` | ||
| holding `boost::graph_traits<PolygonMesh2>::%face_descriptor`. | ||
| * @tparam FacePairOutputIterator model of `OutputIterator` | ||
| holding `std::pair<boost::graph_traits<PolygonMesh1>::%face_descriptor, | ||
| boost::graph_traits<PolygonMesh2>::%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 `PolygonMesh1` | ||
| * @param m2 the second `PolygonMesh2` | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| * @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` | ||
|
Comment on lines
+856
to
+858
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These aren't top notch variable names
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| * @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`} | ||
| * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits<PolygonMesh1>::%vertex_descriptor` | ||
| * as key type and `%Point_3` as value type. `%Point_3` must be LessThanComparable.} | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| * \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` a unique index between `0` and `num_vertices(m1) - 1`, and similarly for `m2`.} | ||
| * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits<Graph>::%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. The same holds for `m2` and `PolygonMesh2`.} | ||
| * \cgalParamNEnd | ||
maxGimeno marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * \cgalNamedParamsEnd | ||
| * | ||
| */ | ||
| template< typename PolygonMesh1, | ||
| typename PolygonMesh2, | ||
| typename FaceOutputIterator1, | ||
| typename FaceOutputIterator2, | ||
| typename FacePairOutputIterator, | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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 GetInitializedVertexIndexMap<PolygonMesh1, NamedParameters1>::const_type VIMap1; | ||
| typedef typename GetInitializedVertexIndexMap<PolygonMesh2, NamedParameters2>::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<VPMap2>::value_type Point_3; | ||
| typedef typename boost::graph_traits<PolygonMesh1>::face_descriptor face_descriptor_1; | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| std::map<Point_3, std::size_t> point_id_map; | ||
|
|
||
| std::vector<std::size_t> m1_vertex_id(num_vertices(m1), -1); | ||
| std::vector<std::size_t> 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. | ||
| std::size_t id = 0; | ||
| for(auto v : vertices(m1)) | ||
| { | ||
| const Point_3& p = get(vpm1, v); | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| auto res = point_id_map.insert(std::make_pair(p, id)); | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if(res.second) | ||
| ++id; | ||
| m1_vertex_id[get(vim1, v)]=res.first->second; | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| for(auto v : vertices(m2)) | ||
| { | ||
| const Point_3& p = get(vpm2, v); | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| auto res = point_id_map.insert(std::make_pair(p, id)); | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if(res.second) | ||
| ++id; | ||
| else | ||
| shared_vertices.set(res.first->second); | ||
| m2_vertex_id[get(vim2, v)]=res.first->second; | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| //fill a set with the "faces point-ids" of m1 and then iterate faces of m2 to compare. | ||
| std::map<boost::container::small_vector<std::size_t, 4>, face_descriptor_1> m1_faces_map; | ||
| for(auto f : faces(m1)) | ||
| { | ||
| bool all_shared = true; | ||
| boost::container::small_vector<std::size_t, 4> ids; | ||
| for(auto v : CGAL::vertices_around_face(halfedge(f, m1), m1)) | ||
| { | ||
| std::size_t vid = m1_vertex_id[get(vim1, v)]; | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ids.push_back(vid); | ||
| if(!shared_vertices.test(vid)) | ||
| { | ||
| all_shared = false; | ||
maxGimeno marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| break; | ||
| } | ||
| } | ||
| if(all_shared) | ||
| { | ||
| pmp_internal::rearrange_face_ids(ids); | ||
| m1_faces_map.insert({ids, f}); | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
maxGimeno marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| else | ||
| *m1_only++ = f; | ||
| } | ||
| for(auto f : faces(m2)) | ||
| { | ||
| boost::container::small_vector<std::size_t, 4> ids; | ||
| bool all_shared = true; | ||
| for(auto v : CGAL::vertices_around_face(halfedge(f, m2), m2)) | ||
| { | ||
| std::size_t vid = m2_vertex_id[get(vim2, v)]; | ||
| ids.push_back(vid); | ||
| if(!shared_vertices.test(vid)) | ||
| { | ||
| all_shared = false; | ||
| break; | ||
| } | ||
| } | ||
| if(all_shared) | ||
| { | ||
| pmp_internal::rearrange_face_ids(ids); | ||
| auto it = m1_faces_map.find(ids); | ||
| if(it != m1_faces_map.end()) | ||
| { | ||
| *common++ = std::make_pair(it->second, f); | ||
| m1_faces_map.erase(it); | ||
| } | ||
| else | ||
| { | ||
| *m2_only++ = f; | ||
| } | ||
| } | ||
| else | ||
| *m2_only++ = f; | ||
| } | ||
| //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<typename PolygonMesh1, typename PolygonMesh2, typename FaceOutputIterator1, typename FaceOutputIterator2, typename FacePairOutputIterator, typename NamedParameters> | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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<typename PolygonMesh1, typename PolygonMesh2, typename FaceOutputIterator1, typename FaceOutputIterator2, typename FacePairOutputIterator> | ||
maxGimeno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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()); | ||
| } | ||
|
|
||
| } // namespace Polygon_mesh_processing | ||
| } // namespace CGAL | ||
|
|
||
|
|
||
18 changes: 18 additions & 0 deletions
18
Polygon_mesh_processing/test/Polygon_mesh_processing/data/cube_quad2.off
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| OFF | ||
| 8 6 0 | ||
|
|
||
| -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 | ||
| 4 2 1 5 6 | ||
| 4 1 0 4 5 | ||
| 4 4 7 6 5 | ||
| 4 0 1 2 3 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.