From d6bbf2bb5f7038bed51f973f554fc92ec52f9f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 4 Mar 2020 11:56:50 +0100 Subject: [PATCH] Fix implementation of initialized index map getters --- .../internal/initialized_index_maps_helpers.h | 318 ++++++++++++++++++ .../CGAL/boost/graph/named_params_helper.h | 201 +---------- BGL/include/CGAL/boost/graph/properties.h | 167 +-------- .../include/CGAL/Dynamic_property_map.h | 4 +- 4 files changed, 336 insertions(+), 354 deletions(-) create mode 100644 BGL/include/CGAL/boost/graph/internal/initialized_index_maps_helpers.h diff --git a/BGL/include/CGAL/boost/graph/internal/initialized_index_maps_helpers.h b/BGL/include/CGAL/boost/graph/internal/initialized_index_maps_helpers.h new file mode 100644 index 00000000000..e939a99e97b --- /dev/null +++ b/BGL/include/CGAL/boost/graph/internal/initialized_index_maps_helpers.h @@ -0,0 +1,318 @@ +// 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) : Mael Rouxel-Labbé +// Maxime Gimeno + +#ifndef CGAL_BOOST_GRAPH_INITIALIZED_INTERNAL_INDEX_MAPS_HELPERS +#define CGAL_BOOST_GRAPH_INITIALIZED_INTERNAL_INDEX_MAPS_HELPERS + +#include +#include +#include +#include +#include + +#include + +namespace CGAL { +namespace BGL { +namespace internal { + +// Check that an index map has been correctly initialized +template +bool is_index_map_valid(const IndexMap idmap, + const std::size_t num_simplices, + const DescriptorRange& range) +{ + typedef typename boost::property_traits::value_type Id_type; + + Id_type max_id = static_cast(num_simplices); + std::vector indices(max_id); + for(const auto& d : range) + { + const Id_type id = get(idmap, d); + if(id >= 0 && id < max_id && !indices[id]) + { + indices[id] = true; + } + else + { + std::cerr << "Invalid ID: " << id << " num_simplices: " << num_simplices << std::endl; + return false; + } + } + + return true; +} + +template +bool is_index_map_valid(const CGAL::internal_np::vertex_index_t, VertexIndexPropertyMap vertex_index_map, const Graph& g) +{ + return is_index_map_valid(vertex_index_map, num_vertices(g), vertices(g)); +} + +template +bool is_index_map_valid(const CGAL::internal_np::halfedge_index_t, HalfedgeIndexPropertyMap halfedge_index_map, const Graph& g) +{ + return is_index_map_valid(halfedge_index_map, num_halfedges(g), halfedges(g)); +} + +template +bool is_index_map_valid(const CGAL::internal_np::edge_index_t, EdgeIndexPropertyMap edge_index_map, const Graph& g) +{ + return is_index_map_valid(edge_index_map, num_edges(g), edges(g)); +} + +template +bool is_index_map_valid(const CGAL::internal_np::face_index_t, FaceIndexPropertyMap face_index_map, const Graph& g) +{ + return is_index_map_valid(face_index_map, num_faces(g), faces(g)); +} + +template +void initialize_index_map(const Parameter, IndexPropertyMap, const Graph&) +{ + // Unknown parameter; should never be here. + CGAL_assertion(false); +} + +template ::value> +struct Index_map_initializer +{ + void operator()(const CGAL::internal_np::vertex_index_t, IndexPropertyMap vertex_index_map, const Graph& g) + { + typename boost::property_traits::value_type i = 0; + for(typename boost::graph_traits::vertex_descriptor vd : vertices(g)) + put(vertex_index_map, vd, i++); + } + + void operator()(const CGAL::internal_np::halfedge_index_t, IndexPropertyMap halfedge_index_map, const Graph& g) + { + typename boost::property_traits::value_type i = 0; + for(typename boost::graph_traits::halfedge_descriptor hd : halfedges(g)) + put(halfedge_index_map, hd, i++); + } + + void operator()(const CGAL::internal_np::edge_index_t, IndexPropertyMap edge_index_map, const Graph& g) + { + typename boost::property_traits::value_type i = 0; + for(typename boost::graph_traits::edge_descriptor ed : edges(g)) + put(edge_index_map, ed, i++); + } + + void operator()(const CGAL::internal_np::face_index_t, IndexPropertyMap face_index_map, const Graph& g) + { + typename boost::property_traits::value_type i = 0; + for(typename boost::graph_traits::face_descriptor fd : faces(g)) + put(face_index_map, fd, i++); + } + + template + void operator()(const Parameter, IndexPropertyMap, const Graph&) + { + // Unknown parameter; should never be here. + CGAL_assertion(false); + } +}; + +template +struct Index_map_initializer +{ + template + void operator()(const Parameter, IndexPropertyMap, const Graph&) + { + // The property map is not writable; should never be here. + CGAL_assertion(false); + } +}; + +// Just for convenience, define the following functions: +// +// BGL::internal::initialize_vertex_index_map() +// BGL::internal::initialize_halfedge_index_map() +// BGL::internal::initialize_edge_index_map() +// BGL::internal::initialize_face_index_map() + +#define CGAL_DEF_INITIALIZE_ID_MAP_FUNCTION(TYPE) \ +template \ +void initialize_##TYPE##_index_map(WritableIndexPropertyMap index_map, \ + const Graph& g) \ +{ \ + Index_map_initializer initializer; \ + initializer(CGAL::internal_np::TYPE##_index_t(), index_map, g); \ +} + +CGAL_DEF_INITIALIZE_ID_MAP_FUNCTION(vertex) +CGAL_DEF_INITIALIZE_ID_MAP_FUNCTION(halfedge) +CGAL_DEF_INITIALIZE_ID_MAP_FUNCTION(edge) +CGAL_DEF_INITIALIZE_ID_MAP_FUNCTION(face) + +#undef CGAL_DEF_INITIALIZE_ID_FUCNTION + +// Using the pmap passed in named parameters +template +IndexMap get_initialized_index_map(const IndexMap index_map, + const Parameter p, Tag, DynamicTag, + const Graph& g) +{ + CGAL_USE(g); + CGAL_USE(p); + CGAL_assertion(is_index_map_valid(p, index_map, g)); + + return index_map; +} + +// Using the internal to the mesh +template +typename boost::property_map::const_type +get_initialized_index_map(CGAL::internal_np::Param_not_found, + const Parameter p, const Tag tag, DynamicTag, + const Graph& g) // @todo non-const +{ + typedef typename boost::property_map::const_type Index_map; + Index_map index_map = get(tag, g); + + if(CGAL::internal::Is_writable_property_map::value) + { + if(!is_index_map_valid(p, index_map, g)) + Index_map_initializer{}(p, index_map, g); + } + else // not writable + { + CGAL_assertion(is_index_map_valid(p, index_map, g)); + } + + return index_map; +} + +// Create a dynamic property and initialize it +template +typename boost::property_map::const_type +get_initialized_index_map(CGAL::internal_np::Param_not_found, + const Parameter p, const DynamicTag tag, DynamicTag, + const Graph& g) +{ + typedef typename boost::property_map::const_type Index_map; + + Index_map index_map = get(tag, g); + Index_map_initializer{}(p, index_map, g); + + return index_map; +} + +template > +class GetInitializedIndexMap +{ +public: + // Definition of the Tag that will be used if there is no named parameter + typedef typename boost::mpl::if_c< + CGAL::graph_has_property::value, Tag, DynamicTag>::type Final_tag; + + typedef typename internal_np::Lookup_named_param_def< + Parameter, + NamedParameters, + typename boost::property_map::type>::type type; + + typedef typename internal_np::Lookup_named_param_def< + Parameter, + NamedParameters, + typename boost::property_map::const_type>::type const_type; + + static const_type get(const Parameter p, const Graph& g, const NamedParameters& np) + { + return BGL::internal::get_initialized_index_map(parameters::get_parameter(np, p), + p, Final_tag(), DynamicTag(), g); + } + + static type get(const Parameter p, Graph& g, const NamedParameters& np) + { + return BGL::internal::get_initialized_index_map(parameters::get_parameter(np, p), + p, Final_tag(), DynamicTag(), g); + } +}; + +} // namespace internal +} // namespace BGL + +// @todo move below to named_params_... + +#define CGAL_DEF_GET_INDEX_TYPE(CTYPE, TYPE) \ +template > \ +struct GetInitialized##CTYPE##IndexMap \ + : public BGL::internal::GetInitializedIndexMap, \ + Graph, NamedParameters> \ +{ }; + +CGAL_DEF_GET_INDEX_TYPE(Vertex, vertex) +CGAL_DEF_GET_INDEX_TYPE(Halfedge, halfedge) +CGAL_DEF_GET_INDEX_TYPE(Edge, edge) +CGAL_DEF_GET_INDEX_TYPE(Face, face) + +#undef CGAL_DEF_GET_INDEX_TYPE + +// @todo move below to properties.h + +// Define the following functions: +// +// get_initialized_vertex_index_map(); +// get_initialized_halfedge_index_map(); +// get_initialized_edge_index_map(); +// get_initialized_face_index_map() +// +// The function returns: +// - the index property map passed in the NPs, if passed in the NPs; it must be initialized by the user; +// - the internal index property map if it is the graph has one. It is initialized if needed and possible; +// - an initialized dynamic pmap otherwise. + +#define CGAL_DEF_GET_INITIALIZED_INDEX_MAP(TYPE) \ +template \ +typename BGL::internal::GetInitializedIndexMap, \ + Graph, NamedParameters>::const_type \ +get_initialized_##TYPE##_index_map(const Graph& g, \ + const NamedParameters& np) \ +{ \ + typedef BGL::internal::GetInitializedIndexMap, \ + Graph, NamedParameters> Index_map_getter; \ + return Index_map_getter::get(CGAL::internal_np::TYPE##_index_t(), g, np); \ +} \ +template \ +typename BGL::internal::GetInitializedIndexMap, \ + Graph>::const_type \ +get_initialized_##TYPE##_index_map(const Graph& g) \ +{ \ + return get_initialized_##TYPE##_index_map(g, CGAL::parameters::all_default()); \ +} + +// @todo add the non-const Graph& version + +CGAL_DEF_GET_INITIALIZED_INDEX_MAP(vertex) +CGAL_DEF_GET_INITIALIZED_INDEX_MAP(halfedge) +CGAL_DEF_GET_INITIALIZED_INDEX_MAP(edge) +CGAL_DEF_GET_INITIALIZED_INDEX_MAP(face) + +#undef CGAL_DEF_GET_INITIALIZED_INDEX_MAP + +} // namespace CGAL + +#endif // CGAL_BOOST_GRAPH_INITIALIZED_INTERNAL_INDEX_MAPS_HELPERS diff --git a/BGL/include/CGAL/boost/graph/named_params_helper.h b/BGL/include/CGAL/boost/graph/named_params_helper.h index 6863ca4564b..68a79777a2d 100644 --- a/BGL/include/CGAL/boost/graph/named_params_helper.h +++ b/BGL/include/CGAL/boost/graph/named_params_helper.h @@ -19,17 +19,16 @@ #ifndef CGAL_BOOST_GRAPH_NAMED_PARAMETERS_HELPERS_H #define CGAL_BOOST_GRAPH_NAMED_PARAMETERS_HELPERS_H +#include #include - +#include +#include #include #include - #include -#include + #include #include -#include - #include #include @@ -106,7 +105,8 @@ namespace CGAL { property_map_selector pms; return pms.get_const_pmap(p, pmesh); } -// shortcut for accessing the value type of the property map + + // Shortcut for accessing the value type of the property map template class property_map_value { typedef typename boost::property_map::const_type PMap; @@ -114,195 +114,6 @@ namespace CGAL { typedef typename boost::property_traits::value_type type; }; - namespace internal_np - { - - //cases the map is writable for vertices - template< class PMap, class Graph> - void initialize_index_map(PMap map, const Graph& g, const boost::vertex_index_t&, const CGAL::Tag_true&) - { - CGAL::helpers::init_vertex_indices(g, map); - } - - template< class PMap, class Graph, typename T> - void initialize_index_map(PMap map, const Graph& g, const CGAL::dynamic_vertex_property_t&, const CGAL::Tag_true&) - { - CGAL::helpers::init_vertex_indices(g, map); - } - - //cases the map is writable for halfedges - template< class PMap, class Graph> - void initialize_index_map(PMap map, const Graph& g, const boost::halfedge_index_t&, const CGAL::Tag_true&) - { - CGAL::helpers::init_halfedge_indices(g, map); - } - - template< class PMap, class Graph, typename T> - void initialize_index_map(PMap map, const Graph& g, const CGAL::dynamic_halfedge_property_t&&, const CGAL::Tag_true&) - { - CGAL::helpers::init_halfedge_indices(g, map); - } - //cases the map is writable for faces - template< class PMap, class Graph> - void initialize_index_map(PMap map, const Graph& g, const boost::face_index_t&, const CGAL::Tag_true&) - { - CGAL::helpers::init_face_indices(g, map); - } - template< class PMap, class Graph, typename T> - void initialize_index_map(PMap map, const Graph& g, const CGAL::dynamic_face_property_t&, const CGAL::Tag_true&) - { - CGAL::helpers::init_face_indices(g, map); - } - - //default case : don't do anything - template - void initialize_index_map(PMap, const Graph&, const SimplexTag&, const IsWritableTag&) - {} - - -#define CGAL_IS_PMAP_WRITABLE(TAG) template \ - struct Is_pmap_writable{ typedef CGAL::Tag_true result; }; \ - template<> \ - struct Is_pmap_writable >{ typedef CGAL::Tag_false result; }; - - //Default is false - template - struct Is_pmap_writable{ - typedef CGAL::Tag_false result; - }; - - //Pmaps with these tags will be considered writable, unless their reference is const - CGAL_IS_PMAP_WRITABLE(boost::read_write_property_map_tag) - CGAL_IS_PMAP_WRITABLE(boost::writable_property_map_tag) - CGAL_IS_PMAP_WRITABLE(boost::lvalue_property_map_tag) -#undef CGAL_IS_PMAP_WRITABLE - - //overloads used to select a default map: - // use the one passed in the named parameters (user must have initialized it) - template - MapFromNP - get_ndi_map(MapFromNP m, Default_tag, Dynamic_tag, const Mesh&) - { - return m; - } - - // use the one internal to the mesh (it will be init if writable) - template - typename boost::property_map::const_type - get_ndi_map(CGAL::internal_np::Param_not_found, Default_tag t, Dynamic_tag , const Mesh& m) - { - typedef typename boost::property_map::const_type Map_const_type; - typedef typename boost::property_traits - - ::const_type>::category Category; - typedef typename boost::property_traits::reference Reference; - - Map_const_type map = get(t, m); - typename Is_pmap_writable >::result is_writable; - initialize_index_map(map, m, t,is_writable); - return map; - } - - // create a dynamic property and initialize it - template - typename boost::property_map::const_type - get_ndi_map(CGAL::internal_np::Param_not_found, Dynamic_tag t, Dynamic_tag , const Mesh& m) - { - typedef typename boost::property_map::const_type Map_const_type; - Map_const_type map = get(t,m); - initialize_index_map(map, m, t, CGAL::Tag_true()); - return map; - } - - }//end of internal_np - - //define types for maps : - //struct Default_face_index_map - //struct Default_vertex_index_map - //struct Default_halfedge_index_map -#define CGAL_DEF_MAP_TYPE(TYPE) \ - template \ - struct Default_##TYPE##_index_map{ \ - typedef typename boost::mpl::if_c< \ - CGAL::graph_has_property::value \ - , boost::TYPE##_index_t \ - , CGAL::dynamic_##TYPE##_property_t \ - >::type Final_tag; \ - typedef typename internal_np::Lookup_named_param_def< \ - internal_np::TYPE##_index_t, \ - NP, \ - typename boost::property_map::const_type \ - > ::type type; \ -}; - - CGAL_DEF_MAP_TYPE(face) - CGAL_DEF_MAP_TYPE(vertex) - CGAL_DEF_MAP_TYPE(halfedge) -#undef CGAL_DEF_MAP_TYPE - - - template - class Get_index_map_from_NP { - private : - const Dynamic_tag dtag; - const Mesh& m; - const NamedParameters& np; - const Parameter p; - - public: - //get the Default tag : - //if Mesh has an internal property map for Tag, use Tag, else use the Dynamic_tag. - typedef typename boost::mpl::if_c::value - , Tag, Dynamic_tag>::type Final_tag; - - //If Parameter is in NamedParameters, take the NP map. - //Else, take the default map. - typedef typename internal_np::Lookup_named_param_def< - Parameter, - NamedParameters, - typename boost::property_map::const_type - > ::type PropertyMapType; - - - Get_index_map_from_NP(const Tag, - const Dynamic_tag dtag, - const Mesh& m, - const NamedParameters& np, - const Parameter p) - : dtag(dtag), m(m), np(np), p(p) {} - - - PropertyMapType property_map() - { - return internal_np::get_ndi_map(parameters::get_parameter(np, p), - Final_tag(), dtag, m); - } - }; - - //define the - // get_initialized_face_index_map(), get_initialized_vertex_index_map(), get_initialized_halfedge_index_map() - // functions. - //This comment is here to make it easier to find the definition of the functions with a grep. - -#define CGAL_DEF_GET_INIT_ID_MAP(TYPE) template \ - typename Default_##TYPE##_index_map::type \ - get_initialized_##TYPE##_index_map(const PolygonMesh& pmesh, const NamedParameters& np){ \ - typedef Get_index_map_from_NP, \ - PolygonMesh, NamedParameters, internal_np::TYPE##_index_t> MapGetter; \ - MapGetter get_map(boost::TYPE##_index_t(), \ - CGAL::dynamic_##TYPE##_property_t(), \ - pmesh, np, internal_np::TYPE##_index); \ - return get_map.property_map(); \ - } - CGAL_DEF_GET_INIT_ID_MAP(face) - CGAL_DEF_GET_INIT_ID_MAP(vertex) - CGAL_DEF_GET_INIT_ID_MAP(halfedge) - -#undef CGAL_DEF_GET_INIT_ID_MAP - template > class GetVertexPointMap diff --git a/BGL/include/CGAL/boost/graph/properties.h b/BGL/include/CGAL/boost/graph/properties.h index fc3a315861c..1f28aac582d 100644 --- a/BGL/include/CGAL/boost/graph/properties.h +++ b/BGL/include/CGAL/boost/graph/properties.h @@ -14,15 +14,15 @@ #define CGAL_BOOST_GRAPH_BGL_PROPERTIES_H #include +#include +#include + #include #include -#include -#include -#include -#include #include #include +#include namespace CGAL { @@ -88,156 +88,7 @@ using boost::face_external_index_t; using boost::face_external_index; } // CGAL -namespace CGAL{ -namespace helpers { - -//check that an existing map is initialized/valid -template -bool is_index_map_valid( std::size_t num_simplices, - const SimplexRange& range, - const IndexMap& idmap) -{ - - typedef typename boost::property_traits::value_type Id_type; - Id_type max_id = static_cast(num_simplices); - std::vector indices(max_id); - for(const auto& simplex : range) - { - Id_type id = get(idmap, simplex); - if( id >= 0 && id < max_id && ! indices[id]) - indices[id] = true; - else - return false; - } - return true; -} - - -// matches read-write property maps -template -void init_face_indices(PolygonMesh& pm, - FaceIndexMap& fid, - boost::read_write_property_map_tag, - Tag) -{ - if(is_index_map_valid(num_faces(pm), faces(pm), fid)) - return; - typename boost::property_traits::value_type i = 0; - for(typename boost::graph_traits::face_descriptor fd : - faces(pm)) - { - put(fid, fd, i); - ++i; - } -} -template -void init_vertex_indices(PolygonMesh& pm, - VertexIndexMap& vid, - boost::read_write_property_map_tag, - Tag) -{ - if(is_index_map_valid(num_vertices(pm), vertices(pm), vid)) - return; - typename boost::property_traits::value_type i = 0; - for(typename boost::graph_traits::vertex_descriptor vd : - vertices(pm)) - { - put(vid, vd, i); - ++i; - } -} -template -void init_halfedge_indices(PolygonMesh& pm, - HalfedgeIndexMap& hid, - boost::read_write_property_map_tag, - Tag) -{ - if(is_index_map_valid(num_halfedges(pm), halfedges(pm), hid)) - return; - typename boost::property_traits::value_type i = 0; - for(typename boost::graph_traits::halfedge_descriptor hd : - halfedges(pm)) - { - put(hid, hd, i); - ++i; - } -} - -// matches mutable Lvalue property maps -template -void init_face_indices(PolygonMesh& pm, - FaceIndexMap& fid, - boost::lvalue_property_map_tag, - boost::false_type) -{ - init_face_indices(pm, fid, - boost::read_write_property_map_tag(), boost::false_type()); -} -template -void init_vertex_indices(PolygonMesh& pm, - VertexIndexMap& vid, - boost::lvalue_property_map_tag, - boost::false_type) -{ - init_vertex_indices(pm, vid, - boost::read_write_property_map_tag(), boost::false_type()); -} -template -void init_halfedge_indices(PolygonMesh& pm, - HalfedgeIndexMap& hid, - boost::lvalue_property_map_tag, - boost::false_type) -{ - init_halfedge_indices(pm, hid, - boost::read_write_property_map_tag(), boost::false_type()); -} - -// matches all other types of property map -template -void init_face_indices(PolygonMesh&, FaceIndexMap, MapTag, Tag) -{} -template -void init_vertex_indices(PolygonMesh&, VertexIndexMap, MapTag, Tag) -{} -template -void init_halfedge_indices(PolygonMesh&, HalfedgeIndexMap, MapTag, Tag) -{} - -template -void init_face_indices(PolygonMesh& pm, FaceIndexMap fid) -{ - init_face_indices(pm, fid, - typename boost::property_traits::category(), - typename boost::is_const< - typename boost::remove_reference< - typename boost::property_traits::reference - >::type >::type() ); -} - -template -void init_vertex_indices(PolygonMesh& pm, VertexIndexMap vid) -{ - init_vertex_indices(pm, vid, - typename boost::property_traits::category(), - typename boost::is_const< - typename boost::remove_reference< - typename boost::property_traits::reference - >::type >::type() ); -} - -template -void init_halfedge_indices(PolygonMesh& pm, HalfedgeIndexMap hid) -{ - init_halfedge_indices(pm, hid, - typename boost::property_traits::category(), - typename boost::is_const< - typename boost::remove_reference< - typename boost::property_traits::reference - >::type >::type() ); -} - -} //namespace helpers - +namespace CGAL { namespace internal { template @@ -265,8 +116,8 @@ struct Edge_index_accessor }; template::type >::value> + bool is_const = std::is_const< + typename std::remove_reference::type >::value> struct Point_accessor : boost::put_get_helper< Reference, Point_accessor > { @@ -335,12 +186,12 @@ enum vertex_time_stamp_t { vertex_time_stamp}; enum halfedge_time_stamp_t { halfedge_time_stamp}; enum face_time_stamp_t { face_time_stamp}; -template +template struct vertex_incident_patches_t { typedef ID type; }; -template +template struct face_patch_id_t { typedef ID type; }; diff --git a/Property_map/include/CGAL/Dynamic_property_map.h b/Property_map/include/CGAL/Dynamic_property_map.h index 35cdcd5f4db..2300b4b5efe 100644 --- a/Property_map/include/CGAL/Dynamic_property_map.h +++ b/Property_map/include/CGAL/Dynamic_property_map.h @@ -13,11 +13,13 @@ #define CGAL_DYNAMIC_PROPERTY_MAP_H #include +#include + #include #include + #include #include - #include #include