Fix merge_duplicated_points

`Union_find` is required to merge correct patch ids.
This commit is contained in:
Laurent Rineau 2018-02-01 17:07:35 +01:00
parent 50865f38e8
commit f2bc9d6b62
1 changed files with 41 additions and 14 deletions

View File

@ -29,6 +29,7 @@
#include <CGAL/Mesh_3/config.h> #include <CGAL/Mesh_3/config.h>
#include <CGAL/Random.h> #include <CGAL/Random.h>
#include <CGAL/Union_find.h>
#include <CGAL/Polyhedral_mesh_domain_3.h> #include <CGAL/Polyhedral_mesh_domain_3.h>
#include <CGAL/Mesh_domain_with_polyline_features_3.h> #include <CGAL/Mesh_domain_with_polyline_features_3.h>
#include <CGAL/Mesh_polyhedron_3.h> #include <CGAL/Mesh_polyhedron_3.h>
@ -954,6 +955,15 @@ merge_duplicated_points(const PointSet& duplicated_points)
if (duplicated_points.empty()) if (duplicated_points.empty())
return; return;
//collect ids to be modified
typedef CGAL::Union_find<Patch_id> Union_find_t;
Union_find_t union_find;
std::vector<typename Union_find_t::handle> handles;
handles.resize(this->nb_of_patch_plus_one());
for (std::size_t i = 0; i < this->nb_of_patch_plus_one(); ++i) {
handles[i] = union_find.make_set(Patch_id(i));
}
Patch_multimap patches; Patch_multimap patches;
BOOST_FOREACH(const Polyhedron_type& p, stored_polyhedra) BOOST_FOREACH(const Polyhedron_type& p, stored_polyhedra)
{ {
@ -978,11 +988,6 @@ merge_duplicated_points(const PointSet& duplicated_points)
} }
} }
//collect ids to be modified
std::vector<Patch_id> new_ids(this->nb_of_patch_plus_one());
for (std::size_t i = 0; i < this->nb_of_patch_plus_one(); ++i)
new_ids[i] = Patch_id(i);
for (Patch_iterator pit = patches.begin(); for (Patch_iterator pit = patches.begin();
pit != patches.end(); pit != patches.end();
/*pit = range_end inside loop*/) /*pit = range_end inside loop*/)
@ -994,24 +999,32 @@ merge_duplicated_points(const PointSet& duplicated_points)
// loop will end with the first iterator when the point differs from // loop will end with the first iterator when the point differs from
// the point of the range). // the point of the range).
Patch_iterator it = range_begin; Patch_iterator it = range_begin;
CGAL_assertion(std::size_t(it->second) < new_ids.size());
Patch_id min_id_around_p = new_ids[it->second];
++it; ++it;
for (; it != patches.end() && it->first == range_begin->first; ++it) for (; it != patches.end() && it->first == range_begin->first; ++it)
{ {
CGAL_assertion(std::size_t(it->second) < new_ids.size());
min_id_around_p = (std::min)(min_id_around_p, new_ids[it->second]);
} }
const Patch_iterator range_end = it; const Patch_iterator range_end = it;
#if CGAL_MESH_3_VERBOSE > 10
std::cerr << "Point " << range_begin->first.first << " is duplicated, in "
<< "the following patches:\n";
#endif // CGAL_MESH_3_VERBOSE
typename Union_find_t::handle first_handle =
handles[range_begin->second];
// In a second loop on the equal-range, update new_ids around p // In a second loop on the equal-range, update new_ids around p
for (it = range_begin; it != range_end; ++it) for (it = boost::next(range_begin); it != range_end; ++it)
{ {
CGAL_assertion(std::size_t(it->second) < new_ids.size()); #if CGAL_MESH_3_VERBOSE > 10
new_ids[it->second] = min_id_around_p; std::cerr << " - #" << it->second << "\n";
#endif // CGAL_MESH_3_VERBOSE
union_find.unify_sets(first_handle,
handles[it->second]);
} }
pit = range_end; pit = range_end;
} }
std::vector<Patch_id> new_ids(this->nb_of_patch_plus_one());
for (std::size_t i = 0; i < this->nb_of_patch_plus_one(); ++i) {
new_ids[i] = *union_find.find(handles[i]);
}
reindex_patches(new_ids); reindex_patches(new_ids);
} }
@ -1119,6 +1132,12 @@ void
Polyhedral_complex_mesh_domain_3<GT_,P_,TA_>:: Polyhedral_complex_mesh_domain_3<GT_,P_,TA_>::
reindex_patches(const std::vector<Surf_p_index>& map) reindex_patches(const std::vector<Surf_p_index>& map)
{ {
#if CGAL_MESH_3_VERBOSE > 10
for(Surf_p_index i = 0, end = Surf_p_index(map.size()); i < end; ++i) {
if(i != map[i])
std::cerr << "patch #" << i << " is reindexed to " << map[i] << "\n";
}
#endif // CGAL_MESH_3_VERBOSE
typedef typename boost::graph_traits<Polyhedron_type>::face_descriptor typedef typename boost::graph_traits<Polyhedron_type>::face_descriptor
Face_descriptor; Face_descriptor;
for(std::size_t i = 0, end = stored_polyhedra.size(); i < end; ++i) { for(std::size_t i = 0, end = stored_polyhedra.size(); i < end; ++i) {
@ -1128,7 +1147,15 @@ reindex_patches(const std::vector<Surf_p_index>& map)
face_pid_pmap = get(face_patch_id_t<Patch_id>(), poly); face_pid_pmap = get(face_patch_id_t<Patch_id>(), poly);
BOOST_FOREACH(Face_descriptor fd, faces(poly)) BOOST_FOREACH(Face_descriptor fd, faces(poly))
{ {
put(face_pid_pmap, fd, map[get(face_pid_pmap, fd)]); const Surf_p_index id = get(face_pid_pmap, fd);
const Surf_p_index new_id = map[id];
put(face_pid_pmap, fd, new_id);
#if CGAL_MESH_3_VERBOSE > 11
if(id != new_id) {
std::cerr << "On polyhedron #" << i << ", patch #" << id
<< " turned into patch #" << new_id << "\n";
}
#endif // CGAL_MESH_3_VERBOSE
} }
} }
BOOST_FOREACH(Surface_patch_index& id, BOOST_FOREACH(Surface_patch_index& id,