// Copyright (c) 2017 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) : Andreas Fabri #ifndef CGAL_DYNAMIC_PROPERTY_MAP_H #define CGAL_DYNAMIC_PROPERTY_MAP_H #include #include #include #include #include #include #include namespace CGAL { namespace internal { template struct Dynamic_property_map { typedef K key_type; typedef V value_type; typedef const value_type& reference; typedef boost::read_write_property_map_tag category; Dynamic_property_map(const V default_value = V()) : map_(new Map()), default_value_(default_value) {} void clear() { if(map_){ map_->clear(); } } friend reference get(const Dynamic_property_map& m, const key_type& k) { typename Map::const_iterator it = m.map_->find(k); if(it == m.map_->end()){ (*(const_cast(m).map_))[k] = m.default_value(); return m.default_value(); } return it->second; } friend void put(const Dynamic_property_map& m, const key_type& k, const value_type& v) { (*(m.map_))[k] = v; } const V& default_value() const { return default_value_; } typedef std::unordered_map Map; std::shared_ptr map_; V default_value_; }; template struct Dynamic_property_map_deleter { M& mesh; Dynamic_property_map_deleter(const M& mesh) : mesh(const_cast(mesh)) {} void operator()(PM* pm) const { remove_property(*pm, mesh); delete pm; } }; template struct Dynamic { typedef typename PM::key_type key_type; typedef typename PM::value_type value_type; typedef typename PM::reference reference; typedef boost::read_write_property_map_tag category; typedef Dynamic_property_map_deleter Deleter; Dynamic() : map_() {} Dynamic(const Mesh& mesh, PM* pm) : map_(pm, Deleter(mesh)) {} friend reference get(const Dynamic& m, const key_type& k) { return get(*(m.map_), k); } friend void put(const Dynamic& m, const key_type& k, const value_type& v) { put(*(m.map_), k, v); } std::shared_ptr map_; }; template struct Dynamic_with_index { typedef Key key_type; typedef Value value_type; typedef std::conditional_t< std::is_same_v, value_type, value_type&> reference; typedef boost::read_write_property_map_tag category; Dynamic_with_index() : m_values() {} Dynamic_with_index(std::size_t num_features, Value default_value = Value()) : m_values( new std::vector(num_features, default_value) ) {} friend reference get(const Dynamic_with_index& m, const key_type& k) { return (*m.m_values)[k.idx()]; } friend void put(const Dynamic_with_index& m, const key_type& k, const value_type& v) { (*m.m_values)[k.idx()]=v; } std::shared_ptr > m_values; }; } // namespace internal struct dynamic_property_t {}; template struct dynamic_vertex_property_t : public dynamic_property_t { dynamic_vertex_property_t() {} using value_type = T; template struct property_map { using descriptor = typename boost::graph_traits::vertex_descriptor; using vertex_descriptor = descriptor; }; }; template struct dynamic_halfedge_property_t : public dynamic_property_t { dynamic_halfedge_property_t() {} using value_type = T; template struct property_map { using descriptor = typename boost::graph_traits::halfedge_descriptor; using halfedge_descriptor = descriptor; }; }; template struct dynamic_edge_property_t : public dynamic_property_t { dynamic_edge_property_t() {} using value_type = T; template struct property_map { using descriptor = typename boost::graph_traits::edge_descriptor; using edge_descriptor = descriptor; }; }; template struct dynamic_face_property_t : public dynamic_property_t { dynamic_face_property_t() {} using value_type = T; template struct property_map { using descriptor = typename boost::graph_traits::face_descriptor; using face_descriptor = descriptor; }; }; template constexpr bool is_dynamic_property_tag() { return std::is_base_of_v; } template struct property_map_of_dynamic_property_map : Dynamic_property_tag::template property_map { using descriptor = typename Dynamic_property_tag::template property_map::descriptor; using type = CGAL::internal::Dynamic_property_map; using const_type = const type; }; } // namespace CGAL namespace boost { template struct property_map > : public CGAL::property_map_of_dynamic_property_map> { using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; }; template struct property_map > : public CGAL::property_map_of_dynamic_property_map> { using halfedge_descriptor = typename boost::graph_traits::halfedge_descriptor; }; template struct property_map > : public CGAL::property_map_of_dynamic_property_map> { using edge_descriptor = typename boost::graph_traits::edge_descriptor; }; template struct property_map > : public CGAL::property_map_of_dynamic_property_map> { using face_descriptor = typename boost::graph_traits::face_descriptor; }; } // namespace boost namespace CGAL { template ()>, typename ...Default_value_args> auto get(const Dynamic_property_tag&, const G&, Default_value_args&&... default_value_args) { using Property_map = internal::Dynamic_property_map; return Property_map(std::forward(default_value_args)...); } template void remove_property( internal::Dynamic_property_map pm, const G&) { pm.clear(); } } // namespace CGAL #endif // CGAL_DYNAMIC_PROPERTY_MAP_H