Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalize documentation of Face_filtered_graph #7595

Merged
merged 6 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 45 additions & 45 deletions BGL/include/CGAL/boost/graph/Face_filtered_graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ namespace CGAL {
* the adapted graph must define a manifold mesh. In order to check that this condition is verified, you can
* use the function `is_selection_valid()`.
*
* There are two different ways to initialize this class. You can directly provide the set of faces selected, or
* if you have a face patch map, select the patches of faces. The latter option is convenient if you want to access
* some connected components of a graph after having called `CGAL::Polygon_mesh_processing::connected_components()`.
* There are two different ways to initialize this class: you can directly provide a set of selected faces,
* or provide a set of patch identifiers as well as a map between faces and patch identifiers.
* The latter option is convenient if you want to access some connected components of a graph
* after having called `CGAL::Polygon_mesh_processing::connected_components()`, or if you want
* to select only faces of a given color, for example.
*
* The documented interface of this class is limited on purpose and free functions of the concept
* this class is a model of must be used to manipulate it.
Expand Down Expand Up @@ -162,15 +164,14 @@ struct Face_filtered_graph
/*!
* \brief Constructor where the set of selected faces is specified as a range of patch ids.
*
* \tparam FacePatchIndexMap a model of `ReadablePropertyMap` with
`face_descriptor` as key type and
`graph_traits<Graph>::%faces_size_type` as value type.
* \tparam FacePatchIndexRange a model of `ConstRange` with `boost::property_traits<FacePatchIndexMap>::%value_type` as value type.
* \tparam FacePatchIDMap a model of `ReadablePropertyMap` with `face_descriptor` as key type
* and whose value type is a model of `Hashable`.
* \tparam FacePatchIDRange a model of `ConstRange` with `boost::property_traits<FacePatchIDMap>::%value_type` as value type.
* \tparam NamedParameters a sequence of named parameters
*
* \param graph the underlying graph
* \param face_patch_index_map the property map that assigns a patch index to each face
* \param selected_face_patch_indices a range of the face patch indices to select
* \param face_patch_id_map the property map that assigns a patch ID to each face
* \param selected_face_patch_ids a range of the face patch identifiers to select
* \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below
*
* \cgalNamedParamsBegin
Expand Down Expand Up @@ -208,14 +209,14 @@ struct Face_filtered_graph
* \cgalParamNEnd
* \cgalNamedParamsEnd
*/
template <typename FacePatchIndexMap, class FacePatchIndexRange, class CGAL_NP_TEMPLATE_PARAMETERS>
template <typename FacePatchIDMap, class FacePatchIDRange, class CGAL_NP_TEMPLATE_PARAMETERS>
Face_filtered_graph(const Graph& graph,
const FacePatchIndexRange& selected_face_patch_indices,
FacePatchIndexMap face_patch_index_map,
const FacePatchIDRange& selected_face_patch_ids,
FacePatchIDMap face_patch_id_map,
const CGAL_NP_CLASS& np
#ifndef DOXYGEN_RUNNING
, std::enable_if_t<
boost::has_range_const_iterator<FacePatchIndexRange>::value
boost::has_range_const_iterator<FacePatchIDRange>::value
>* = 0
#endif
)
Expand All @@ -224,35 +225,34 @@ struct Face_filtered_graph
vimap(CGAL::get_initialized_vertex_index_map(graph, np)),
himap(CGAL::get_initialized_halfedge_index_map(graph, np))
{
set_selected_faces(selected_face_patch_indices, face_patch_index_map);
set_selected_faces(selected_face_patch_ids, face_patch_id_map);
}

template <typename FacePatchIndexMap, class FacePatchIndexRange>
template <typename FacePatchIDMap, class FacePatchIDRange>
Face_filtered_graph(const Graph& graph,
const FacePatchIndexRange& selected_face_patch_indices,
FacePatchIndexMap face_patch_index_map
const FacePatchIDRange& selected_face_patch_ids,
FacePatchIDMap face_patch_id_map
, std::enable_if_t<
boost::has_range_const_iterator<FacePatchIndexRange>::value
boost::has_range_const_iterator<FacePatchIDRange>::value
>* = 0
)
: _graph(const_cast<Graph&>(graph)),
fimap(CGAL::get_initialized_face_index_map(graph)),
vimap(CGAL::get_initialized_vertex_index_map(graph)),
himap(CGAL::get_initialized_halfedge_index_map(graph))
{
set_selected_faces(selected_face_patch_indices, face_patch_index_map);
set_selected_faces(selected_face_patch_ids, face_patch_id_map);
}
/*!
* \brief Constructor where the set of selected faces is specified as a patch id.
*
* \tparam FacePatchIndexMap a model of `ReadablePropertyMap` with
`face_descriptor` as key type and
`graph_traits<Graph>::%faces_size_type` as value type.
* \tparam FacePatchIDMap a model of `ReadablePropertyMap` with `face_descriptor` as key type
* and whose value type is a model of `Hashable`.
* \tparam NamedParameters a sequence of named parameters
*
* \param graph the underlying graph.
* \param face_patch_index_map the property map that assigns a patch index to each face
* \param selected_face_patch_index the index of the face patch selected
* \param face_patch_id_map the property map that assigns a patch ID to each face
* \param selected_face_patch_id the identifier of the face patch selected
* \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below
*
* \cgalNamedParamsBegin
Expand Down Expand Up @@ -290,29 +290,29 @@ struct Face_filtered_graph
* \cgalParamNEnd
* \cgalNamedParamsEnd
*/
template <typename FacePatchIndexMap, class CGAL_NP_TEMPLATE_PARAMETERS>
template <typename FacePatchIDMap, class CGAL_NP_TEMPLATE_PARAMETERS>
Face_filtered_graph(const Graph& graph,
typename boost::property_traits<FacePatchIndexMap>::value_type selected_face_patch_index,
FacePatchIndexMap face_patch_index_map,
typename boost::property_traits<FacePatchIDMap>::value_type selected_face_patch_id,
FacePatchIDMap face_patch_id_map,
const CGAL_NP_CLASS& np)
: _graph(const_cast<Graph&>(graph)),
fimap(CGAL::get_initialized_face_index_map(graph, np)),
vimap(CGAL::get_initialized_vertex_index_map(graph, np)),
himap(CGAL::get_initialized_halfedge_index_map(graph, np))
{
set_selected_faces(selected_face_patch_index, face_patch_index_map);
set_selected_faces(selected_face_patch_id, face_patch_id_map);
}

template <typename FacePatchIndexMap>
template <typename FacePatchIDMap>
Face_filtered_graph(const Graph& graph,
typename boost::property_traits<FacePatchIndexMap>::value_type pid,
FacePatchIndexMap face_patch_index_map)
typename boost::property_traits<FacePatchIDMap>::value_type pid,
FacePatchIDMap face_patch_id_map)
: _graph(const_cast<Graph&>(graph)),
fimap(CGAL::get_initialized_face_index_map(graph)),
vimap(CGAL::get_initialized_vertex_index_map(graph)),
himap(CGAL::get_initialized_halfedge_index_map(graph))
{
set_selected_faces(pid, face_patch_index_map);
set_selected_faces(pid, face_patch_id_map);
}

