use BGL named parameters

This commit is contained in:
Andreas Fabri 2015-02-17 20:13:48 +01:00
parent 5fd11a8f59
commit fef3ec4692
15 changed files with 251 additions and 61 deletions

View File

@ -121,6 +121,14 @@ namespace CGAL {
typedef cgal_bgl_named_params<IndexMap, boost::halfedge_index_t, self> Params;
return Params(p, *this);
}
template <typename IndexMap>
cgal_bgl_named_params<IndexMap, boost::face_index_t, self>
face_index_map(const IndexMap& p) const
{
typedef cgal_bgl_named_params<IndexMap, boost::face_index_t, self> Params;
return Params(p, *this);
}
template <typename Visitor>
cgal_bgl_named_params<Visitor, boost::graph_visitor_t, self>
@ -321,6 +329,9 @@ namespace CGAL {
}
#endif
namespace parameters {
template <typename IndexMap>
cgal_bgl_named_params<IndexMap, boost::vertex_index_t>
vertex_index_map(IndexMap const& p)
@ -337,6 +348,14 @@ namespace CGAL {
return Params(p);
}
template <typename IndexMap>
cgal_bgl_named_params<IndexMap, boost::face_index_t>
face_index_map(IndexMap const& p)
{
typedef cgal_bgl_named_params<IndexMap, boost::face_index_t> Params;
return Params(p);
}
template <typename PointMap>
cgal_bgl_named_params<PointMap, vertex_point_t>
vertex_point_map(PointMap const& p)
@ -424,6 +443,9 @@ namespace CGAL {
typedef cgal_bgl_named_params<EdgeIsConstrainedParams, edge_is_constrained_params_t> Params;
return Params(em);
}
} // namespace parameters
} //namespace CGAL
#if BOOST_VERSION >= 105100

View File

@ -68,6 +68,7 @@ create_single_source_cgal_program( "fill_polyhedron_example.cpp" )
create_single_source_cgal_program( "refine_polyhedron_example.cpp" )
create_single_source_cgal_program( "triangulate_polyline_example.cpp" )
create_single_source_cgal_program( "connected_component.cpp" )
create_single_source_cgal_program( "cc_polyhedron.cpp" )
else(EIGEN3_FOUND)

View File

@ -0,0 +1,79 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Polyhedron_items_with_id_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
#include <CGAL/Polygon_mesh_processing/Connected_components.h>
#include <iostream>
#include <fstream>
namespace PMP = CGAL::Polygon_mesh_processing;
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point;
typedef CGAL::Polyhedron_3<Kernel,CGAL::Polyhedron_items_with_id_3> Mesh;
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
typedef boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<Mesh>::edge_descriptor edge_descriptor;
template <typename G>
struct Constraint {
Constraint() { }
Constraint(G & g) : g(&g) { }
bool operator[](const edge_descriptor&) const {
return false; // no constraint
}
G* g;
};
int main(int, char* argv[])
{
Mesh sm;
std::ifstream in(argv[1]);
in >> sm;
int i=0;
BOOST_FOREACH(face_descriptor f, faces(sm)){
f->id() = i++;
}
i=0;
BOOST_FOREACH(vertex_descriptor v, vertices(sm)){
v->id() = i++;
}
std::vector<face_descriptor> cc;
face_descriptor fd = *faces(sm).first;
CGAL::Polygon_mesh_processing::connected_component(fd,
sm,
std::back_inserter(cc));
std::cerr << cc.size() << " faces in the CC of " << &*fd << std::endl;
boost::vector_property_map<int, typename boost::property_map<Mesh, boost::face_index_t>::type> fccmap(get(boost::face_index,sm));
int num = PMP::connected_components(sm,
fccmap// ,
// CGAL::parameters::edge_is_constrained_map(Constraint<Mesh>())
// .face_index_map(get(CGAL::face_index, sm))
);
std::cerr << "The graph has " << num << " connected components (face connectivity)" << std::endl;
BOOST_FOREACH(face_descriptor f , faces(sm)){
std::cout << &*f << " in connected component " << fccmap[f] << std::endl;
}
CGAL::Polygon_mesh_processing::keep_largest_connected_components(sm,2);
std::cout << "mesh:\n" << sm << std::endl;
return 0;
}

View File

