add a function to merge vertices globally

This commit is contained in:
Sébastien Loriot 2018-04-13 14:54:29 +02:00
parent 0830c7a112
commit fe407a701f
2 changed files with 126 additions and 31 deletions

View File

@ -35,6 +35,46 @@ namespace CGAL{
namespace Polygon_mesh_processing{
namespace internal {
// warning: vertices will be altered (sorted)
template <class Vpm, class vertex_descriptor>
void detect_identical_vertices(std::vector<vertex_descriptor>& vertices,
std::vector< std::vector<vertex_descriptor> >& identical_vertices,
Vpm vpm)
{
typedef typename boost::property_traits<Vpm>::value_type Point_3;
// sort vertices using their point to ease the detection
// of vertices with identical points
CGAL::Property_map_to_unary_function<Vpm> Get_point(vpm);
std::sort( vertices.begin(), vertices.end(),
boost::bind(std::less<Point_3>(), boost::bind(Get_point,_1),
boost::bind(Get_point, _2)) );
std::size_t nbv=vertices.size();
std::size_t i=1;
while(i!=nbv)
{
if (get(vpm, vertices[i]) == get(vpm, vertices[i-1]))
{
identical_vertices.push_back( std::vector<vertex_descriptor>() );
identical_vertices.back().push_back(vertices[i-1]);
identical_vertices.back().push_back(vertices[i]);
while(++i!=nbv)
{
if (get(vpm, vertices[i]) == get(vpm, vertices[i-1]))
identical_vertices.back().push_back(vertices[i]);
else
break;
}
}
++i;
}
}
} // end of internal
/// \todo document me
/// It should probably go into BGL package
template <typename PolygonMesh, typename OutputIterator>
@ -60,8 +100,8 @@ extract_boundary_cycles(PolygonMesh& pm,
/// \ingroup PMP_repairing_grp
/// \todo document me
template <typename PolygonMesh, class VertexRange>
void merge_vertices(const VertexRange& vertices,
PolygonMesh& pm)
void merge_boundary_vertices(const VertexRange& vertices,
PolygonMesh& pm)
{
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
@ -102,7 +142,7 @@ void merge_duplicated_vertices_in_boundary_cycle(typename boost::graph_traits<Po
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
typedef typename GetVertexPointMap<PolygonMesh, NamedParameter>::const_type Vpm;
typedef typename boost::property_traits<Vpm>::value_type Point_3;
Vpm vpm = choose_param(get_param(np, internal_np::vertex_point),
get_const_property_map(vertex_point, pm));
@ -114,35 +154,11 @@ void merge_duplicated_vertices_in_boundary_cycle(typename boost::graph_traits<Po
h=next(h, pm);
}while(start!=h);
// sort vertices using their point to ease the detection
// of vertices with identical points
CGAL::Property_map_to_unary_function<Vpm> Get_point(vpm);
std::sort( vertices.begin(), vertices.end(),
boost::bind(std::less<Point_3>(), boost::bind(Get_point,_1),
boost::bind(Get_point, _2)) );
std::size_t nbv=vertices.size();
std::size_t i=1;
std::vector< std::vector<vertex_descriptor> > identical_vertices;
while(i!=nbv)
{
if (get(vpm, vertices[i]) == get(vpm, vertices[i-1]))
{
identical_vertices.push_back( std::vector<vertex_descriptor>() );
identical_vertices.back().push_back(vertices[i-1]);
identical_vertices.back().push_back(vertices[i]);
while(++i!=nbv)
{
if (get(vpm, vertices[i]) == get(vpm, vertices[i-1]))
identical_vertices.back().push_back(vertices[i]);
else
break;
}
}
++i;
}
internal::detect_identical_vertices(vertices, identical_vertices, vpm);
BOOST_FOREACH(const std::vector<vertex_descriptor>& vrtcs, identical_vertices)
merge_vertices(vrtcs, pm);
merge_boundary_vertices(vrtcs, pm);
}
/// \ingroup PMP_repairing_grp
@ -160,6 +176,36 @@ void merge_duplicated_vertices_in_boundary_cycles( PolygonMesh& pm,
merge_duplicated_vertices_in_boundary_cycle(h, pm, np);
}
/// \ingroup PMP_repairing_grp
/// \todo document me
template <class PolygonMesh, class NamedParameter>
void merge_duplicated_boundary_vertices( PolygonMesh& pm,
const NamedParameter& np)
{
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
typedef typename GetVertexPointMap<PolygonMesh, NamedParameter>::const_type Vpm;
Vpm vpm = choose_param(get_param(np, internal_np::vertex_point),
get_const_property_map(vertex_point, pm));
std::vector<vertex_descriptor> border_vertices;
BOOST_FOREACH(halfedge_descriptor h, halfedges(pm))
{
if(is_border(h, pm))
border_vertices.push_back(target(h, pm));
}
std::vector< std::vector<vertex_descriptor> > identical_vertices;
internal::detect_identical_vertices(border_vertices, identical_vertices, vpm);
BOOST_FOREACH(const std::vector<vertex_descriptor>& vrtcs, identical_vertices)
merge_boundary_vertices(vrtcs, pm);
}
template <class PolygonMesh>
void merge_duplicated_vertices_in_boundary_cycles(PolygonMesh& pm)
{
@ -174,6 +220,13 @@ void merge_duplicated_vertices_in_boundary_cycle(
merge_duplicated_vertices_in_boundary_cycles(h, pm, parameters::all_default());
}
template <class PolygonMesh>
void merge_duplicated_boundary_vertices(PolygonMesh& pm)
{
merge_duplicated_boundary_vertices(pm, parameters::all_default());
}
} } // end of CGAL::Polygon_mesh_processing
#endif //CGAL_POLYGON_MESH_PROCESSING_MERGE_BORDER_VERTICES_H

View File

@ -22,22 +22,64 @@ void test_merge_duplicated_vertices_in_boundary_cycles(const char* fname,
exit(1);
}
std::cout << "Testing " << fname << "\n";
std::cout << "Testing merging in cycles " << fname << "\n";
std::cout << " input mesh has " << vertices(mesh).size() << " vertices.\n";
CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycles(mesh);
std::cout << " output mesh has " << vertices(mesh).size() << " vertices.\n";
assert(expected_nb_vertices==0 ||
expected_nb_vertices == vertices(mesh).size());
if (expected_nb_vertices==0)
{
std::cout << "writting output to out1.off\n";
std::ofstream output("out1.off");
output << std::setprecision(17);
output << mesh;
}
}
void test_merge_duplicated_boundary_vertices(const char* fname,
std::size_t expected_nb_vertices)
{
std::ifstream input(fname);
Surface_mesh mesh;
if (!input || !(input >> mesh) || mesh.is_empty()) {
std::cerr << fname << " is not a valid off file.\n";
exit(1);
}
std::cout << "Testing merging globally " << fname << "\n";
std::cout << " input mesh has " << vertices(mesh).size() << " vertices.\n";
CGAL::Polygon_mesh_processing::merge_duplicated_boundary_vertices(mesh);
std::cout << " output mesh has " << vertices(mesh).size() << " vertices.\n";
assert(expected_nb_vertices == 0 ||
expected_nb_vertices == vertices(mesh).size());
if (expected_nb_vertices==0)
{
std::cout << "writting output to out2.off\n";
std::ofstream output("out2.off");
output << std::setprecision(17);
output << mesh;
}
}
int main(int argc, char** argv)
{
if (argc==1)
{
test_merge_duplicated_vertices_in_boundary_cycles("data/merge_points.off", 43);
test_merge_duplicated_boundary_vertices("data/merge_points.off", 40);
}
else
{
for (int i=1; i< argc; ++i)
{
test_merge_duplicated_vertices_in_boundary_cycles(argv[i], 0);
test_merge_duplicated_boundary_vertices(argv[i], 0);
}
}
return 0;
}