/*!
Expand Down Expand Up @@ -438,9 +438,9 @@ struct Face_filtered_graph
}

/// changes the set of selected faces using a patch id.
template<class FacePatchIndexMap>
void set_selected_faces(typename boost::property_traits<FacePatchIndexMap>::value_type face_patch_id,
FacePatchIndexMap face_patch_index_map)
template<class FacePatchIDMap>
void set_selected_faces(typename boost::property_traits<FacePatchIDMap>::value_type face_patch_id,
FacePatchIDMap face_patch_id_map)
{
selected_faces.resize(num_faces(_graph));
selected_vertices.resize(num_vertices(_graph));
Expand All @@ -452,7 +452,7 @@ struct Face_filtered_graph

for(face_descriptor fd : faces(_graph) )
{
if(get(face_patch_index_map, fd) == face_patch_id)
if(get(face_patch_id_map, fd) == face_patch_id)
{
selected_faces.set(get(fimap, fd));
for(halfedge_descriptor hd : halfedges_around_face(halfedge(fd, _graph), _graph))
Expand All @@ -467,12 +467,12 @@ struct Face_filtered_graph
reset_indices();
}
/// changes the set of selected faces using a range of patch ids
template<class FacePatchIndexRange, class FacePatchIndexMap>
void set_selected_faces(const FacePatchIndexRange& selected_face_patch_indices,
FacePatchIndexMap face_patch_index_map
template<class FacePatchIDRange, class FacePatchIDMap>
void set_selected_faces(const FacePatchIDRange& selected_face_patch_ids,
FacePatchIDMap face_patch_id_map
#ifndef DOXYGEN_RUNNING
, std::enable_if_t<
boost::has_range_const_iterator<FacePatchIndexRange>::value
boost::has_range_const_iterator<FacePatchIDRange>::value
>* = 0
#endif
)
Expand All @@ -485,13 +485,13 @@ struct Face_filtered_graph
selected_vertices.reset();
selected_halfedges.reset();

typedef typename boost::property_traits<FacePatchIndexMap>::value_type Patch_index;
std::unordered_set<Patch_index> pids(std::begin(selected_face_patch_indices),
std::end(selected_face_patch_indices));
typedef typename boost::property_traits<FacePatchIDMap>::value_type Patch_ID;
std::unordered_set<Patch_ID> pids(std::begin(selected_face_patch_ids),
std::end(selected_face_patch_ids));

for(face_descriptor fd : faces(_graph) )
for(face_descriptor fd : faces(_graph))
{
if(pids.count(get(face_patch_index_map, fd)) != 0)
if(pids.count(get(face_patch_id_map, fd)) != 0)
{
selected_faces.set(get(fimap, fd));
for(halfedge_descriptor hd : halfedges_around_face(halfedge(fd, _graph), _graph))
Expand Down
70 changes: 54 additions & 16 deletions BGL/test/BGL/test_Face_filtered_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ typedef std::unordered_set<std::size_t> id_map;
namespace PMP = CGAL::Polygon_mesh_processing;

template <typename Graph>
void test_halfedge_around_vertex_iterator(const Graph& g)
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;
Expand Down Expand Up @@ -319,17 +319,42 @@ void test_index_property_maps(const Graph& g)
}

template<typename Graph>
void test_read(const Graph& g)
void test_constructors(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);

Adapter fg0(g);
Adapter fg1(g, CGAL::parameters::default_values());

std::map<g_face_descriptor, std::size_t> map;
PMP::connected_components(g, boost::make_assoc_property_map(map));
Adapter fg(g, 0, boost::make_assoc_property_map(map));
assert(fg.is_selection_valid());
assert(CGAL::is_valid_polygon_mesh(fg));

// patch ID type that is not a fundamental type
std::map<g_face_descriptor, CGAL::IO::Color> colors;
for(auto f : faces(fg))
colors[f] = CGAL::IO::blue();
auto color_map = boost::make_assoc_property_map(colors);
Adapter color_fg(g, CGAL::IO::blue(), color_map);
assert(color_fg.is_selection_valid());
assert(CGAL::is_valid_polygon_mesh(color_fg));
assert(num_faces(g) == num_faces(color_fg));

Adapter color_fg2(g, CGAL::IO::red(), color_map, CGAL::parameters::default_values());
assert(color_fg2.is_selection_valid());
assert(CGAL::is_valid_polygon_mesh(color_fg2));
assert(num_faces(color_fg2) == 0);

// range of non-fundamental ID types
std::vector<CGAL::IO::Color> selected_colors { CGAL::IO::blue(), CGAL::IO::red() };
Adapter color_fg3(g, selected_colors, color_map);
assert(color_fg3.is_selection_valid());
assert(CGAL::is_valid_polygon_mesh(color_fg3));
assert(num_faces(g) == num_faces(color_fg3));
}

template <typename Graph>
Expand All @@ -338,7 +363,7 @@ test_graph_range(const std::vector<Graph>& graphs)
{
for(Graph p : graphs)
{
test_read(p);
test_constructors(p);
test_vertex_iterators(p);
test_out_edges(p);
test_in_edges(p);
Expand Down Expand Up @@ -500,20 +525,8 @@ void test_invalid_selections()
assert(!many_umbrellas_fg.is_selection_valid());
}

int main()
void test_SM_tetrahedron()
{
test_graph_range(poly_data());

#ifdef CGAL_USE_SURFACE_MESH
test_graph_range(sm_data());
#endif

#ifdef CGAL_USE_OPENMESH
test_graph_range(omesh_data());
#endif

test_invalid_selections();

// 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;
Expand All @@ -531,7 +544,10 @@ int main()
pids.insert(2);
SM_Adapter sm_adapter(*sm, pids, fccmap);
test_mesh<SM,SM_FCCMap, SM_Adapter>(sm_adapter);
}

void test_Polyhedron_tetrahedron()
{
typedef boost::graph_traits<Polyhedron> PolyTraits;
typedef boost::property_map<Polyhedron, boost::vertex_point_t>::const_type VPMap;
typedef PolyTraits::face_descriptor poly_face_descriptor;
Expand All @@ -550,6 +566,9 @@ int main()
std::map<poly_face_descriptor, PolyTraits::faces_size_type> fc_map;
FCMap poly_fccmap(fc_map);

std::unordered_set<long unsigned int> pids;
pids.insert(0);
pids.insert(2);
VPMap vpmap = get(boost::vertex_point, *poly);
PMP::connected_components(*poly, poly_fccmap,
CGAL::parameters::edge_is_constrained_map(Constraint<Polyhedron, VPMap >(*poly, vpmap))
Expand All @@ -560,3 +579,22 @@ int main()
.halfedge_index_map(poly_himap));
test_mesh<Polyhedron, FCMap, Poly_Adapter>(poly_adapter);
}

int main(int, char**)
{
test_graph_range(poly_data());
#ifdef CGAL_USE_SURFACE_MESH
test_graph_range(sm_data());
#endif
#ifdef CGAL_USE_OPENMESH
test_graph_range(omesh_data());
#endif

test_invalid_selections();

test_SM_tetrahedron();
test_Polyhedron_tetrahedron();

std::cout << "Done" << std::endl;
return EXIT_SUCCESS;
}
24 changes: 20 additions & 4 deletions Stream_support/include/CGAL/IO/Color.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@

#include <CGAL/config.h>
#include <CGAL/array.h>

#include <boost/functional/hash.hpp>

#include <algorithm>
#include <cstdlib>
#include <cmath>



namespace CGAL {

namespace IO {
Expand Down Expand Up @@ -287,7 +288,6 @@ class Color
}

/// @}

};


Expand Down Expand Up @@ -375,6 +375,22 @@ using IO::white;
using IO::yellow;
#endif

} //namespace CGAL
} // namespace CGAL

namespace std {

template <>
struct hash<CGAL::IO::Color>
{
std::size_t operator()(const CGAL::IO::Color& c) const
{
std::size_t result = boost::hash_value(c[0]);
for(std::size_t i=1; i<4; ++i)
boost::hash_combine(result, c[i]);
return result;
}
};

} // namespace std

#endif // CGAL_COLOR_H