@ -5,6 +5,8 @@
#include <fstream>
namespace PMP = CGAL::Polygon_mesh_processing;
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point;
typedef CGAL::Surface_mesh<Point> Mesh;
@ -40,7 +42,6 @@ int main(int, char* argv[])
face_descriptor fd = *faces(sm).first;
CGAL::Polygon_mesh_processing::connected_component(fd,
sm,
Constraint<Mesh>(sm),
std::back_inserter(cc));
@ -48,9 +49,11 @@ int main(int, char* argv[])
Mesh::Property_map<face_descriptor,int> fccmap;
fccmap = sm.add_property_map<face_descriptor,int>("f:CC").first;
int num = CGAL::Polygon_mesh_processing::connected_components(sm,
//Constraint<Mesh>(sm),
fccmap);
int num = PMP::connected_components(sm,
fccmap,
CGAL::parameters::edge_is_constrained_map(Constraint<Mesh>())
.face_index_map(get(CGAL::face_index, sm))
);
std::cerr << "The graph has " << num << " connected components (face connectivity)" << std::endl;
BOOST_FOREACH(face_descriptor f , faces(sm)){

View File

@ -28,6 +28,7 @@
#include <boost/graph/filtered_graph.hpp>
#include <boost/graph/connected_components.hpp>
#include <boost/property_map/vector_property_map.hpp>
#include <CGAL/boost/graph/named_function_params.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/boost/graph/helpers.h>
@ -468,66 +469,96 @@ connected_component(typename boost::graph_traits<PolygonMesh>::face_descriptor s
* Two faces are considered to be in the same connected component if they share an edge that is not constrained.
* \tparam PolygonMesh a model of `FaceGraph`
* \tparam EdgeConstraintMap a property map with the edge descriptor as key type and `bool` as value type.
* \tparam FaceComponentIndexMap the property map with the face index as value type, and the index of its connected component
* \tparam FaceComponentMap the property map with the face index as value type, and the index of its connected component
* \returns the number of connected components.
*/
template <class PolygonMesh, class EdgeConstraintMap, class FaceComponentIndexMap>
template <class PolygonMesh, class EdgeConstraintMap, class FaceComponentMap, class FaceIndexMap>
typename boost::graph_traits<PolygonMesh>::faces_size_type
connected_components(PolygonMesh& pmesh,
FaceComponentMap& fcm,
EdgeConstraintMap ecmap,
FaceComponentIndexMap& fim)
FaceIndexMap fim)
{
typedef Dual<PolygonMesh> Dual;
typedef boost::filtered_graph<Dual, internal::No_border<PolygonMesh,EdgeConstraintMap> > FiniteDual;
Dual dual(pmesh);
FiniteDual finite_dual(dual,internal::No_border<PolygonMesh,EdgeConstraintMap>(pmesh,ecmap));
return boost::connected_components(finite_dual, fim);
return boost::connected_components(finite_dual, fcm);
}
template <class PolygonMesh, class FaceComponentMap, class P, class T, class R>
typename boost::graph_traits<PolygonMesh>::faces_size_type
connected_components(PolygonMesh& pmesh,
FaceComponentMap& fcm,
const cgal_bgl_named_params<P,T,R>& params)
{
using boost::choose_param;
using boost::choose_const_pmap;
using boost::get_param;
return connected_components(pmesh,
fcm,
choose_param(get_param(params,edge_is_constrained),internal::No_constraint<PolygonMesh>(pmesh)),
choose_const_pmap(get_param(params,boost::face_index),pmesh,boost::face_index)
);
}
/*!
* \ingroup PkgPolygonMeshProcessing
* computes for each face the index of the connected components to which it belongs.
* Two faces are considered to be in the same connected component if they share an edge.
* \tparam PolygonMesh a model of `FaceGraph`
* \tparam FaceComponentIndexMap the property map with the face index as value type, and the index of its connected component
* \tparam FaceComponentMap the property map with the face index as value type, and the index of its connected component
* \returns the number of connected components.
*/
template <class PolygonMesh, class FaceComponentIndexMap>
template <class PolygonMesh, class FaceComponentMap>
typename boost::graph_traits<PolygonMesh>::faces_size_type
connected_components(PolygonMesh& pmesh,
FaceComponentIndexMap& fim)
FaceComponentMap& fcm)
{
typedef Dual<PolygonMesh> Dual;
typedef boost::filtered_graph<Dual, internal::No_border<PolygonMesh> > FiniteDual;
Dual dual(pmesh);
FiniteDual finite_dual(dual,internal::No_border<PolygonMesh>(pmesh));
return boost::connected_components(finite_dual, fim);
return connected_components(pmesh,
fcm,
internal::No_constraint<PolygonMesh>(pmesh),
get(boost::face_index,pmesh));
}
/*!
* \ingroup PkgPolygonMeshProcessing
* Erases the small connected components and the isolated vertices.
* Keep `nb_components_to_keep` largest connected components.
* \return the number of connected components erased (ignoring isolated vertices).
* \todo BGLize me
*/
template <class PolygonMesh>
std::size_t keep_largest_connected_components(PolygonMesh& pmesh, std::size_t nb_components_to_keep)
template <class PolygonMesh, class EdgeConstraintMap, class VertexIndexMap, class FaceIndexMap>
std::size_t keep_largest_connected_components(PolygonMesh& pmesh,
std::size_t nb_components_to_keep,
EdgeConstraintMap ecmap,
VertexIndexMap vim,
FaceIndexMap fim)
{
typedef typename boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::vertex_iterator vertex_iterator;
typedef typename boost::graph_traits<PolygonMesh>::face_descriptor face_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::face_iterator face_iterator;
typedef typename boost::graph_traits<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::edge_descriptor edge_descriptor;
boost::vector_property_map<int, typename boost::property_map<PolygonMesh, boost::face_index_t>::type> face_cc(get(boost::face_index,pmesh));
typedef typename boost::graph_traits<PolygonMesh>::edge_iterator edge_iterator;
boost::vector_property_map<int, typename boost::property_map<PolygonMesh, boost::face_index_t>::type> face_cc(fim);
int num = connected_components(pmesh,face_cc);
int num = connected_components(pmesh,
face_cc,
ecmap,
fim);
if((num == 1)|| (nb_components_to_keep > num) ){
return 0;
}
boost::vector_property_map<bool, typename boost::property_map<PolygonMesh, boost::vertex_index_t>::type> keep_vertex(get(boost::vertex_index,pmesh));
boost::vector_property_map<bool, typename boost::property_map<PolygonMesh, boost::vertex_index_t>::type> keep_vertex(vim);
BOOST_FOREACH(vertex_descriptor v, vertices(pmesh)){
keep_vertex[v] = false;
}
@ -540,9 +571,13 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh, std::size_t nb
BOOST_FOREACH(face_descriptor f, faces(pmesh)){
component_size[face_cc[f]].second++;
}
#ifdef CGAL_CC_DEBUG
for(int i=0; i < component_size.size(); ++i){
std::cerr << "component " << i << " has " << component_size[i].second << " faces\n";
}
#endif
// we have to sort the range [0, num) by component size
internal::MoreSecond ls;
std::sort(component_size.begin(), component_size.end(), ls);
@ -551,14 +586,20 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh, std::size_t nb
}
internal::LessFirst lsinv;
std::sort(component_size.begin(), component_size.end(), lsinv);
#ifdef CGAL_CC_DEBUG
for(std::size_t i=0; i < num; i++){
std::cout << i << " " << component_size[i].first << " " << component_size[i].second << std::endl;
}
#endif
BOOST_FOREACH(face_descriptor f, faces(pmesh)){
face_cc[f] = component_size[face_cc[f]].second;
#ifdef CGAL_CC_DEBUG
if(face_cc[f] == 1){
std::cerr << "keep " << f << std::endl;
}
#endif
}
// Now face_cc[f] == 1 means that we want to keep the face
@ -567,11 +608,17 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh, std::size_t nb
BOOST_FOREACH(halfedge_descriptor h, halfedges_around_face(halfedge(f,pmesh),pmesh)){
vertex_descriptor v = target(h,pmesh);
keep_vertex[v] = true;
#ifdef CGAL_CC_DEBUG
std::cout << "keep vertex "<< v << std::endl;
#endif
}
}
}
BOOST_FOREACH(edge_descriptor e, edges(pmesh)){
edge_iterator eb, ee;
for(boost::tie(eb,ee)= edges(pmesh);eb!= ee;){
edge_descriptor e = *eb;
++eb;
vertex_descriptor v = source(e,pmesh);
vertex_descriptor w = target(e,pmesh);
halfedge_descriptor h = halfedge(e,pmesh);
@ -580,10 +627,13 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh, std::size_t nb
// don't care about connectivity
// As vertices are not kept the faces and vertices will be removed later
remove_edge(e,pmesh);
std::cerr << "after remove_edge"<< std::endl;
} else if( keep_vertex[v] && keep_vertex[w]){
face_descriptor fh = face(h,pmesh), ofh = face(oh,pmesh);
if(is_border(h,pmesh) && is_border(oh,pmesh)){
#ifdef CGAL_CC_DEBUG
std::cerr << "null_face on both sides of " << e << " is kept\n";
#endif
} else if( (face_cc[fh] && is_border(oh,pmesh)) ||
(face_cc[ofh] && is_border(h,pmesh)) ||
(face_cc[fh] && face_cc[ofh]) ){
@ -622,21 +672,56 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh, std::size_t nb
remove_edge(e,pmesh);
}
}
face_iterator fb, fe;
// We now can remove all vertices and faces not marked as kept
BOOST_FOREACH(face_descriptor f, faces(pmesh)){
for(boost::tie(fb,fe)=faces(pmesh); fb!=fe;){
face_descriptor f = *fb;
++fb;
if(face_cc[f] != 1){
remove_face(f,pmesh);
}
}
BOOST_FOREACH(vertex_descriptor v, vertices(pmesh)){
vertex_iterator b,e;
for(boost::tie(b,e)=vertices(pmesh); b!=e;){
vertex_descriptor v = *b;
++b;
if(! keep_vertex[v]){
remove_vertex(v,pmesh);
}
}
return num - nb_components_to_keep;
}
template <class PolygonMesh, class P, class T, class R>
std::size_t keep_largest_connected_components(PolygonMesh& pmesh,
std::size_t nb_components_to_keep,
const cgal_bgl_named_params<P,T,R>& params)
{
using boost::choose_param;
using boost::choose_const_pmap;
using boost::get_param;
return keep_largest_connected_component(pmesh,
nb_components_to_keep,
choose_param(get_param(params,edge_is_constrained),internal::No_constraint<PolygonMesh>(pmesh)),
choose_const_pmap(get_param(params,boost::vertex_index),pmesh,boost::vertex_index)
choose_const_pmap(get_param(params,boost::face_index),pmesh,boost::face_index)
);
}
template <class PolygonMesh>
std::size_t keep_largest_connected_components(PolygonMesh& pmesh,
std::size_t nb_components_to_keep)
{
return keep_largest_connected_components(pmesh,
nb_components_to_keep,
internal::No_constraint<PolygonMesh>(pmesh),
get(boost::vertex_index, pmesh),
get(boost::face_index, pmesh));
}
} // namespace Polygon_mesh_processing

View File

@ -68,8 +68,8 @@ void Polyhedron_demo_mesh_simplification_plugin::on_actionSimplify_triggered()
namespace SMS = CGAL::Surface_mesh_simplification;
SMS::Count_stop_predicate< Polyhedron > stop(nb_edges); // target #edges
SMS::edge_collapse( *pMesh, stop,
CGAL::vertex_index_map(get(CGAL::vertex_external_index,*pMesh))
.halfedge_index_map(get(CGAL::halfedge_external_index,*pMesh)));
CGAL::parameters::vertex_index_map(get(CGAL::vertex_external_index,*pMesh))
.halfedge_index_map(get(CGAL::halfedge_external_index,*pMesh)));
std::cout << "ok (" << time.elapsed() << " ms, "
<< pMesh->size_of_halfedges() / 2 << " edges)" << std::endl;

