diff --git a/BGL/include/CGAL/boost/graph/Connected_component_graph.h b/BGL/include/CGAL/boost/graph/Connected_component_graph.h index 12e889c571f..9c4fd8aa77f 100644 --- a/BGL/include/CGAL/boost/graph/Connected_component_graph.h +++ b/BGL/include/CGAL/boost/graph/Connected_component_graph.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -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 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::value_type pid) - : _graph(graph), _property_map(fccmap), _patch_index(pid) + boost::unordered_set::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::value_type pid) + : _graph(graph), _property_map(fccmap) + { + _patch_indices = boost::unordered_set::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::value_type patch_index()const{ return _patch_index; } - - void change_patch_id(typename boost::property_traits::value_type pid) { _patch_index = pid;} + ///returns the unordered set of patch ids of the Connected_component_graph. + boost::unordered_set::value_type> patch_indices()const{ return _patch_indices; } + /// Replaces the current unordered set of patches by `pids` + void change_patch_id(boost::unordered_set::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::value_type _patch_index; + boost::unordered_set::value_type> _patch_indices; }; } // namespace CGAL @@ -171,7 +192,7 @@ bool in_CC(const typename boost::graph_traits< Connected_component_graph >::face_descriptor f, const Connected_component_graph & 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 diff --git a/BGL/include/CGAL/boost/graph/copy_face_graph_patch.h b/BGL/include/CGAL/boost/graph/copy_face_graph_patch.h deleted file mode 100644 index fe0c808d356..00000000000 --- a/BGL/include/CGAL/boost/graph/copy_face_graph_patch.h +++ /dev/null @@ -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 -#include -#include -#include - -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::%vertex_descriptor` - and `boost::graph_traits::%face_descriptor` must be - models of `Hashable`. - \tparam TargetMesh a model of `FaceListGraph` - \tparam FaceComponentMap a model of `WritablePropertyMap` with - `boost::graph_traits::%face_descriptor` as key type and - `graph_traits::faces_size_type` as value type. - \tparam V2V a model of `OutputIterator` accepting `std::pair` - \tparam H2H a model of `OutputIterator` accepting `std::pair` - \tparam F2F a model of `OutputIterator` accepting `std::pair` - \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` 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 ::const_type, - typename Tgt_vpm = typename boost::property_map::type> -void copy_face_graph_patch(const SourceMesh& sm, - FaceComponentMap fccmap, - typename boost::graph_traits::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 -void copy_face_graph_patch(const SourceMesh& sm, FaceComponentMap fccmap, typename boost::graph_traits::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 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::%vertex_descriptor` - and `boost::graph_traits::%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` - \tparam H2H a model of `OutputIterator` accepting `std::pair` - \tparam F2F a model of `OutputIterator` accepting `std::pair` - \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` 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 ::const_type, - typename Tgt_vpm = typename boost::property_map::type> -void copy_face_graph_patch(const SourceMesh& sm, - const typename boost::graph_traits:: - 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 -void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits:: - 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::face_descriptor g_face_descriptor; - typedef typename boost::graph_traits::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 Adapter; - - boost::unordered_map 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 -void copy_face_graph_patch(const SourceMesh& sm, FaceComponentMap fccmap, typename boost::graph_traits::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 -void copy_face_graph_patch(const SourceMesh& sm, FaceComponentMap fccmap, typename boost::graph_traits::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 -void copy_face_graph_patch(const SourceMesh& sm, FaceComponentMap fccmap, typename boost::graph_traits::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 -void copy_face_graph_patch(const SourceMesh& sm, FaceComponentMap fccmap, typename boost::graph_traits::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 -void copy_face_graph_patch(const SourceMesh& sm, FaceComponentMap fccmap, typename boost::graph_traits::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 -void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits:: - 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 -void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits:: - 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 -void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits:: - 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 -void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits:: - 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 -void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits:: - 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 -void copy_face_graph_patch(const SourceMesh& sm, const typename boost::graph_traits:: - 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 diff --git a/BGL/test/BGL/test_Connected_component_graph.cpp b/BGL/test/BGL/test_Connected_component_graph.cpp index fb8b0d7db11..e69cfaaaff7 100644 --- a/BGL/test/BGL/test_Connected_component_graph.cpp +++ b/BGL/test/BGL/test_Connected_component_graph.cpp @@ -340,6 +340,16 @@ struct Constraint : public boost::put_get_helper::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::vertex_descriptor, SM::Point> >(*sm, positions))); - - Adapter fga(*sm, fccmap, boost::get(fccmap, *faces(*sm).first)); + boost::unordered_set 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; }