mirror of https://github.com/CGAL/cgal
Merge pull request #1861 from maxGimeno/BGL_copy_face_graph_patch-GF
BGL: Connected_component_graph and copy_face_graph_patch
This commit is contained in:
commit
4116d749d2
|
|
@ -8,12 +8,28 @@ INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Euler_operations.h \
|
|||
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/split_graph_into_polylines.h \
|
||||
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/copy_face_graph.h \
|
||||
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Graph_with_descriptor_with_graph.h \
|
||||
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Face_filtered_graph.h \
|
||||
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Dual.h \
|
||||
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/convert_nef_polyhedron_to_polygon_mesh.h
|
||||
EXAMPLE_PATH = ${CGAL_Surface_mesh_skeletonization_EXAMPLE_DIR} \
|
||||
${CGAL_Surface_mesh_segmentation_EXAMPLE_DIR} \
|
||||
${CGAL_Polygon_mesh_processing_EXAMPLE_DIR} \
|
||||
${CGAL_BGL_EXAMPLE_DIR}
|
||||
|
||||
ALIASES += "bgllink{1}=<a href=\"http://www.boost.org/libs/graph/doc/\1.html\"><code>\1</code></a>"
|
||||
ALIASES += "cgalNamedParamsBegin=<dl class=\"params\"><dt>Named Parameters</dt><dd> <table class=\"params\">"
|
||||
# macros to be used inside the code
|
||||
ALIASES += "cgalNamedParamsBegin=<dl class=\"params\"><dt>Named Parameters</dt><dd> <table class=\"params\">"
|
||||
ALIASES += "cgalNamedParamsEnd=</table> </dd> </dl>"
|
||||
ALIASES += "cgalParamBegin{1}=<tr><td class=\"paramname\">\1</td><td>"
|
||||
ALIASES += "cgalParamEnd=</td></tr>"
|
||||
|
||||
|
||||
EXTRACT_ALL=NO
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
EXPAND_AS_DEFINED = CGAL_BGL_NP_TEMPLATE_PARAMETERS \
|
||||
CGAL_BGL_NP_CLASS
|
||||
|
|
|
|||
|
|
@ -316,6 +316,7 @@ user might encounter.
|
|||
- `CGAL::Dual`
|
||||
- `CGAL::Graph_with_descriptor_with_graph`
|
||||
- `CGAL::Graph_with_descriptor_with_graph_property_map`
|
||||
- `CGAL::Face_filtered_graph`
|
||||
|
||||
## Helper Functions ##
|
||||
- `CGAL::is_border()`
|
||||
|
|
@ -342,7 +343,6 @@ user might encounter.
|
|||
|
||||
- `CGAL::clear()`
|
||||
- `CGAL::copy_face_graph()`
|
||||
- `CGAL::reserve()`
|
||||
|
||||
## Iterators ##
|
||||
- `CGAL::Halfedge_around_source_iterator`
|
||||
|
|
|
|||
|
|
@ -17,4 +17,6 @@
|
|||
\example BGL_surface_mesh/prim.cpp
|
||||
\example BGL_surface_mesh/surface_mesh_dual.cpp
|
||||
\example Surface_mesh_skeletonization/simple_mcfskel_example.cpp
|
||||
\example Surface_mesh_segmentation/extract_segmentation_into_mesh_example.cpp
|
||||
\example Polygon_mesh_processing/face_filtered_graph_example.cpp
|
||||
*/
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -23,6 +23,7 @@
|
|||
#include <CGAL/assertions.h>
|
||||
#include <CGAL/boost/graph/properties.h>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <CGAL/boost/graph/iterator.h>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
||||
|
||||
|
|
@ -325,8 +326,7 @@ edge(typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::ver
|
|||
|
||||
|
||||
template <class Graph>
|
||||
std::pair<typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::vertex_iterator,
|
||||
typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::vertex_iterator>
|
||||
CGAL::Iterator_range<typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::vertex_iterator>
|
||||
vertices(const Graph_with_descriptor_with_graph<Graph> & w)
|
||||
{
|
||||
typename boost::graph_traits<Graph>::vertex_iterator b,e;
|
||||
|
|
@ -336,8 +336,7 @@ vertices(const Graph_with_descriptor_with_graph<Graph> & w)
|
|||
}
|
||||
|
||||
template <class Graph>
|
||||
std::pair<typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::edge_iterator,
|
||||
typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::edge_iterator>
|
||||
CGAL::Iterator_range<typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::edge_iterator>
|
||||
edges(const Graph_with_descriptor_with_graph<Graph> & w)
|
||||
{
|
||||
typename boost::graph_traits<Graph>::edge_iterator b,e;
|
||||
|
|
@ -347,8 +346,7 @@ edges(const Graph_with_descriptor_with_graph<Graph> & w)
|
|||
}
|
||||
|
||||
template <class Graph>
|
||||
std::pair<typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::out_edge_iterator,
|
||||
typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::out_edge_iterator>
|
||||
CGAL::Iterator_range<typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::out_edge_iterator>
|
||||
out_edges(typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::vertex_descriptor v,
|
||||
const Graph_with_descriptor_with_graph<Graph> & w)
|
||||
{
|
||||
|
|
@ -360,8 +358,7 @@ out_edges(typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >
|
|||
}
|
||||
|
||||
template <class Graph>
|
||||
std::pair<typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::in_edge_iterator,
|
||||
typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::in_edge_iterator>
|
||||
CGAL::Iterator_range<typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::in_edge_iterator>
|
||||
in_edges(typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::vertex_descriptor v,
|
||||
const Graph_with_descriptor_with_graph<Graph> & w)
|
||||
{
|
||||
|
|
@ -630,8 +627,7 @@ prev(typename boost::graph_traits< Graph_with_descriptor_with_graph<Graph> >::ha
|
|||
//
|
||||
|
||||
template <class Graph>
|
||||
std::pair<typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::halfedge_iterator,
|
||||
typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::halfedge_iterator>
|
||||
CGAL::Iterator_range<typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::halfedge_iterator>
|
||||
halfedges(const Graph_with_descriptor_with_graph<Graph> & w)
|
||||
{
|
||||
typename boost::graph_traits<Graph>::halfedge_iterator b,e;
|
||||
|
|
@ -671,8 +667,7 @@ halfedge(typename boost::graph_traits< Graph_with_descriptor_with_graph<Graph> >
|
|||
|
||||
|
||||
template <class Graph>
|
||||
std::pair<typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::face_iterator,
|
||||
typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::face_iterator>
|
||||
CGAL::Iterator_range<typename boost::graph_traits<Graph_with_descriptor_with_graph<Graph> >::face_iterator>
|
||||
faces(const Graph_with_descriptor_with_graph<Graph> & w)
|
||||
{
|
||||
typename boost::graph_traits<Graph>::face_iterator b,e;
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ namespace boost{
|
|||
} //end of namespace boost
|
||||
#endif
|
||||
|
||||
#define CGAL_BGL_NP_TEMPLATE_PARAMETERS T, typename Tag, typename Base
|
||||
#define CGAL_BGL_NP_CLASS CGAL::cgal_bgl_named_params<T,Tag,Base>
|
||||
|
||||
namespace CGAL {
|
||||
namespace internal_np{
|
||||
|
|
@ -162,6 +164,68 @@ using boost::visitor;
|
|||
|
||||
} // namespace parameters
|
||||
|
||||
//helper classes
|
||||
template<typename PolygonMesh, typename PropertyTag>
|
||||
class property_map_selector
|
||||
{
|
||||
public:
|
||||
typedef typename boost::graph_has_property<PolygonMesh, PropertyTag>::type Has_internal_pmap;
|
||||
typedef typename boost::mpl::if_c< Has_internal_pmap::value
|
||||
, typename boost::property_map<PolygonMesh, PropertyTag>::type
|
||||
, typename boost::cgal_no_property::type
|
||||
>::type type;
|
||||
typedef typename boost::mpl::if_c< Has_internal_pmap::value
|
||||
, typename boost::property_map<PolygonMesh, PropertyTag>::const_type
|
||||
, typename boost::cgal_no_property::const_type
|
||||
>::type const_type;
|
||||
|
||||
type get_pmap(const PropertyTag& p, PolygonMesh& pmesh)
|
||||
{
|
||||
return get_impl(p, pmesh, Has_internal_pmap());
|
||||
}
|
||||
|
||||
const_type get_const_pmap(const PropertyTag& p, const PolygonMesh& pmesh)
|
||||
{
|
||||
return get_const_pmap_impl(p, pmesh, Has_internal_pmap());
|
||||
}
|
||||
|
||||
private:
|
||||
type get_impl(const PropertyTag&, PolygonMesh&, CGAL::Tag_false)
|
||||
{
|
||||
return type(); //boost::cgal_no_property::type
|
||||
}
|
||||
type get_impl(const PropertyTag& p, PolygonMesh& pmesh, CGAL::Tag_true)
|
||||
{
|
||||
return get(p, pmesh);
|
||||
}
|
||||
|
||||
const_type get_const_pmap_impl(const PropertyTag&
|
||||
, const PolygonMesh&, CGAL::Tag_false)
|
||||
{
|
||||
return const_type(); //boost::cgal_no_property::type
|
||||
}
|
||||
const_type get_const_pmap_impl(const PropertyTag& p
|
||||
, const PolygonMesh& pmesh, CGAL::Tag_true)
|
||||
{
|
||||
return get(p, pmesh);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PolygonMesh, typename PropertyTag>
|
||||
typename property_map_selector<PolygonMesh, PropertyTag>::type
|
||||
get_property_map(const PropertyTag& p, PolygonMesh& pmesh)
|
||||
{
|
||||
property_map_selector<PolygonMesh, PropertyTag> pms;
|
||||
return pms.get_pmap(p, pmesh);
|
||||
}
|
||||
|
||||
template<typename PolygonMesh, typename PropertyTag>
|
||||
typename property_map_selector<PolygonMesh, PropertyTag>::const_type
|
||||
get_const_property_map(const PropertyTag& p, const PolygonMesh& pmesh)
|
||||
{
|
||||
property_map_selector<PolygonMesh, PropertyTag> pms;
|
||||
return pms.get_const_pmap(p, pmesh);
|
||||
}
|
||||
} //namespace CGAL
|
||||
|
||||
// partial specializations hate inheritance and we need to repeat
|
||||
|
|
|
|||
|
|
@ -88,8 +88,14 @@ create_single_source_cgal_program( "test_Has_member_id.cpp" )
|
|||
create_single_source_cgal_program( "test_cgal_bgl_named_params.cpp" )
|
||||
|
||||
|
||||
create_single_source_cgal_program( "graph_concept_Face_filtered_graph.cpp" )
|
||||
|
||||
|
||||
create_single_source_cgal_program( "test_Face_filtered_graph.cpp" )
|
||||
if(OpenMesh_FOUND)
|
||||
target_link_libraries( test_Face_filtered_graph ${OPENMESH_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(OpenMesh_FOUND)
|
||||
target_link_libraries( test_clear ${OPENMESH_LIBRARIES})
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/boost/graph/Face_filtered_graph.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <CGAL/boost/graph/graph_concepts.h>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> K;
|
||||
typedef CGAL::Surface_mesh<K::Point_3> SM;
|
||||
typedef CGAL::Face_filtered_graph<SM, SM::Property_map<boost::graph_traits<SM>::face_descriptor , std::size_t> > Adapter;
|
||||
typedef boost::graph_traits< Adapter > Traits;
|
||||
typedef Traits::edge_descriptor edge_descriptor;
|
||||
typedef Traits::halfedge_descriptor halfedge_descriptor;
|
||||
typedef Traits::vertex_descriptor vertex_descriptor;
|
||||
typedef Traits::face_descriptor face_descriptor;
|
||||
|
||||
void concept_check_adapter()
|
||||
{
|
||||
boost::function_requires< boost::GraphConcept<Adapter> >();
|
||||
boost::function_requires< boost::VertexListGraphConcept<Adapter> >();
|
||||
boost::function_requires< boost::EdgeListGraphConcept<Adapter> >();
|
||||
boost::function_requires< boost::IncidenceGraphConcept<Adapter> >();
|
||||
boost::function_requires< boost::AdjacencyMatrixConcept<Adapter> >();
|
||||
boost::function_requires< boost::BidirectionalGraphConcept<Adapter> >();
|
||||
boost::function_requires< CGAL::HalfedgeGraphConcept<Adapter> >();
|
||||
boost::function_requires< CGAL::HalfedgeListGraphConcept<Adapter> >();
|
||||
boost::function_requires< CGAL::FaceGraphConcept<Adapter> >();
|
||||
boost::function_requires< CGAL::FaceListGraphConcept<Adapter> >();
|
||||
|
||||
boost::function_requires< boost::concepts::ReadablePropertyGraph<
|
||||
Adapter, halfedge_descriptor, CGAL::halfedge_index_t> >();
|
||||
boost::function_requires< boost::concepts::ReadablePropertyGraph<
|
||||
Adapter, edge_descriptor, boost::edge_index_t> >();
|
||||
boost::function_requires< boost::concepts::ReadablePropertyGraph<
|
||||
Adapter, edge_descriptor, boost::edge_weight_t> >();
|
||||
boost::function_requires< boost::concepts::PropertyGraph<
|
||||
Adapter, vertex_descriptor, CGAL::vertex_point_t> >();
|
||||
boost::function_requires< boost::concepts::ReadablePropertyGraph<
|
||||
Adapter, vertex_descriptor, boost::vertex_index_t> >();
|
||||
boost::function_requires< boost::concepts::ReadablePropertyGraph<
|
||||
Adapter, face_descriptor, CGAL::face_index_t> >();
|
||||
|
||||
// null
|
||||
boost::graph_traits<Adapter>::null_vertex();
|
||||
boost::graph_traits<Adapter>::null_face();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
concept_check_adapter();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,466 @@
|
|||
#include <CGAL/boost/graph/Face_filtered_graph.h>
|
||||
#include <CGAL/Polygon_mesh_processing/connected_components.h>
|
||||
#include <CGAL/boost/graph/copy_face_graph.h>
|
||||
#include "test_Prefix.h"
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <CGAL/use.h>
|
||||
#include <fstream>
|
||||
|
||||
typedef boost::unordered_set<std::size_t> id_map;
|
||||
|
||||
template <typename Graph>
|
||||
void test_halfedge_around_vertex_iterator(const Graph& g)
|
||||
{
|
||||
typedef typename boost::graph_traits<Graph>::face_descriptor g_face_descriptor;
|
||||
typedef CGAL::Face_filtered_graph<Graph> Adapter;
|
||||
CGAL_GRAPH_TRAITS_MEMBERS(Adapter);
|
||||
boost::unordered_map<g_face_descriptor, std::size_t> map(num_faces(g));
|
||||
CGAL::Polygon_mesh_processing::connected_components(g, boost::make_assoc_property_map(map), CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
|
||||
|
||||
Adapter fg(g, 0, boost::make_assoc_property_map(map));
|
||||
typename boost::graph_traits<Adapter >::vertex_iterator vit, vend;
|
||||
for(boost::tie(vit, vend) = vertices(fg); vit != vend; ++vit) {
|
||||
halfedge_around_target_iterator havit, havend;
|
||||
for(boost::tie(havit, havend) = CGAL::halfedges_around_target(halfedge(*vit, fg), fg);
|
||||
havit != havend; ++havit) {
|
||||
assert(target(*havit, fg) == *vit);
|
||||
|
||||
// check if we are really moving clockwise
|
||||
halfedge_around_target_iterator step = boost::next(havit);
|
||||
if(step != havend) {
|
||||
halfedge_descriptor stepd = *step;
|
||||
assert(stepd == opposite(next(*havit, fg), fg));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
void test_halfedge_around_face_iterator(const Graph& g)
|
||||
{
|
||||
typedef typename boost::graph_traits<Graph>::face_descriptor g_face_descriptor;
|
||||
typedef CGAL::Face_filtered_graph<Graph> Adapter;
|
||||
CGAL_GRAPH_TRAITS_MEMBERS(Adapter);
|
||||
std::map<g_face_descriptor, std::size_t> map;
|
||||
CGAL::Polygon_mesh_processing::connected_components(g, boost::make_assoc_property_map(map), CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
Adapter fg(g, 0, boost::make_assoc_property_map(map));
|
||||
face_iterator fit, fend;
|
||||
for(boost::tie(fit, fend) = faces(fg); fit != fend; ++fit) {
|
||||
halfedge_around_face_iterator hafit, hafend;
|
||||
boost::tie(hafit, hafend) = CGAL::halfedges_around_face(halfedge(*fit, fg), fg);
|
||||
assert(std::distance(hafit, hafend) != 0);
|
||||
for(boost::tie(hafit, hafend) = CGAL::halfedges_around_face(halfedge(*fit, fg), fg); hafit != hafend; ++hafit) {
|
||||
assert(face(*hafit, fg) == *fit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
void test_edge_iterators(const Graph& g)
|
||||
{
|
||||
typedef typename boost::graph_traits<Graph>::face_descriptor g_face_descriptor;
|
||||
typedef CGAL::Face_filtered_graph<Graph> Adapter;
|
||||
CGAL_GRAPH_TRAITS_MEMBERS(Adapter);
|
||||
std::map<g_face_descriptor, std::size_t> map;
|
||||
CGAL::Polygon_mesh_processing::connected_components(g, boost::make_assoc_property_map(map), CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
Adapter fg(g, 0, boost::make_assoc_property_map(map));
|
||||
|
||||
// do we iterate as many as that?
|
||||
edge_iterator eb, ee;
|
||||
boost::tie(eb, ee) = edges(fg);
|
||||
assert(boost::numeric_cast<edges_size_type>(std::distance(eb, ee)) == num_edges(g));
|
||||
id_map ids;
|
||||
unsigned int count = 0;
|
||||
for(boost::tie(eb, ee) = edges(fg); eb != ee; ++eb) {
|
||||
edge_descriptor e = *eb;
|
||||
std::pair<id_map::iterator, bool> r = ids.insert(get(boost::edge_index, g, e));
|
||||
// unique?
|
||||
assert(r.second);
|
||||
++count;
|
||||
}
|
||||
assert(count == num_edges(fg));
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
void test_vertex_iterators(Graph& g)
|
||||
{
|
||||
typedef typename boost::graph_traits<Graph>::face_descriptor g_face_descriptor;
|
||||
typedef CGAL::Face_filtered_graph<Graph> Adapter;
|
||||
CGAL_GRAPH_TRAITS_MEMBERS(Adapter);
|
||||
std::map<g_face_descriptor, std::size_t> map;
|
||||
CGAL::Polygon_mesh_processing::connected_components(g, boost::make_assoc_property_map(map), CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
Adapter fg(g, 0, boost::make_assoc_property_map(map));
|
||||
vertex_iterator vb, ve;
|
||||
std::size_t count = 0;
|
||||
for(boost::tie(vb, ve) = vertices(fg); vb != ve; ++vb){
|
||||
++count;
|
||||
}
|
||||
|
||||
assert(count == num_vertices(fg));
|
||||
|
||||
// check that the iterators reach uniques
|
||||
id_map ids;
|
||||
|
||||
count = 0;
|
||||
for(boost::tie(vb, ve) = vertices(fg); vb != ve; ++vb) {
|
||||
std::pair<id_map::iterator, bool> r = ids.insert(get(boost::vertex_index, g, *vb));
|
||||
assert(r.second);
|
||||
++count;
|
||||
}
|
||||
assert(count == num_vertices(fg));
|
||||
}
|
||||
|
||||
|
||||
template<typename Graph>
|
||||
void test_out_edges(const Graph& g)
|
||||
{
|
||||
typedef typename boost::graph_traits<Graph>::face_descriptor g_face_descriptor;
|
||||
typedef CGAL::Face_filtered_graph<Graph> Adapter;
|
||||
CGAL_GRAPH_TRAITS_MEMBERS(Adapter);
|
||||
std::map<g_face_descriptor, std::size_t> map;
|
||||
CGAL::Polygon_mesh_processing::connected_components(g, boost::make_assoc_property_map(map), CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
Adapter fg(g, 0, boost::make_assoc_property_map(map));
|
||||
|
||||
vertex_iterator vb, ve;
|
||||
for(boost::tie(vb, ve) = vertices(fg); vb != ve; ++vb) {
|
||||
id_map v_ids;
|
||||
|
||||
vertex_descriptor around = *vb;
|
||||
out_edge_iterator oeb, oee;
|
||||
for(boost::tie(oeb, oee) = out_edges(*vb, fg); oeb != oee; ++oeb) {
|
||||
vertex_descriptor t = target(*oeb, fg);
|
||||
vertex_descriptor s = source(*oeb, fg);
|
||||
assert(s != t);
|
||||
assert(s == around);
|
||||
assert(t != around);
|
||||
std::pair<id_map::iterator, bool> r =
|
||||
v_ids.insert(get(boost::vertex_index, g, target(*oeb, fg)));
|
||||
assert(r.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
void test_in_edges(const Graph& g)
|
||||
{
|
||||
typedef typename boost::graph_traits<Graph>::face_descriptor g_face_descriptor;
|
||||
typedef CGAL::Face_filtered_graph<Graph> Adapter;
|
||||
CGAL_GRAPH_TRAITS_MEMBERS(Adapter);
|
||||
std::map<g_face_descriptor, std::size_t> map;
|
||||
CGAL::Polygon_mesh_processing::connected_components(g, boost::make_assoc_property_map(map), CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
Adapter fg(g, 0, boost::make_assoc_property_map(map));
|
||||
|
||||
vertex_iterator vb, ve;
|
||||
for(boost::tie(vb, ve) = vertices(fg); vb != ve; ++vb) {
|
||||
id_map v_ids;
|
||||
vertex_descriptor around = *vb;
|
||||
in_edge_iterator ieb, iee;
|
||||
for(boost::tie(ieb, iee) = in_edges(*vb, fg); ieb != iee; ++ieb) {
|
||||
vertex_descriptor t = target(*ieb, fg);
|
||||
vertex_descriptor s = source(*ieb, fg);
|
||||
assert(t == around);
|
||||
assert(s != around);
|
||||
std::pair<id_map::iterator, bool> r =
|
||||
v_ids.insert(get(boost::vertex_index, g, source(*ieb, fg)));
|
||||
assert(r.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
void test_in_out_edges(const Graph& g)
|
||||
{
|
||||
typedef typename boost::graph_traits<Graph>::face_descriptor g_face_descriptor;
|
||||
typedef CGAL::Face_filtered_graph<Graph> Adapter;
|
||||
CGAL_GRAPH_TRAITS_MEMBERS(Adapter);
|
||||
std::map<g_face_descriptor, std::size_t> map;
|
||||
CGAL::Polygon_mesh_processing::connected_components(g, boost::make_assoc_property_map(map), CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
Adapter fg(g, 0, boost::make_assoc_property_map(map));
|
||||
|
||||
// check that the sets of in out edges are the same
|
||||
vertex_iterator vb, ve;
|
||||
for(boost::tie(vb, ve) = vertices(fg); vb != ve; ++vb) {
|
||||
id_map v_ids;
|
||||
std::vector<vertex_descriptor> in, out;
|
||||
in_edge_iterator ieb, iee;
|
||||
for(boost::tie(ieb, iee) = in_edges(*vb, fg); ieb != iee; ++ieb) {
|
||||
std::pair<id_map::iterator, bool> r =
|
||||
v_ids.insert(get(boost::vertex_index, g, source(*ieb, fg)));
|
||||
assert(r.second);
|
||||
in.push_back(source(*ieb, fg));
|
||||
}
|
||||
out_edge_iterator oeb, oee;
|
||||
for(boost::tie(oeb, oee) = out_edges(*vb, fg); oeb != oee; ++oeb) {
|
||||
std::pair<id_map::iterator, bool> r =
|
||||
v_ids.insert(get(boost::vertex_index, g, target(*oeb, fg)));
|
||||
// insertion must fail
|
||||
assert(!r.second);
|
||||
out.push_back(target(*oeb, fg));
|
||||
}
|
||||
// did we walk the vertices in the same order?
|
||||
assert(in.size() == out.size());
|
||||
assert(std::equal(in.begin(), in.end(), out.begin()));
|
||||
assert(in.size() == in_degree(*vb, fg));
|
||||
assert(out.size() == out_degree(*vb, fg));
|
||||
assert(in.size() == degree(*vb, fg));
|
||||
assert(degree(*vb, fg) == in_degree(*vb, fg));
|
||||
assert(degree(*vb, fg) == out_degree(*vb, fg));
|
||||
}
|
||||
}
|
||||
|
||||
// check that every edge can be found through edge(u, v, g)
|
||||
template<typename Graph>
|
||||
void test_edge_find(const Graph& g)
|
||||
{
|
||||
typedef typename boost::graph_traits<Graph>::face_descriptor g_face_descriptor;
|
||||
typedef CGAL::Face_filtered_graph<Graph> Adapter;
|
||||
CGAL_GRAPH_TRAITS_MEMBERS(Adapter);
|
||||
std::map<g_face_descriptor, std::size_t> map;
|
||||
CGAL::Polygon_mesh_processing::connected_components(g, boost::make_assoc_property_map(map), CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
Adapter fg(g, 0, boost::make_assoc_property_map(map));
|
||||
typedef std::pair<edge_descriptor, bool> ret;
|
||||
|
||||
edge_iterator eb, ee;
|
||||
for(boost::tie(eb, ee) = edges(fg); eb != ee; ++eb) {
|
||||
vertex_descriptor s = source(*eb, fg);
|
||||
vertex_descriptor t = target(*eb, fg);
|
||||
ret found = edge(s, t, fg);
|
||||
ret found2 = edge(t, s, fg);
|
||||
assert(found.second);
|
||||
assert(found2.second);
|
||||
assert(found.first == *eb);
|
||||
assert(found2.first == *eb);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
void test_faces(const Graph& g)
|
||||
{
|
||||
typedef typename boost::graph_traits<Graph>::face_descriptor g_face_descriptor;
|
||||
typedef CGAL::Face_filtered_graph<Graph> Adapter;
|
||||
CGAL_GRAPH_TRAITS_MEMBERS(Adapter);
|
||||
std::map<g_face_descriptor, std::size_t> map;
|
||||
CGAL::Polygon_mesh_processing::connected_components(g, boost::make_assoc_property_map(map), CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
Adapter fg(g, 0, boost::make_assoc_property_map(map));
|
||||
|
||||
unsigned int count = 0;
|
||||
face_iterator fb, fe;
|
||||
for(boost::tie(fb, fe) = faces(fg); fb != fe; ++fb) {
|
||||
++count;
|
||||
// reverse look-up
|
||||
halfedge_descriptor assoc = halfedge(*fb, fg);
|
||||
assert(face(assoc, fg) == *fb);
|
||||
// check the enclosure
|
||||
halfedge_around_face_iterator encb, ence;
|
||||
for(boost::tie(encb, ence) = CGAL::halfedges_around_face(halfedge(*fb, fg), fg); encb != ence; ++encb) {
|
||||
assert(face(*encb, fg) == *fb);
|
||||
}
|
||||
}
|
||||
assert(count == num_faces(fg));
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
void test_read(const Graph& g)
|
||||
{
|
||||
typedef typename boost::graph_traits<Graph>::face_descriptor g_face_descriptor;
|
||||
typedef CGAL::Face_filtered_graph<Graph> Adapter;
|
||||
CGAL_GRAPH_TRAITS_MEMBERS(Adapter);
|
||||
std::map<g_face_descriptor, std::size_t> map;
|
||||
CGAL::Polygon_mesh_processing::connected_components(g, boost::make_assoc_property_map(map), CGAL::Polygon_mesh_processing::parameters::all_default());
|
||||
Adapter fg(g, 0, boost::make_assoc_property_map(map));
|
||||
assert(CGAL::is_valid(fg));
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
void
|
||||
test(const std::vector<Graph>& graphs)
|
||||
{
|
||||
BOOST_FOREACH(Graph p, graphs){
|
||||
test_read(p);
|
||||
test_vertex_iterators(p);
|
||||
test_out_edges(p);
|
||||
test_in_edges(p);
|
||||
test_in_out_edges(p);
|
||||
test_edge_find(p);
|
||||
test_faces(p);
|
||||
test_edge_iterators(p);
|
||||
test_halfedge_around_face_iterator(p);
|
||||
test_halfedge_around_vertex_iterator(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef SM::Point Point_3;
|
||||
|
||||
template<class Mesh, typename VertexPointPMap>
|
||||
struct Constraint : public boost::put_get_helper<bool,Constraint<Mesh, VertexPointPMap> >
|
||||
{
|
||||
typedef typename boost::graph_traits<Mesh>::edge_descriptor edge_descriptor;
|
||||
typedef boost::readable_property_map_tag category;
|
||||
typedef bool value_type;
|
||||
typedef bool reference;
|
||||
typedef edge_descriptor key_type;
|
||||
|
||||
|
||||
Constraint()
|
||||
:g_(NULL)
|
||||
{}
|
||||
|
||||
Constraint(Mesh& g, VertexPointPMap vpp)
|
||||
: g_(&g), vppmap(vpp)
|
||||
{}
|
||||
|
||||
bool operator[](edge_descriptor e) const
|
||||
{
|
||||
const Mesh& g = *g_;
|
||||
if(
|
||||
((boost::get(vppmap, target(e, g)) == Point_3(1,1,1) ||
|
||||
boost::get(vppmap, source(e, g)) == Point_3(1,1,1)) &&
|
||||
(boost::get(vppmap, target(e, g)) == Point_3(0,0,0) ||
|
||||
boost::get(vppmap, source(e, g)) == Point_3(0,0,0)))
|
||||
||
|
||||
((boost::get(vppmap, target(e, g)) == Point_3(1,1,1) ||
|
||||
boost::get(vppmap, source(e, g)) == Point_3(1,1,1)) &&
|
||||
(boost::get(vppmap, target(e, g)) == Point_3(0,0,1) ||
|
||||
boost::get(vppmap, source(e, g)) == Point_3(0,0,1)))
|
||||
||
|
||||
((boost::get(vppmap, target(e, g)) == Point_3(0,0,1) ||
|
||||
boost::get(vppmap, source(e, g)) == Point_3(0,0,1)) &&
|
||||
(boost::get(vppmap, target(e, g)) == Point_3(0,0,0) ||
|
||||
boost::get(vppmap, source(e, g)) == Point_3(0,0,0)))
|
||||
||
|
||||
((boost::get(vppmap, target(e, g)) == Point_3(1,0,1) ||
|
||||
boost::get(vppmap, source(e, g)) == Point_3(1,0,1)) &&
|
||||
(boost::get(vppmap, target(e, g)) == Point_3(0,0,0) ||
|
||||
boost::get(vppmap, source(e, g)) == Point_3(0,0,0)))
|
||||
||
|
||||
((boost::get(vppmap, target(e, g)) == Point_3(1,1,1) ||
|
||||
boost::get(vppmap, source(e, g)) == Point_3(1,1,1)) &&
|
||||
(boost::get(vppmap, target(e, g)) == Point_3(1,0,1) ||
|
||||
boost::get(vppmap, source(e, g)) == Point_3(1,0,1)))
|
||||
)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
const Mesh* g_;
|
||||
VertexPointPMap vppmap;
|
||||
};
|
||||
template<class Mesh, class FCCMAP, class Adapter>
|
||||
void test_mesh(Adapter fga)
|
||||
{
|
||||
|
||||
CGAL_GRAPH_TRAITS_MEMBERS(Adapter);
|
||||
//check that there is the right number of simplices in fga
|
||||
CGAL_assertion(CGAL::is_valid(fga));
|
||||
CGAL_assertion(num_faces(fga) == 2);
|
||||
CGAL_assertion(num_edges(fga) == 5);
|
||||
CGAL_assertion(num_halfedges(fga) == 10);
|
||||
CGAL_assertion(num_vertices(fga) == 4);
|
||||
halfedge_descriptor h = halfedge(*faces(fga).first, fga);
|
||||
CGAL_assertion_code( vertex_descriptor v = source(h, fga) );
|
||||
//check that next() works inside the patch
|
||||
CGAL_assertion(
|
||||
next(next(next(h, fga), fga), fga) == h
|
||||
);
|
||||
//check that next() works on bordure of the patch
|
||||
h = opposite(h, fga);
|
||||
CGAL_assertion(
|
||||
next(next(next(next(h, fga), fga), fga), fga) == h
|
||||
);
|
||||
//check that prev() works inside the patch
|
||||
h = halfedge(*faces(fga).first, fga);
|
||||
CGAL_assertion(
|
||||
prev(prev(prev(h, fga), fga), fga) == h
|
||||
);
|
||||
//check that prev() works on bordure of the patch
|
||||
h = opposite(h, fga);
|
||||
CGAL_assertion(
|
||||
prev(prev(prev(prev(h, fga), fga), fga), fga) == h
|
||||
);
|
||||
//check degree
|
||||
CGAL_assertion(degree(v, fga) == 3);
|
||||
//check in_edges and out_edges
|
||||
CGAL_assertion(std::distance(in_edges(v, fga).first ,in_edges(v, fga).second) == 3 );
|
||||
CGAL_assertion(std::distance(out_edges(v, fga).first ,out_edges(v, fga).second) == 3 );
|
||||
|
||||
Mesh copy;
|
||||
CGAL::copy_face_graph(fga, copy);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test(sm_data());
|
||||
#ifdef CGAL_USE_OPENMESH
|
||||
test(omesh_data());
|
||||
#endif
|
||||
//Make a tetrahedron and test the adapter for a patch that only contains 2 faces
|
||||
typedef CGAL::Face_filtered_graph<SM> SM_Adapter;
|
||||
typedef SM::Property_map<boost::graph_traits<SM>::face_descriptor , std::size_t> SM_FCCMap;
|
||||
SM* sm = new SM();
|
||||
CGAL::make_tetrahedron(
|
||||
Point_3(1,1,1),
|
||||
Point_3(0,0,0),
|
||||
Point_3(0,0,1),
|
||||
Point_3(1,0,1),
|
||||
*sm);
|
||||
SM_FCCMap fccmap =
|
||||
sm->add_property_map<boost::graph_traits<SM>::face_descriptor, std::size_t>("f:CC").first;
|
||||
SM::Property_map<boost::graph_traits<SM>::vertex_descriptor, SM::Point> positions =
|
||||
sm->points();
|
||||
CGAL::Polygon_mesh_processing::connected_components(*sm, fccmap, CGAL::Polygon_mesh_processing::parameters::
|
||||
edge_is_constrained_map(Constraint<SM, SM::Property_map<boost::graph_traits<SM>::vertex_descriptor,
|
||||
SM::Point> >(*sm, positions)));
|
||||
boost::unordered_set<long unsigned int> pids;
|
||||
pids.insert(0);
|
||||
pids.insert(2);
|
||||
SM_Adapter sm_adapter(*sm, pids, fccmap);
|
||||
test_mesh<SM,SM_FCCMap, SM_Adapter>(sm_adapter);
|
||||
|
||||
|
||||
|
||||
|
||||
typedef boost::graph_traits<Polyhedron> PolyTraits;
|
||||
typedef boost::property_map<Polyhedron, boost::vertex_point_t>::type VPMap;
|
||||
typedef PolyTraits::face_descriptor poly_face_descriptor;
|
||||
typedef boost::associative_property_map< std::map<poly_face_descriptor,
|
||||
PolyTraits::faces_size_type> > FCMap;
|
||||
typedef boost::property_map<Polyhedron, CGAL::face_external_index_t>::type FIMap;
|
||||
typedef boost::property_map<Polyhedron, CGAL::vertex_external_index_t>::type VIMap;
|
||||
typedef boost::property_map<Polyhedron, CGAL::halfedge_external_index_t>::type HIMap;
|
||||
typedef CGAL::Face_filtered_graph<Polyhedron, FIMap, VIMap, HIMap> Poly_Adapter;
|
||||
Polyhedron *poly = new Polyhedron();
|
||||
CGAL::make_tetrahedron(
|
||||
Point_3(1,1,1),
|
||||
Point_3(0,0,0),
|
||||
Point_3(0,0,1),
|
||||
Point_3(1,0,1),
|
||||
*poly);
|
||||
|
||||
|
||||
FIMap poly_fimap = get(CGAL::face_external_index, *poly);
|
||||
VIMap poly_vimap = get(CGAL::vertex_external_index, *poly);
|
||||
HIMap poly_himap = get(CGAL::halfedge_external_index, *poly);
|
||||
std::map<poly_face_descriptor,
|
||||
PolyTraits::faces_size_type> fc_map;
|
||||
FCMap poly_fccmap(fc_map);
|
||||
|
||||
VPMap vpmap = get(boost::vertex_point, *poly);
|
||||
CGAL::Polygon_mesh_processing::connected_components(*poly, poly_fccmap, CGAL::Polygon_mesh_processing::parameters::
|
||||
edge_is_constrained_map(Constraint<Polyhedron, VPMap >(*poly, vpmap)).
|
||||
face_index_map(poly_fimap));
|
||||
Poly_Adapter poly_adapter(*poly,
|
||||
pids,
|
||||
poly_fccmap,
|
||||
CGAL::parameters::face_index_map(poly_fimap).
|
||||
vertex_index_map(poly_vimap).
|
||||
halfedge_index_map(poly_himap));
|
||||
test_mesh<Polyhedron, FCMap, Poly_Adapter>(poly_adapter);
|
||||
}
|
||||
|
|
@ -178,6 +178,14 @@ and <code>src/</code> directories).
|
|||
<!-- Interpolation -->
|
||||
<!-- Kinetic Data Structures -->
|
||||
<!-- Support Library -->
|
||||
<h3>CGAL and the Boost Graph Library (BGL)</h3>
|
||||
<ul>
|
||||
<li>
|
||||
Add class <code>CGAL::Face_filtered_graph</code> that
|
||||
wraps an existing graph and hide all simplices that are not
|
||||
in the selected connected components.
|
||||
</li>
|
||||
</ul>
|
||||
<!-- Visualization -->
|
||||
|
||||
<!-- end of the div for 4.10 -->
|
||||
|
|
|
|||
|
|
@ -598,7 +598,7 @@ should be discarded in favour of major connected components.
|
|||
|
||||
\subsection CCExample Connected Components Example
|
||||
|
||||
The following example shows how to record the connected
|
||||
The first example shows how to record the connected
|
||||
components of a polygon mesh.
|
||||
In particular, we provide an example for the optional parameter \c EdgeConstraintMap,
|
||||
a property map that returns information about an edge being a \e constraint or not.
|
||||
|
|
@ -607,6 +607,12 @@ the propagation of a connected component index to cross it.
|
|||
|
||||
\cgalExample{Polygon_mesh_processing/connected_components_example.cpp}
|
||||
|
||||
The second example shows how to use the class template `Face_filtered_graph`
|
||||
which enables to treat one or several connected components as a face graph.
|
||||
|
||||
\cgalExample{Polygon_mesh_processing/face_filtered_graph_example.cpp}
|
||||
|
||||
|
||||
\section PMPDistance Approximate Hausdorff Distance
|
||||
|
||||
This package provides methods to compute (approximate) distances between meshes and point sets.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
\example Polygon_mesh_processing/point_inside_example.cpp
|
||||
\example Polygon_mesh_processing/triangulate_faces_example.cpp
|
||||
\example Polygon_mesh_processing/connected_components_example.cpp
|
||||
\example Polygon_mesh_processing/face_filtered_graph_example.cpp
|
||||
\example Polygon_mesh_processing/polygon_soup_example.cpp
|
||||
\example Polygon_mesh_processing/triangulate_polyline_example.cpp
|
||||
\example Polygon_mesh_processing/refine_fair_example.cpp
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ create_single_source_cgal_program( "compute_normals_example.cpp" CXX_FEATURES cx
|
|||
create_single_source_cgal_program( "point_inside_example.cpp")
|
||||
create_single_source_cgal_program( "triangulate_faces_example.cpp")
|
||||
create_single_source_cgal_program( "connected_components_example.cpp")
|
||||
create_single_source_cgal_program( "face_filtered_graph_example.cpp")
|
||||
create_single_source_cgal_program( "polygon_soup_example.cpp")
|
||||
create_single_source_cgal_program( "triangulate_polyline_example.cpp")
|
||||
create_single_source_cgal_program( "mesh_slicer_example.cpp")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/connected_components.h>
|
||||
#include <CGAL/boost/graph/Face_filtered_graph.h>
|
||||
|
||||
#include <boost/property_map/property_map.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_3 Point;
|
||||
|
||||
typedef CGAL::Surface_mesh<Point> Mesh;
|
||||
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
|
||||
typedef boost::graph_traits<Mesh>::faces_size_type faces_size_type;
|
||||
|
||||
typedef Mesh::Property_map<face_descriptor, faces_size_type> FCCmap;
|
||||
typedef CGAL::Face_filtered_graph<Mesh> Filtered_graph;
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
std::ifstream input((argc > 1) ? argv[1] : "data/blobby_3cc.off");
|
||||
|
||||
Mesh mesh;
|
||||
if (!input || !(input >> mesh) || mesh.is_empty()) {
|
||||
std::cerr << "Not a valid off file." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
FCCmap fccmap = mesh.add_property_map<face_descriptor, faces_size_type>("f:CC").first;
|
||||
|
||||
faces_size_type num = PMP::connected_components(mesh,fccmap);
|
||||
|
||||
std::cerr << "- The graph has " << num << " connected components (face connectivity)" << std::endl;
|
||||
|
||||
Filtered_graph ffg(mesh, 0, fccmap);
|
||||
|
||||
std::cout << "The faces in component 0 are:" << std::endl;
|
||||
BOOST_FOREACH(boost::graph_traits<Filtered_graph>::face_descriptor f, faces(ffg)){
|
||||
std::cout << f << std::endl;
|
||||
}
|
||||
|
||||
if(num>1){
|
||||
std::vector<faces_size_type> components;
|
||||
components.push_back(0);
|
||||
components.push_back(1);
|
||||
|
||||
ffg.set_selected_faces(components, fccmap);
|
||||
|
||||
std::cout << "The faces in components 0 and 1 are:" << std::endl;
|
||||
BOOST_FOREACH(Filtered_graph::face_descriptor f, faces(ffg)){
|
||||
std::cout << f << std::endl;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -42,52 +42,6 @@ public:
|
|||
typedef typename boost::property_traits<PMap>::value_type type;
|
||||
};
|
||||
|
||||
template<typename PolygonMesh, typename PropertyTag>
|
||||
class property_map_selector
|
||||
{
|
||||
public:
|
||||
typedef typename boost::graph_has_property<PolygonMesh, PropertyTag>::type Has_internal_pmap;
|
||||
typedef typename boost::mpl::if_c< Has_internal_pmap::value
|
||||
, typename boost::property_map<PolygonMesh, PropertyTag>::type
|
||||
, typename boost::cgal_no_property::type
|
||||
>::type type;
|
||||
typedef typename boost::mpl::if_c< Has_internal_pmap::value
|
||||
, typename boost::property_map<PolygonMesh, PropertyTag>::const_type
|
||||
, typename boost::cgal_no_property::const_type
|
||||
>::type const_type;
|
||||
|
||||
type get_pmap(const PropertyTag& p, PolygonMesh& pmesh)
|
||||
{
|
||||
return get_impl(p, pmesh, Has_internal_pmap());
|
||||
}
|
||||
|
||||
const_type get_const_pmap(const PropertyTag& p, const PolygonMesh& pmesh)
|
||||
{
|
||||
return get_const_pmap_impl(p, pmesh, Has_internal_pmap());
|
||||
}
|
||||
|
||||
private:
|
||||
type get_impl(const PropertyTag&, PolygonMesh&, CGAL::Tag_false)
|
||||
{
|
||||
return type(); //boost::cgal_no_property::type
|
||||
}
|
||||
type get_impl(const PropertyTag& p, PolygonMesh& pmesh, CGAL::Tag_true)
|
||||
{
|
||||
return get(p, pmesh);
|
||||
}
|
||||
|
||||
const_type get_const_pmap_impl(const PropertyTag&
|
||||
, const PolygonMesh&, CGAL::Tag_false)
|
||||
{
|
||||
return const_type(); //boost::cgal_no_property::type
|
||||
}
|
||||
const_type get_const_pmap_impl(const PropertyTag& p
|
||||
, const PolygonMesh& pmesh, CGAL::Tag_true)
|
||||
{
|
||||
return get(p, pmesh);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PolygonMesh, typename NamedParameters>
|
||||
class GetVertexPointMap
|
||||
{
|
||||
|
|
@ -138,22 +92,6 @@ public:
|
|||
> ::type type;
|
||||
};
|
||||
|
||||
template<typename PolygonMesh, typename PropertyTag>
|
||||
typename property_map_selector<PolygonMesh, PropertyTag>::type
|
||||
get_property_map(const PropertyTag& p, PolygonMesh& pmesh)
|
||||
{
|
||||
property_map_selector<PolygonMesh, PropertyTag> pms;
|
||||
return pms.get_pmap(p, pmesh);
|
||||
}
|
||||
|
||||
template<typename PolygonMesh, typename PropertyTag>
|
||||
typename property_map_selector<PolygonMesh, PropertyTag>::const_type
|
||||
get_const_property_map(const PropertyTag& p, const PolygonMesh& pmesh)
|
||||
{
|
||||
property_map_selector<PolygonMesh, PropertyTag> pms;
|
||||
return pms.get_const_pmap(p, pmesh);
|
||||
}
|
||||
|
||||
template<typename PolygonMesh, typename NamedParameters>
|
||||
class GetFaceIndexMap
|
||||
{
|
||||
|
|
|
|||
|
|
@ -200,11 +200,17 @@ The main advantage is to decrease from log to constant the complexity for access
|
|||
|
||||
\cgalExample{Surface_mesh_segmentation/segmentation_with_facet_ids_example.cpp}
|
||||
|
||||
|
||||
\subsection Surface_mesh_segmentationUsingapolyhedron Using a Surface_mesh
|
||||
When using a `Surface_mesh`, you can use the built-in property mechanism.
|
||||
|
||||
\cgalExample{Surface_mesh_segmentation/segmentation_from_sdf_values_SM_example.cpp}
|
||||
|
||||
\subsection Surface_mesh_segmentationIndependantmeshpersegment Independant TriangleMesh per Segment
|
||||
It is possible to consider each segment as an independant triangle mesh, like in the following example, where the area of each segment is computed.
|
||||
|
||||
\cgalExample{Surface_mesh_segmentation/extract_segmentation_into_mesh_example.cpp}
|
||||
|
||||
<BR>
|
||||
\section Performances Performances
|
||||
<!-- \subsection SMSRuntime Runtime of the functions sdf_values() and segmentation_from_sdf_values() -->
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@
|
|||
/// \example Surface_mesh_segmentation/segmentation_from_sdf_values_SM_example.cpp
|
||||
/// \example Surface_mesh_segmentation/segmentation_via_sdf_values_example.cpp
|
||||
/// \example Surface_mesh_segmentation/segmentation_with_facet_ids_example.cpp
|
||||
/// \example Surface_mesh_segmentation/extract_segmentation_into_mesh_example.cpp
|
||||
|
|
|
|||
|
|
@ -64,8 +64,11 @@ create_single_source_cgal_program( "segmentation_from_sdf_values_example.cpp" )
|
|||
create_single_source_cgal_program( "segmentation_via_sdf_values_example.cpp" )
|
||||
|
||||
create_single_source_cgal_program( "segmentation_with_facet_ids_example.cpp" )
|
||||
|
||||
create_single_source_cgal_program( "segmentation_from_sdf_values_SM_example.cpp")
|
||||
|
||||
create_single_source_cgal_program( "extract_segmentation_into_mesh_example.cpp")
|
||||
|
||||
if(OpenMesh_FOUND)
|
||||
create_single_source_cgal_program( "segmentation_from_sdf_values_OpenMesh_example.cpp" )
|
||||
target_link_libraries( segmentation_from_sdf_values_OpenMesh_example ${OPENMESH_LIBRARIES} )
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
|
||||
#include <CGAL/boost/graph/Face_filtered_graph.h>
|
||||
#include <CGAL/Polygon_mesh_processing/measure.h>
|
||||
#include <CGAL/boost/graph/copy_face_graph.h>
|
||||
#include <CGAL/mesh_segmentation.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef CGAL::Surface_mesh<Kernel::Point_3> SM;
|
||||
typedef boost::graph_traits<SM>::face_descriptor face_descriptor;
|
||||
|
||||
int main(int argc, char** argv )
|
||||
{
|
||||
SM mesh;
|
||||
if (argc==2){
|
||||
std::ifstream input(argv[1]);
|
||||
input >> mesh;
|
||||
} else {
|
||||
std::ifstream cactus("data/cactus.off");
|
||||
cactus >> mesh;
|
||||
}
|
||||
typedef SM::Property_map<face_descriptor,double> Facet_double_map;
|
||||
Facet_double_map sdf_property_map;
|
||||
|
||||
sdf_property_map = mesh.add_property_map<face_descriptor,double>("f:sdf").first;
|
||||
|
||||
CGAL::sdf_values(mesh, sdf_property_map);
|
||||
|
||||
// create a property-map for segment-ids
|
||||
typedef SM::Property_map<face_descriptor, std::size_t> Facet_int_map;
|
||||
Facet_int_map segment_property_map = mesh.add_property_map<face_descriptor,std::size_t>("f:sid").first;;
|
||||
|
||||
// segment the mesh using default parameters for number of levels, and smoothing lambda
|
||||
// Any other scalar values can be used instead of using SDF values computed using the CGAL function
|
||||
std::size_t number_of_segments = CGAL::segmentation_from_sdf_values(mesh, sdf_property_map, segment_property_map);
|
||||
|
||||
typedef CGAL::Face_filtered_graph<SM> Filtered_graph;
|
||||
//print area of each segment and then put it in a Mesh and print it in an OFF file
|
||||
Filtered_graph segment_mesh(mesh, 0, segment_property_map);
|
||||
for(std::size_t id = 0; id < number_of_segments; ++id)
|
||||
{
|
||||
if(id > 0)
|
||||
segment_mesh.set_selected_faces(id, segment_property_map);
|
||||
std::cout << "Segment "<<id<<"'s area is : "<<CGAL::Polygon_mesh_processing::area(segment_mesh)<<std::endl;
|
||||
SM out;
|
||||
CGAL::copy_face_graph(segment_mesh, out);
|
||||
std::ostringstream oss;
|
||||
oss << "Segment_" << id<<".off";
|
||||
std::ofstream os(oss.str().data());
|
||||
os<<out;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue