diff --git a/BGL/doc/BGL/BGL.txt b/BGL/doc/BGL/BGL.txt index b31a570ee71..ca164170b6c 100644 --- a/BGL/doc/BGL/BGL.txt +++ b/BGL/doc/BGL/BGL.txt @@ -634,6 +634,12 @@ Seam meshes are for example used in Chapter \ref PkgSurfaceMeshParameterization to parameterize a topological sphere by first virtually cutting it into a topological disk. +\subsection BGLInheriting Inheriting from a Model of a Face Graph Concept +In order for a type `FG` to be a model of one of the face graph concepts, a specialization of +`boost::graph_traits` must exist. When you derive a class from `FG` this graph traits class specialization does not match. +For such cases, a header file consuming some user defined macros is provided to make the derived class a valid model +of the same concept. See `CGAL/boost/graph/graph_traits_inheritance_macros.h` for more details. + \section BGLPartitioning Graph Partitioning For algorithms that operate locally, partitioning is often an easy way to parallelize diff --git a/BGL/doc/BGL/Doxyfile.in b/BGL/doc/BGL/Doxyfile.in index 8d9f34127c0..6fd75dba201 100644 --- a/BGL/doc/BGL/Doxyfile.in +++ b/BGL/doc/BGL/Doxyfile.in @@ -16,13 +16,16 @@ INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Euler_operations.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/partition.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_graph.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_dual_graph.h \ - ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/alpha_expansion_graphcut.h + ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/alpha_expansion_graphcut.h \ + ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/graph_traits_inheritance_macros.h EXAMPLE_PATH = ${CGAL_Surface_mesh_skeletonization_EXAMPLE_DIR} \ ${CGAL_Surface_mesh_segmentation_EXAMPLE_DIR} \ ${CGAL_Polygon_mesh_processing_EXAMPLE_DIR} \ + ${CGAL_Surface_mesh_EXAMPLE_DIR} \ ${CGAL_Property_map_EXAMPLE_DIR} \ + ${CGAL_Polyhedron_EXAMPLE_DIR} \ ${CGAL_BGL_EXAMPLE_DIR} ALIASES += "bgllink{1}=\1" diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index 8e9032f8c07..6057bada0c6 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -713,6 +713,7 @@ user might encounter. - `CGAL::Graph_with_descriptor_with_graph` - `CGAL::Graph_with_descriptor_with_graph_property_map` - `CGAL::Seam_mesh` +- `CGAL/boost/graph/graph_traits_inheritance_macros.h` \cgalCRPSection{Partitioning Methods} - `CGAL::METIS::partition_graph()` diff --git a/BGL/doc/BGL/examples.txt b/BGL/doc/BGL/examples.txt index dd1d623ab0a..05a8063563c 100644 --- a/BGL/doc/BGL/examples.txt +++ b/BGL/doc/BGL/examples.txt @@ -31,4 +31,6 @@ \example Surface_mesh_segmentation/extract_segmentation_into_mesh_example.cpp \example Polygon_mesh_processing/face_filtered_graph_example.cpp \example Property_map/dynamic_properties.cpp +\example Surface_mesh/sm_derivation.cpp +\example Polyhedron/poly_derivation.cpp */ diff --git a/BGL/include/CGAL/boost/graph/graph_traits_inheritance_macros.h b/BGL/include/CGAL/boost/graph/graph_traits_inheritance_macros.h new file mode 100644 index 00000000000..12faf7e2a0c --- /dev/null +++ b/BGL/include/CGAL/boost/graph/graph_traits_inheritance_macros.h @@ -0,0 +1,171 @@ +// Copyright (c) 2020 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Sébastien Loriot + +// This file is intentionally not protected against re-inclusion. +// It's aimed at being included from within a user code to +// make any structure inheriting from a face graph model a face graph +// model itself + +// It is the responsibility of the including file to correctly set the +// macros CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME, CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME +// and optionally CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS. +// They are #undefed at the end of this file. + +/** +* \ingroup PkgBGLRef +* \file CGAL/boost/graph/graph_traits_inheritance_macros.h +* Convenience header file defining the necessary specializations and overloads to make a +* class, inheriting from a model of a face graph concept, a model of that face graph concept itself. +* Prior to the inclusion of this header, specific macros must be defined and those macros will be +* undefined automatically when processing to the inclusion of this header. +* It is possible to include the header several times if the operation must be done for several classes. +* The macros that must be defined are the following: +* - `CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME`: the inheriting class. If it is a template class, it must be instantiated parameters named as in `CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS` or parameters available in the scope including the header; +* - `CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME`: the base class. it must be instantiated parameters named as in `CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS` or parameters available in the scope including the header; +* - `CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS`: (optional) if the inheriting class, a list of template parameters separated by commas (`,`) including `class/typename/integral type`. +* +* Some examples are provided in \ref Surface_mesh/sm_derivation.cpp and \ref Polyhedron/poly_derivation.cpp. +* +*/ + +#include + +#if !defined(CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME) || !defined(CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME) + +CGAL_pragma_warning("\nBoth macros CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME and CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME " + "must be defined if you want to use this file\n") + +#else + +#ifdef CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS + +namespace boost { + +template +struct graph_traits : + public graph_traits +{}; + +template +struct property_map : + public property_map +{}; + +} // boost namespace + +#define CGAL_PM_DT_SPEC(DTAG) \ +namespace boost {\ +template \ +struct property_map > \ + : property_map > \ +{};\ +} /* boost namespace */\ +\ +namespace CGAL { \ +template \ +typename boost::property_map >::type \ +get(DTAG t, CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME& g) \ +{ \ + return get(t, static_cast(g)); \ +} \ +\ +template \ +typename boost::property_map >::const_type \ +get(DTAG t, const CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME& g) \ +{ \ + return get(t, static_cast(g)); \ +}\ +} //CGAL namespace + +CGAL_PM_DT_SPEC(CGAL::dynamic_vertex_property_t) +CGAL_PM_DT_SPEC(CGAL::dynamic_halfedge_property_t) +CGAL_PM_DT_SPEC(CGAL::dynamic_face_property_t) +CGAL_PM_DT_SPEC(CGAL::dynamic_edge_property_t) + +#undef CGAL_PM_DT_SPEC + +namespace CGAL { + +template +struct graph_has_property : + public CGAL::graph_has_property +{}; + + +} // CGAL namespace + +#undef CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS + +#else + +namespace boost { + +template <> +struct graph_traits : + public graph_traits +{}; + +template +struct property_map : + public property_map +{}; + +} // boost namespace + +#define CGAL_PM_DT_SPEC(DTAG) \ +namespace boost {\ +template \ +struct property_map > \ + : property_map > \ +{};\ +} /* boost namespace */\ +\ +namespace CGAL { \ +template \ +typename boost::property_map >::type \ +get(DTAG t, CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME& g) \ +{ \ + return get(t, static_cast(g)); \ +} \ +\ +template \ +typename boost::property_map >::const_type \ +get(DTAG t, const CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME& g) \ +{ \ + return get(t, static_cast(g)); \ +}\ +} //CGAL namespace + +CGAL_PM_DT_SPEC(CGAL::dynamic_vertex_property_t) +CGAL_PM_DT_SPEC(CGAL::dynamic_halfedge_property_t) +CGAL_PM_DT_SPEC(CGAL::dynamic_face_property_t) +CGAL_PM_DT_SPEC(CGAL::dynamic_edge_property_t) + +#undef CGAL_PM_DT_SPEC + +namespace CGAL { + +template +struct graph_has_property : + public CGAL::graph_has_property +{}; + + +} // CGAL namespace + +#endif + + +#undef CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME +#undef CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME + +#endif + diff --git a/BGL/test/BGL/CMakeLists.txt b/BGL/test/BGL/CMakeLists.txt index 2f9e1bb404e..875cf10fd5d 100644 --- a/BGL/test/BGL/CMakeLists.txt +++ b/BGL/test/BGL/CMakeLists.txt @@ -71,6 +71,8 @@ create_single_source_cgal_program( "graph_concept_Linear_cell_complex.cpp" ) create_single_source_cgal_program( "graph_concept_Arrangement_2.cpp" ) +create_single_source_cgal_program( "graph_concept_Derived.cpp" ) + create_single_source_cgal_program( "test_clear.cpp" ) create_single_source_cgal_program( "test_helpers.cpp" ) @@ -103,6 +105,8 @@ create_single_source_cgal_program( "test_wrl.cpp" ) create_single_source_cgal_program( "bench_read_from_stream_vs_add_face_and_add_faces.cpp" ) +create_single_source_cgal_program( "graph_traits_inheritance.cpp" ) + if(OpenMesh_FOUND) target_link_libraries( test_clear PRIVATE ${OPENMESH_LIBRARIES}) target_link_libraries( test_Euler_operations PRIVATE ${OPENMESH_LIBRARIES}) diff --git a/BGL/test/BGL/graph_concept_Derived.cpp b/BGL/test/BGL/graph_concept_Derived.cpp new file mode 100644 index 00000000000..f28fc180a48 --- /dev/null +++ b/BGL/test/BGL/graph_concept_Derived.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include + +#include +#include + + +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_3 Point_3; + +template +struct My_mesh_1 : public CGAL::Polyhedron_3 {}; + +struct My_mesh_2 : public CGAL::Polyhedron_3 {}; + +template +struct My_mesh_3 : public CGAL::Surface_mesh {}; + +struct My_mesh_5 : public CGAL::Surface_mesh {}; + +// dim could be hard-coded but for the purpose of the example it is left +template +struct My_mesh_4 : + CGAL::Linear_cell_complex_for_bgl_combinatorial_map_helper + <2, dim, CGAL::Linear_cell_complex_traits >::type +{}; + +/// make My_mesh_1 a valid face graph model +#define CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS typename Traits +#define CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME My_mesh_1 +#define CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME CGAL::Polyhedron_3 +#include + +/// make My_mesh_2 a valid face graph model +// no template parameter, CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS is then not defined +#define CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME My_mesh_2 +#define CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME CGAL::Polyhedron_3 +#include + +/// make My_mesh_3 a valid face graph model +#define CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS typename PT +#define CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME My_mesh_3 +#define CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME CGAL::Surface_mesh +#include + +/// make My_mesh_4 a valid face graph model +#define CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS int dim, typename K +#define CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME My_mesh_4 +#define CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME typename CGAL::Linear_cell_complex_for_bgl_combinatorial_map_helper\ + <2, dim, CGAL::Linear_cell_complex_traits >::type +#include + +/// make My_mesh_5 a valid face graph model +// no template parameter, CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS is then not defined +#define CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME My_mesh_5 +#define CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME CGAL::Surface_mesh +#include + + +template +void concept_check() +{ + typedef boost::graph_traits< Graph > Traits; + typedef typename Traits::edge_descriptor edge_descriptor; + typedef typename Traits::halfedge_descriptor halfedge_descriptor; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::face_descriptor face_descriptor; + + boost::function_requires< boost::GraphConcept >(); + boost::function_requires< boost::VertexListGraphConcept >(); + boost::function_requires< boost::EdgeListGraphConcept >(); + boost::function_requires< boost::IncidenceGraphConcept >(); + boost::function_requires< boost::AdjacencyMatrixConcept >(); + boost::function_requires< boost::BidirectionalGraphConcept >(); + boost::function_requires< CGAL::HalfedgeGraphConcept >(); + boost::function_requires< CGAL::HalfedgeListGraphConcept >(); + boost::function_requires< CGAL::FaceGraphConcept >(); + boost::function_requires< CGAL::FaceListGraphConcept >(); + boost::function_requires< CGAL::MutableHalfedgeGraphConcept >(); + boost::function_requires< CGAL::MutableFaceGraphConcept >(); + + boost::function_requires< boost::concepts::ReadablePropertyGraph< + Graph, halfedge_descriptor, CGAL::halfedge_index_t> >(); + boost::function_requires< boost::concepts::ReadablePropertyGraph< + Graph, edge_descriptor, boost::edge_index_t> >(); + boost::function_requires< boost::concepts::ReadablePropertyGraph< + Graph, edge_descriptor, boost::edge_weight_t> >(); + boost::function_requires< boost::concepts::PropertyGraph< + Graph, vertex_descriptor, CGAL::vertex_point_t> >(); + boost::function_requires< boost::concepts::ReadablePropertyGraph< + Graph, vertex_descriptor, boost::vertex_index_t> >(); + boost::function_requires< boost::concepts::ReadablePropertyGraph< + Graph, face_descriptor, CGAL::face_index_t> >(); + + // null + boost::graph_traits::null_vertex(); + boost::graph_traits::null_halfedge(); + boost::graph_traits::null_face(); +} + +int main() +{ + concept_check>(); + concept_check(); + concept_check >(); + concept_check>(); + concept_check(); + return 0; +} diff --git a/BGL/test/BGL/graph_traits_inheritance.cpp b/BGL/test/BGL/graph_traits_inheritance.cpp new file mode 100644 index 00000000000..fd4540af69e --- /dev/null +++ b/BGL/test/BGL/graph_traits_inheritance.cpp @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + +template +struct My_mesh_1 : public CGAL::Polyhedron_3 {}; + +struct My_mesh_2 : public CGAL::Polyhedron_3 {}; + +template +struct My_mesh_3 : public CGAL::Surface_mesh {}; + +struct My_mesh_5 : public CGAL::Surface_mesh {}; + +// dim could be hard-coded but for the purpose of the example it is left +template +struct My_mesh_4 : + CGAL::Linear_cell_complex_for_bgl_combinatorial_map_helper + <2, dim, CGAL::Linear_cell_complex_traits >::type +{}; + +/// make My_mesh_1 a valid face graph model +#define CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS typename Traits +#define CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME My_mesh_1 +#define CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME CGAL::Polyhedron_3 +#include + +/// make My_mesh_2 a valid face graph model +// no template parameter, CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS is then not defined +#define CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME My_mesh_2 +#define CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME CGAL::Polyhedron_3 +#include + +/// make My_mesh_3 a valid face graph model +#define CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS typename PT +#define CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME My_mesh_3 +#define CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME CGAL::Surface_mesh +#include + +/// make My_mesh_4 a valid face graph model +#define CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS int dim, typename K +#define CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME My_mesh_4 +#define CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME typename CGAL::Linear_cell_complex_for_bgl_combinatorial_map_helper\ + <2, dim, CGAL::Linear_cell_complex_traits >::type +#include + +/// make My_mesh_5 a valid face graph model +// no template parameter, CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS is then not defined +#define CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME My_mesh_5 +#define CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME CGAL::Surface_mesh +#include + +int main() +{ + typedef My_mesh_1 Mesh1; + + std::vector points; + Mesh1 poly1; + CGAL::convex_hull_3(points.begin(), points.end(), poly1); + + My_mesh_2 poly2; + CGAL::convex_hull_3(points.begin(), points.end(), poly2); + + My_mesh_3 poly3; + CGAL::convex_hull_3(points.begin(), points.end(), poly3); + + My_mesh_4<3, Kernel> poly4; + CGAL::convex_hull_3(points.begin(), points.end(), poly4); + + My_mesh_5 poly5; + CGAL::convex_hull_3(points.begin(), points.end(), poly5); + + return 0; +} diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index bdb01e6b8b4..3097856f4be 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -1,6 +1,12 @@ Release History =============== +### [CGAL and the Boost Graph Library (BGL)](https://doc.cgal.org/5.1/Manual/packages.html#PkgBGL) + +- Added the convenience header `CGAL/boost/graph/graph_traits_inheritance_macros.h` that allows to easily + make any class inheriting from a model of a face graph concept, a model of the same concept. + + [Release 5.1](https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.1) ----------- diff --git a/Polyhedron/examples/Polyhedron/poly_derivation.cpp b/Polyhedron/examples/Polyhedron/poly_derivation.cpp new file mode 100644 index 00000000000..30392f83af6 --- /dev/null +++ b/Polyhedron/examples/Polyhedron/poly_derivation.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include + + +template +struct Mesh: public CGAL::Polyhedron_3 { + std::string name; +}; + +#define CGAL_GRAPH_TRAITS_INHERITANCE_TEMPLATE_PARAMS typename Traits +#define CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME Mesh +#define CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME CGAL::Polyhedron_3 +#include + +typedef CGAL::Simple_cartesian K; +typedef K::Point_3 Point_3; + +int main() +{ + Mesh mesh; + CGAL::make_triangle(Point_3(0,0,0), Point_3(1,0,0), Point_3(1,1,1), mesh); + typedef boost::graph_traits>::vertex_descriptor vertex_descriptor; + + typedef boost::property_map,CGAL::vertex_point_t>::type Point_property_map; + Point_property_map ppm = get(CGAL::vertex_point, mesh); + + for(vertex_descriptor vd : vertices(mesh)){ + if (vd != boost::graph_traits>::null_vertex()){ + std::cout << get(ppm, vd) << std::endl; + } + } + std::cout << CGAL::Polygon_mesh_processing::bbox(mesh) << std::endl; + + return 0; +} + + + + + diff --git a/Surface_mesh/examples/Surface_mesh/sm_derivation.cpp b/Surface_mesh/examples/Surface_mesh/sm_derivation.cpp index 3589b291eab..cde991d63c7 100644 --- a/Surface_mesh/examples/Surface_mesh/sm_derivation.cpp +++ b/Surface_mesh/examples/Surface_mesh/sm_derivation.cpp @@ -16,26 +16,9 @@ namespace My { } // namespace My -namespace boost { - - template <> - struct graph_traits - : public boost::graph_traits - {}; - - template - struct property_map - : public boost::property_map - {}; - -} - -namespace CGAL{ - template - struct graph_has_property - : public CGAL::graph_has_property - {}; -} +#define CGAL_GRAPH_TRAITS_INHERITANCE_CLASS_NAME My::Mesh +#define CGAL_GRAPH_TRAITS_INHERITANCE_BASE_CLASS_NAME CGAL::Surface_mesh<::Point_3> +#include int main() {