View File

@ -80,9 +80,9 @@ int main( int argc, char** argv )
int r = SMS::edge_collapse
(surface_mesh
,stop
,CGAL::halfedge_index_map (get(CGAL::halfedge_index ,surface_mesh))
.vertex_point_map(get(boost::vertex_point, surface_mesh))
.edge_is_constrained_map(constraints_map)
,CGAL::parameters::halfedge_index_map (get(CGAL::halfedge_index ,surface_mesh))
.vertex_point_map(get(boost::vertex_point, surface_mesh))
.edge_is_constrained_map(constraints_map)
);
surface_mesh.garbage_collection();

View File

@ -130,10 +130,10 @@ int main( int argc, char** argv )
int r
= SMS::edge_collapse(surface_mesh
,stop
,CGAL::vertex_index_map(get(CGAL::vertex_external_index, surface_mesh))
.halfedge_index_map(get(CGAL::halfedge_external_index, surface_mesh))
.edge_is_constrained_map(constraints_map)
.get_placement(placement)
,CGAL::parameters::vertex_index_map(get(CGAL::vertex_external_index, surface_mesh))
.halfedge_index_map(get(CGAL::halfedge_external_index, surface_mesh))
.edge_is_constrained_map(constraints_map)
.get_placement(placement)
);
std::cout << "\nFinished...\n" << r << " edges removed.\n"
@ -170,10 +170,10 @@ int main( int argc, char** argv )
std::cout << "Check that no removable edge has been forgotten..." << std::endl;
r = SMS::edge_collapse(surface_mesh
,stop
,CGAL::vertex_index_map(get(CGAL::vertex_external_index, surface_mesh))
.halfedge_index_map (get(CGAL::halfedge_external_index, surface_mesh))
.edge_is_constrained_map(constraints_map)
.get_placement(placement)
,CGAL::parameters::vertex_index_map(get(CGAL::vertex_external_index, surface_mesh))
.halfedge_index_map (get(CGAL::halfedge_external_index, surface_mesh))
.edge_is_constrained_map(constraints_map)
.get_placement(placement)
);
assert(r==0);

