mirror of https://github.com/CGAL/cgal
add a function to merge vertices globally
This commit is contained in:
parent
0830c7a112
commit
fe407a701f
|
|
@ -35,6 +35,46 @@ namespace CGAL{
|
||||||
|
|
||||||
namespace Polygon_mesh_processing{
|
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
|
/// \todo document me
|
||||||
/// It should probably go into BGL package
|
/// It should probably go into BGL package
|
||||||
template <typename PolygonMesh, typename OutputIterator>
|
template <typename PolygonMesh, typename OutputIterator>
|
||||||
|
|
@ -60,8 +100,8 @@ extract_boundary_cycles(PolygonMesh& pm,
|
||||||
/// \ingroup PMP_repairing_grp
|
/// \ingroup PMP_repairing_grp
|
||||||
/// \todo document me
|
/// \todo document me
|
||||||
template <typename PolygonMesh, class VertexRange>
|
template <typename PolygonMesh, class VertexRange>
|
||||||
void merge_vertices(const VertexRange& vertices,
|
void merge_boundary_vertices(const VertexRange& vertices,
|
||||||
PolygonMesh& pm)
|
PolygonMesh& pm)
|
||||||
{
|
{
|
||||||
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
|
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
|
||||||
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_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>::halfedge_descriptor halfedge_descriptor;
|
||||||
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
|
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
|
||||||
typedef typename GetVertexPointMap<PolygonMesh, NamedParameter>::const_type Vpm;
|
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),
|
Vpm vpm = choose_param(get_param(np, internal_np::vertex_point),
|
||||||
get_const_property_map(vertex_point, pm));
|
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);
|
h=next(h, pm);
|
||||||
}while(start!=h);
|
}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;
|
std::vector< std::vector<vertex_descriptor> > identical_vertices;
|
||||||
while(i!=nbv)
|
internal::detect_identical_vertices(vertices, identical_vertices, vpm);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
BOOST_FOREACH(const std::vector<vertex_descriptor>& vrtcs, identical_vertices)
|
BOOST_FOREACH(const std::vector<vertex_descriptor>& vrtcs, identical_vertices)
|
||||||
merge_vertices(vrtcs, pm);
|
merge_boundary_vertices(vrtcs, pm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \ingroup PMP_repairing_grp
|
/// \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);
|
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>
|
template <class PolygonMesh>
|
||||||
void merge_duplicated_vertices_in_boundary_cycles(PolygonMesh& pm)
|
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());
|
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
|
} } // end of CGAL::Polygon_mesh_processing
|
||||||
|
|
||||||
#endif //CGAL_POLYGON_MESH_PROCESSING_MERGE_BORDER_VERTICES_H
|
#endif //CGAL_POLYGON_MESH_PROCESSING_MERGE_BORDER_VERTICES_H
|
||||||
|
|
|
||||||
|
|
@ -22,22 +22,64 @@ void test_merge_duplicated_vertices_in_boundary_cycles(const char* fname,
|
||||||
exit(1);
|
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";
|
std::cout << " input mesh has " << vertices(mesh).size() << " vertices.\n";
|
||||||
CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycles(mesh);
|
CGAL::Polygon_mesh_processing::merge_duplicated_vertices_in_boundary_cycles(mesh);
|
||||||
std::cout << " output mesh has " << vertices(mesh).size() << " vertices.\n";
|
std::cout << " output mesh has " << vertices(mesh).size() << " vertices.\n";
|
||||||
|
|
||||||
assert(expected_nb_vertices==0 ||
|
assert(expected_nb_vertices==0 ||
|
||||||
expected_nb_vertices == vertices(mesh).size());
|
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)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
if (argc==1)
|
if (argc==1)
|
||||||
|
{
|
||||||
test_merge_duplicated_vertices_in_boundary_cycles("data/merge_points.off", 43);
|
test_merge_duplicated_vertices_in_boundary_cycles("data/merge_points.off", 43);
|
||||||
|
test_merge_duplicated_boundary_vertices("data/merge_points.off", 40);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
for (int i=1; i< argc; ++i)
|
for (int i=1; i< argc; ++i)
|
||||||
|
{
|
||||||
test_merge_duplicated_vertices_in_boundary_cycles(argv[i], 0);
|
test_merge_duplicated_vertices_in_boundary_cycles(argv[i], 0);
|
||||||
|
test_merge_duplicated_boundary_vertices(argv[i], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue