Changes :

- Remove copy_face_graph_patch
- Use an unordered_set instead of a single patch_id.
This commit is contained in:
Maxime Gimeno 2017-02-03 10:24:28 +01:00
parent 513edafdb2
commit afd44de2e6
3 changed files with 59 additions and 286 deletions

View File

@ -24,6 +24,7 @@
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/assertions.h>
#include <boost/foreach.hpp>
#include <boost/unordered_set.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/foreach.hpp>
@ -35,9 +36,9 @@ namespace CGAL
/*!
\ingroup PkgBGLHelper
The class `Connected_component_graph` wraps a graph into another graph in such a way that only the specified connected component is seen from the outside.
The class `Connected_component_graph` wraps a graph into another graph in such a way that only the specified connected components are seen from the outside.
For example, calling `vertices(graph)` will return an iterator range of all but only the vertices that belong to the connected component whose id in `fccmap` is `pid`.
For example, calling `vertices(graph)` will return an iterator range of all but only the vertices that belong to the connected components whose ids in `fccmap` are contained in `pids`.
\attention The functions `num_vertices()`, `num_edges()`, `num_halfedges()`, `num_faces()`, are forwarded from the underlying graph,
which means that `num_vertices(graph)` is different from `std::distance(vertices(graph).first,vertices(graph).second)`
@ -62,22 +63,42 @@ struct Connected_component_graph
typedef typename gt::face_descriptor face_descriptor;
typedef Connected_component_graph<Graph, FaceComponentMap> Self;
/*!
* \brief Creates a Connected_component_graph of the connected components of `graph` that are listed in `pids`.
* \param graph the graph containing the wanted patches.
* \param fccmap the property_map that assigns a patch to each face
* \param pids the indices of the patches of interest.
*/
Connected_component_graph(const Graph& graph,
FaceComponentMap fccmap,
typename boost::property_traits<FaceComponentMap>::value_type pid)
: _graph(graph), _property_map(fccmap), _patch_index(pid)
boost::unordered_set<typename boost::property_traits<FaceComponentMap>::value_type> pids)
: _graph(graph), _property_map(fccmap), _patch_indices(pids)
{
}
/*!
* \brief Creates a Connected_component_graph of the connected component `pid` of `graph`.
* \param graph the graph containing the wanted patch.
* \param fccmap the property_map that assigns a patch to each face
* \param pid the index of the patch of interest.
*/
Connected_component_graph(const Graph& graph,
FaceComponentMap fccmap,
typename boost::property_traits<FaceComponentMap>::value_type pid)
: _graph(graph), _property_map(fccmap)
{
_patch_indices = boost::unordered_set<typename boost::property_traits<FaceComponentMap>::value_type>();
_patch_indices.insert(pid);
}
///returns the graph of the Connected_component_graph.
const Graph& graph()const{ return _graph; }
///returns the property map of the Connected_component_graph.
FaceComponentMap property_map()const{ return _property_map; }
typename boost::property_traits<FaceComponentMap>::value_type patch_index()const{ return _patch_index; }
void change_patch_id(typename boost::property_traits<FaceComponentMap>::value_type pid) { _patch_index = pid;}
///returns the unordered set of patch ids of the Connected_component_graph.
boost::unordered_set<typename boost::property_traits<FaceComponentMap>::value_type> patch_indices()const{ return _patch_indices; }
/// Replaces the current unordered set of patches by `pids`
void change_patch_id(boost::unordered_set<typename boost::property_traits<FaceComponentMap>::value_type> pids) { _patch_indices = pids;}
struct Is_simplex_valid
{
@ -100,7 +121,7 @@ struct Connected_component_graph
private:
const Graph& _graph;
FaceComponentMap _property_map;
typename boost::property_traits<FaceComponentMap>::value_type _patch_index;
boost::unordered_set<typename boost::property_traits<FaceComponentMap>::value_type> _patch_indices;
};
} // namespace CGAL
@ -171,7 +192,7 @@ bool
in_CC(const typename boost::graph_traits< Connected_component_graph<Graph, FaceComponentMap> >::face_descriptor f,
const Connected_component_graph<Graph, FaceComponentMap> & w)
{
return boost::get(w.property_map(), f) == w.patch_index();
return w.patch_indices().find(boost::get(w.property_map(), f)) != w.patch_indices().end();
}
template <class Graph, typename FaceComponentMap >

View File

@ -1,260 +0,0 @@
// Copyright (c) 2017 GeometryFactory (France). All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Maxime Gimeno
#ifndef CGAL_BOOST_GRAPH_COPY_FACE_GRAPH_PATCH_H
#define CGAL_BOOST_GRAPH_COPY_FACE_GRAPH_PATCH_H
#include <CGAL/boost/graph/copy_face_graph.h>
#include <CGAL/boost/graph/Connected_component_graph.h>
#include <CGAL/boost/graph/halfedge_graph_traits.h>
#include <CGAL/boost/graph/Connected_component_graph.h>
namespace CGAL {
/*!
\ingroup PkgBGLHelperFct
copies a connected component of a source model of `FaceListGraph` into a target model of a
`FaceListGraph`. `OutputIterators` can be provided to produce a
mapping between source and target elements. The target graph is not
cleared.
\tparam SourceMesh a model of `FaceListGraph`.
The descriptor types `boost::graph_traits<SourceMesh>::%vertex_descriptor`
and `boost::graph_traits<SourceMesh>::%face_descriptor` must be
models of `Hashable`.
\tparam TargetMesh a model of `FaceListGraph`
\tparam FaceComponentMap a model of `WritablePropertyMap` with
`boost::graph_traits<PolygonMesh>::%face_descriptor` as key type and
`graph_traits<PolygonMesh>::faces_size_type` as value type.
\tparam V2V a model of `OutputIterator` accepting `std::pair<sm_vertex_descriptor, tm_vertex_descriptor>`
\tparam H2H a model of `OutputIterator` accepting `std::pair<sm_halfedge_descriptor, tm_halfedge_descriptor>`
\tparam F2F a model of `OutputIterator` accepting `std::pair<sm_face_descriptor, tm_face_descriptor>`
\tparam Src_vpm a model of `ReadablePropertyMap` with `sm_vertex_descriptor` as key
\tparam Tgt_vpm a model of `WritablePropertyMap` with `tm_vertex_descriptor` as key
where the prefix `sm_` and `tm_` mean belonging to the source and
target mesh respectively.
The types `sm_vertex_descriptor` and `sm_face_descriptor` must be models of the concept `Hashable`.
\param sm the source mesh
\param fccmap the property map containing the faces of `sm` and the index of their connected component.
\param pid the index in `fccmap` of the connected component to copy
\param tm the target mesh
\param v2v pairs of `vertex_descriptors` from `sm` and corresponding `vertex_descriptors` in `tm` are added to `v2v`
\param h2h pairs of `halfedge_descriptors` from `sm` and corresponding `halfedge_descriptors` in `tm` are added to `h2h`
\param f2f pairs of `face_descriptors` from `sm` and corresponding `face_descriptors` in `tm` are added to `f2f`
\param sm_vpm vertex point map for `sm`
\param tm_vpm vertex point map for `tm`
The points from `sm` to `tm` are converted using
`CGAL::Cartesian_converter<SourceKernel, TargetKernel>`.
`SourceKernel` and `TargetKernel` are deduced using `CGAL::Kernel_traits`
from the value types of `Src_vpm` and `Tgt_vpm`.
Other properties are not copied.
*/
#if defined(DOXYGEN_RUNNING) // Use template default arguments
template <typename SourceMesh, typename TargetMesh,
typename FaceComponentMap,
typename V2V = Emptyset_iterator,
typename H2H = Emptyset_iterator,
typename F2F = Emptyset_iterator,
typename Src_vpm = typename boost::property_map<SourceMesh, vertex_point_t>::const_type,
typename Tgt_vpm = typename boost::property_map<TargetMesh, vertex_point_t>::type>
void copy_face_graph_patch(const SourceMesh& sm,
FaceComponentMap fccmap,
typename boost::graph_traits<SourceMesh>::faces_size_type pid,
TargetMesh& tm,
V2V v2v = V2V(), H2H h2h = H2H(), F2F f2f = F2F(),
Src_vpm sm_vpm = get(vertex_point, sm),
Tgt_vpm tm_vpm = get(vertex_point, tm) )
#else // use the overloads
template <typename SourceMesh, typename TargetMesh,
typename FaceComponentMap, typename V2V,
typename H2H, typename F2F,
typename Src_vpm, typename Tgt_vpm >
void copy_face_graph_patch(const SourceMesh& sm, FaceComponentMap fccmap, typename boost::graph_traits<SourceMesh>::faces_size_type pid, TargetMesh& tm,
V2V v2v, H2H h2h, F2F f2f,
Src_vpm sm_vpm, Tgt_vpm tm_vpm )
#endif
{
typedef CGAL::Connected_component_graph<SourceMesh, FaceComponentMap> Adapter;
copy_face_graph(Adapter(sm, fccmap, pid), tm, v2v, h2h, f2f, sm_vpm, tm_vpm);
}
/*!
\ingroup PkgBGLHelperFct
copies the connected component containg `seed_face` of a source model of `FaceListGraph` into a target model of a
`FaceListGraph`. `OutputIterators` can be provided to produce a
mapping between source and target elements. The target graph is not
cleared.
\tparam SourceMesh a model of `FaceListGraph`.
The descriptor types `boost::graph_traits<SourceMesh>::%vertex_descriptor`
and `boost::graph_traits<SourceMesh>::%face_descriptor` must be
models of `Hashable`.
\tparam TargetMesh a model of `FaceListGraph`
\tparam NamedParameters a sequence of \ref namedparameters
\tparam V2V a model of `OutputIterator` accepting `std::pair<sm_vertex_descriptor, tm_vertex_descriptor>`
\tparam H2H a model of `OutputIterator` accepting `std::pair<sm_halfedge_descriptor, tm_halfedge_descriptor>`
\tparam F2F a model of `OutputIterator` accepting `std::pair<sm_face_descriptor, tm_face_descriptor>`
\tparam Src_vpm a model of `ReadablePropertyMap` with `sm_vertex_descriptor` as key
\tparam Tgt_vpm a model of `WritablePropertyMap` with `tm_vertex_descriptor` as key
where the prefix `sm_` and `tm_` mean belonging to the source and
target mesh respectively.
The types `sm_vertex_descriptor` and `sm_face_descriptor` must be models of the concept `Hashable`.
\param sm the source mesh
\param tm the target mesh
\param seed_face a face of `sm` belonging to the connected component to copy
\param np optional \ref namedparameters described below
*
* \cgalNamedParamsBegin
* \cgalParamBegin{edge_is_constrained_map} a property map containing the constrained-or-not status of each edge of `pmesh` \cgalParamEnd
* \cgalNamedParamsEnd
\param v2v pairs of `vertex_descriptors` from `sm` and corresponding `vertex_descriptors` in `tm` are added to `v2v`
\param h2h pairs of `halfedge_descriptors` from `sm` and corresponding `halfedge_descriptors` in `tm` are added to `h2h`
\param f2f pairs of `face_descriptors` from `sm` and corresponding `face_descriptors` in `tm` are added to `f2f`
\param sm_vpm vertex point map for `sm`
\param tm_vpm vertex point map for `tm`
The points from `sm` to `tm` are converted using
`CGAL::Cartesian_converter<SourceKernel, TargetKernel>`.
`SourceKernel` and `TargetKernel` are deduced using `CGAL::Kernel_traits`
from the value types of `Src_vpm` and `Tgt_vpm`.
Other properties are not copied.
*/
#if defined(DOXYGEN_RUNNING) // Use template default arguments
template <typename SourceMesh, typename TargetMesh,
typename NamedParameters,
typename V2V = Emptyset_iterator,
typename H2H = Emptyset_iterator,
typename F2F = Emptyset_iterator,
typename Src_vpm = typename boost::property_map<SourceMesh, vertex_point_t>::const_type,
typename Tgt_vpm = typename boost::property_map<TargetMesh, vertex_point_t>::type>
void copy_face_graph_patch(const SourceMesh& sm,
const typename boost::graph_traits<SourceMesh>::
face_descriptor& seed_face,
const NamedParameters& np = boost::parameter::all_default(),
TargetMesh& tm,
V2V v2v = V2V(), H2H h2h = H2H(), F2F f2f = F2F(),
Src_vpm sm_vpm = get(vertex_point, sm),
Tgt_vpm tm_vpm = get(vertex_point, tm) )
#else // use the overloads
template <typename SourceMesh, typename TargetMesh,
typename NamedParameters,
typename V2V,typename H2H, typename F2F,
typename Src_vpm, typename Tgt_vpm >
void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits<SourceMesh>::
face_descriptor& seed_face,
const NamedParameters& np, TargetMesh& tm, V2V v2v, H2H h2h, F2F f2f,
Src_vpm sm_vpm, Tgt_vpm tm_vpm )
#endif
{
typedef typename boost::graph_traits<SourceMesh>::face_descriptor g_face_descriptor;
typedef typename boost::graph_traits<SourceMesh>::faces_size_type faces_size_t;
typedef boost::associative_property_map< boost::unordered_map< g_face_descriptor, faces_size_t> >FCMap;
typedef CGAL::Connected_component_graph<SourceMesh, FCMap> Adapter;
boost::unordered_map<g_face_descriptor, faces_size_t> map(CGAL::num_faces(sm));
Polygon_mesh_processing::connected_components(sm, boost::make_assoc_property_map(map), np);
copy_face_graph(Adapter(sm, boost::make_assoc_property_map(map), map[seed_face]), tm, v2v, h2h, f2f, sm_vpm, tm_vpm);
}
#if !defined(DOXYGEN_RUNNING)
template <typename SourceMesh, typename FaceComponentMap, typename TargetMesh>
void copy_face_graph_patch(const SourceMesh& sm, FaceComponentMap fccmap, typename boost::graph_traits<SourceMesh>::faces_size_type pid, TargetMesh& tm)
{ copy_face_graph_patch(sm, fccmap, pid, tm, Emptyset_iterator(), Emptyset_iterator(), Emptyset_iterator(),
get(vertex_point, sm), get(vertex_point, tm)); }
template <typename SourceMesh, typename FaceComponentMap, typename TargetMesh, typename V2V>
void copy_face_graph_patch(const SourceMesh& sm, FaceComponentMap fccmap, typename boost::graph_traits<SourceMesh>::faces_size_type pid, TargetMesh& tm, V2V v2v)
{ copy_face_graph_patch(sm, fccmap, pid, tm, v2v, Emptyset_iterator(), Emptyset_iterator(),
get(vertex_point, sm), get(vertex_point, tm)); }
template <typename SourceMesh, typename FaceComponentMap, typename TargetMesh, typename V2V, typename H2H>
void copy_face_graph_patch(const SourceMesh& sm, FaceComponentMap fccmap, typename boost::graph_traits<SourceMesh>::faces_size_type pid, TargetMesh& tm, V2V v2v, H2H h2h)
{ copy_face_graph_patch(sm, fccmap, pid, tm, v2v, h2h, Emptyset_iterator(),
get(vertex_point, sm), get(vertex_point, tm)); }
template <typename SourceMesh, typename FaceComponentMap, typename TargetMesh, typename V2V, typename H2H, typename F2F>
void copy_face_graph_patch(const SourceMesh& sm, FaceComponentMap fccmap, typename boost::graph_traits<SourceMesh>::faces_size_type pid, TargetMesh& tm, V2V v2v, H2H h2h, F2F f2f)
{ copy_face_graph_patch(sm, fccmap, pid, tm, v2v, h2h, f2f,
get(vertex_point, sm), get(vertex_point, tm)); }
template <typename SourceMesh, typename FaceComponentMap, typename TargetMesh, typename V2V, typename H2H, typename F2F, typename Src_vpm>
void copy_face_graph_patch(const SourceMesh& sm, FaceComponentMap fccmap, typename boost::graph_traits<SourceMesh>::faces_size_type pid, TargetMesh& tm, V2V v2v, H2H h2h, F2F f2f, Src_vpm sm_vpm)
{ copy_face_graph_patch(sm, fccmap, pid, tm, v2v, h2h, f2f,
sm_vpm, get(vertex_point, tm)); }
template <typename SourceMesh, typename TargetMesh>
void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits<SourceMesh>::
face_descriptor& seed_face, TargetMesh& tm)
{ copy_face_graph_patch(sm, seed_face, Polygon_mesh_processing::parameters::all_default(), tm, Emptyset_iterator(), Emptyset_iterator(), Emptyset_iterator(),
get(vertex_point, sm), get(vertex_point, tm)); }
template <typename SourceMesh, typename NamedParameters, typename TargetMesh>
void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits<SourceMesh>::
face_descriptor& seed_face,
const NamedParameters& np, TargetMesh& tm)
{ copy_face_graph_patch(sm, seed_face, np, tm, Emptyset_iterator(), Emptyset_iterator(), Emptyset_iterator(),
get(vertex_point, sm), get(vertex_point, tm)); }
template <typename SourceMesh, typename NamedParameters, typename TargetMesh, typename V2V>
void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits<SourceMesh>::
face_descriptor& seed_face,
const NamedParameters& np, TargetMesh& tm, V2V v2v)
{ copy_face_graph_patch(sm, seed_face, np, tm, v2v, Emptyset_iterator(), Emptyset_iterator(),
get(vertex_point, sm), get(vertex_point, tm)); }
template <typename SourceMesh, typename NamedParameters, typename TargetMesh, typename V2V, typename H2H>
void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits<SourceMesh>::
face_descriptor& seed_face,
const NamedParameters& np, TargetMesh& tm, V2V v2v, H2H h2h)
{ copy_face_graph_patch(sm, seed_face, np, tm, v2v, h2h, Emptyset_iterator(),
get(vertex_point, sm), get(vertex_point, tm)); }
template <typename SourceMesh, typename NamedParameters, typename TargetMesh, typename V2V, typename H2H, typename F2F>
void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits<SourceMesh>::
face_descriptor& seed_face,
const NamedParameters& np, TargetMesh& tm, V2V v2v, H2H h2h, F2F f2f)
{ copy_face_graph_patch(sm, seed_face, np, tm, v2v, h2h, f2f,
get(vertex_point, sm), get(vertex_point, tm)); }
template <typename SourceMesh, typename NamedParameters, typename TargetMesh, typename V2V, typename H2H, typename F2F, typename Src_vpm>
void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits<SourceMesh>::
face_descriptor& seed_face,
const NamedParameters& np, TargetMesh& tm, V2V v2v, H2H h2h, F2F f2f, Src_vpm sm_vpm)
{ copy_face_graph_patch(sm, seed_face, np, tm, v2v, h2h, f2f,
sm_vpm, get(vertex_point, tm)); }
#endif
}//end CGAL
#endif // CGAL_BOOST_GRAPH_COPY_FACE_GRAPH_PATCH_H

View File

@ -340,6 +340,16 @@ struct Constraint : public boost::put_get_helper<bool,Constraint<VertexPointPMap
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
@ -355,8 +365,8 @@ int
main()
{
typedef CGAL::Connected_component_graph<SM, SM::Property_map<boost::graph_traits<SM>::face_descriptor , std::size_t> > Adapter;
test(sm_data());
//Make a tetrahedron and test the adapter for a patch that only contains the front face
// test(sm_data());
//Make a tetrahedron and test the adapter for a patch that only contains 2 faces
SM* sm = new SM();
CGAL::make_tetrahedron(
Point_3(1,1,1),
@ -371,17 +381,19 @@ main()
CGAL::Polygon_mesh_processing::connected_components(*sm, fccmap, CGAL::Polygon_mesh_processing::parameters::
edge_is_constrained_map(Constraint<CGAL::Properties::Property_map<boost::graph_traits<SM>::vertex_descriptor,
SM::Point> >(*sm, positions)));
Adapter fga(*sm, fccmap, boost::get(fccmap, *faces(*sm).first));
boost::unordered_set<long unsigned int> pids;
pids.insert(0);
pids.insert(2);
Adapter fga(*sm, fccmap, pids);
CGAL_GRAPH_TRAITS_MEMBERS(Adapter);
//check that there is the right number of simplices in fga
CGAL_assertion(CGAL::is_valid(fga));
CGAL_assertion(std::distance(faces(fga).first,faces(fga).second) == 1);
CGAL_assertion(std::distance(edges(fga).first,edges(fga).second) == 3);
CGAL_assertion(std::distance(halfedges(fga).first,halfedges(fga).second) == 6);
CGAL_assertion(std::distance(vertices(fga).first,vertices(fga).second) == 3);
CGAL_assertion(std::distance(faces(fga).first,faces(fga).second) == 2);
CGAL_assertion(std::distance(edges(fga).first,edges(fga).second) == 5);
CGAL_assertion(std::distance(halfedges(fga).first,halfedges(fga).second) == 10);
CGAL_assertion(std::distance(vertices(fga).first,vertices(fga).second) == 4);
halfedge_descriptor h = halfedge(*faces(fga).first, fga);
vertex_descriptor v = target(h, fga);
vertex_descriptor v = source(h, fga);
//check that next() works inside the patch
CGAL_assertion(
next(next(next(h, fga), fga), fga) == h
@ -389,7 +401,7 @@ main()
//check that next() works on bordure of the patch
h = opposite(h, fga);
CGAL_assertion(
next(next(next(h, fga), fga), fga) == h
next(next(next(next(h, fga), fga), fga), fga) == h
);
//check that prev() works inside the patch
h = halfedge(*faces(fga).first, fga);
@ -399,13 +411,13 @@ main()
//check that prev() works on bordure of the patch
h = opposite(h, fga);
CGAL_assertion(
prev(prev(prev(h, fga), fga), fga) == h
prev(prev(prev(prev(h, fga), fga), fga), fga) == h
);
//check degree
CGAL_assertion(degree(v, fga) == 2);
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) == 2 );
CGAL_assertion(std::distance(out_edges(v, fga).first ,out_edges(v, fga).second) == 2 );
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 );
return 0;
}