View File

@ -96,10 +96,10 @@ int main( int argc, char** argv )
int r = SMS::edge_collapse
(surface_mesh
,stop
,CGAL::vertex_index_map(get(CGAL::vertex_external_index,surface_mesh))
.halfedge_index_map (get(CGAL::halfedge_external_index ,surface_mesh))
.edge_is_constrained_map(bem)
.get_placement(Placement(bem))
,CGAL::parameters::vertex_index_map(get(CGAL::vertex_external_index,surface_mesh))
.halfedge_index_map (get(CGAL::halfedge_external_index ,surface_mesh))
.edge_is_constrained_map(bem)
.get_placement(Placement(bem))
);
std::cout << "\nFinished...\n" << r << " edges removed.\n"

View File

@ -94,8 +94,8 @@ int main( int argc, char** argv )
int r = SMS::edge_collapse
(surface_mesh
,stop
,CGAL::edge_is_constrained_map(bem)
.get_placement(Placement(bem))
,CGAL::parameters::edge_is_constrained_map(bem)
.get_placement(Placement(bem))
);
std::cout << "\nFinished...\n" << r << " edges removed.\n"

View File

@ -162,9 +162,9 @@ int main( int argc, char** argv )
int r = SMS::edge_collapse
(surface_mesh
,stop
,CGAL::get_cost (SMS::Edge_length_cost <Surface_mesh>())
.get_placement(SMS::Midpoint_placement<Surface_mesh>())
.visitor (vis)
,CGAL::parameters::get_cost (SMS::Edge_length_cost <Surface_mesh>())
.get_placement(SMS::Midpoint_placement<Surface_mesh>())
.visitor (vis)
);
std::cout << "\nEdges collected: " << stats.collected

View File

@ -38,10 +38,10 @@ int main( int argc, char** argv )
int r = SMS::edge_collapse
(surface_mesh
,stop
,CGAL::vertex_index_map(get(CGAL::vertex_external_index,surface_mesh))
.halfedge_index_map (get(CGAL::halfedge_external_index ,surface_mesh))
.get_cost (SMS::Edge_length_cost <Surface_mesh>())
.get_placement(SMS::Midpoint_placement<Surface_mesh>())
,CGAL::parameters::vertex_index_map(get(CGAL::vertex_external_index,surface_mesh))
.halfedge_index_map (get(CGAL::halfedge_external_index ,surface_mesh))
.get_cost (SMS::Edge_length_cost <Surface_mesh>())
.get_placement(SMS::Midpoint_placement<Surface_mesh>())
);
std::cout << "\nFinished...\n" << r << " edges removed.\n"

View File

@ -136,9 +136,9 @@ int main( int argc, char** argv )
int r = SMS::edge_collapse
(surface_mesh
,stop
,CGAL::get_cost (SMS::Edge_length_cost <Surface_mesh>())
.get_placement(SMS::Midpoint_placement<Surface_mesh>())
.visitor (vis)
,CGAL::parameters::get_cost (SMS::Edge_length_cost <Surface_mesh>())
.get_placement(SMS::Midpoint_placement<Surface_mesh>())
.visitor (vis)
);
std::cout << "\nEdges collected: " << stats.collected

View File

@ -44,8 +44,8 @@ int main( int argc, char** argv )
int r = SMS::edge_collapse
(surface
,stop
,CGAL::vertex_index_map(get(CGAL::vertex_external_index,surface))
.halfedge_index_map (get(CGAL::halfedge_external_index ,surface))
,CGAL::parameters::vertex_index_map(get(CGAL::vertex_external_index,surface))
.halfedge_index_map (get(CGAL::halfedge_external_index ,surface))
);
std::cout << "\nFinished...\n" << r << " edges removed.\n"

View File

@ -392,14 +392,14 @@ bool Test ( string aName )
SMS::Edge_length_cost <Surface> cost ;
SMS::Midpoint_placement<Surface> placement ;
edge_collapse(lSurface,stop,get_cost(cost).get_placement(placement).visitor(vis) );
edge_collapse(lSurface,stop,CGAL::parameters::get_cost(cost).get_placement(placement).visitor(vis) );
}
else
{
SMS::LindstromTurk_cost <Surface> cost ;
SMS::LindstromTurk_placement<Surface> placement ;
edge_collapse(lSurface,stop,get_cost(cost).get_placement(placement).visitor(vis) );
edge_collapse(lSurface,stop,CGAL::parameters::get_cost(cost).get_placement(placement).visitor(vis) );
}
t.stop();