// Copyright (c) 2008-2009 GeometryFactory and INRIA // 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$ // SPDX-License-Identifier: LGPL-3.0+ // // Author(s) : Andreas Fabri and Laurent Saboret #ifndef CGAL_POINT_SET_PROPERTY_MAP_H #define CGAL_POINT_SET_PROPERTY_MAP_H #include #include #if BOOST_VERSION >= 104000 #include #else #include #include #endif #include #include #include // defines std::pair #include #include namespace CGAL { /// \cond SKIP_DOXYGEN /// This class is almost the same as boost::static_property_map /// The difference is that it is writable, although put() does nothing template class Static_property_map { public: typedef K key_type; typedef V value_type; typedef const V& reference; typedef boost::read_write_property_map_tag category; private: V v; public: Static_property_map(V pv) :v(pv){} inline friend value_type get(const Static_property_map& pm, const key_type&) { return pm.v; } inline friend void put(Static_property_map&, const key_type&, const value_type&) {} }; template class OR_property_map { typedef typename PM1::key_type key_type; typedef typename PM1::value_type value_type; typedef typename PM1::reference reference; typedef boost::read_write_property_map_tag category; PM1 pm1; PM2 pm2; public: OR_property_map() {} // required by boost::connected_components OR_property_map(PM1 pm1, PM2 pm2) : pm1(pm1),pm2(pm2) {} inline friend value_type get(const OR_property_map& pm, const key_type& k) { return get(pm.pm1,k) || get(pm.pm2,k); } inline friend void put(OR_property_map& pm, const key_type& k, const value_type& v) { put(pm.pm1,k, v); put(pm.pm2,k, v); } }; template OR_property_map make_OR_property_map(const PM1& pm1, const PM2& pm2) { return OR_property_map(pm1, pm2); } // A property map that uses the result of a property map as key. template struct Property_map_binder{ typedef typename boost::property_traits::key_type key_type; typedef typename boost::property_traits::value_type value_type; typedef typename boost::property_traits::reference reference; typedef boost::read_write_property_map_tag category; KeyMap key_map; ValueMap value_map; Property_map_binder(const KeyMap& key_map, const ValueMap& value_map) : key_map(key_map) , value_map(value_map) {} friend reference get(const Property_map_binder& map, key_type k) { return get(map.value_map, get(map.key_map,k)); } friend void put(const Property_map_binder& map, key_type k, const value_type& v) { put(map.value_map, get(map.key_map,k), v); } }; template Property_map_binder bind_property_maps(const KeyMap& src, const ValueMap& tgt) { return Property_map_binder(src, tgt); } /// Property map that accesses a value from an iterator /// /// \cgalModels `ReadablePropertyMap` /// /// \tparam InputIterator an input iterator /// \endcond template struct Input_iterator_property_map{ typedef InputIterator key_type; typedef typename std::iterator_traits::value_type value_type; typedef typename std::iterator_traits::reference reference; typedef boost::readable_property_map_tag category; /// Free function to use a get the value from an iterator using Input_iterator_property_map. inline friend reference get(Input_iterator_property_map,InputIterator it){ return *it; } }; /// \ingroup PkgProperty_map /// Property map that converts a `T*` pointer (or in general an iterator /// over `T` elements) to the `T` object. /// /// \cgalModels `LvaluePropertyMap` template struct Dereference_property_map : public boost::put_get_helper > { typedef T* key_type; ///< typedef to 'T*' typedef T value_type; ///< typedef to 'T' typedef const value_type& reference; ///< typedef to 'T&' typedef boost::lvalue_property_map_tag category; ///< `boost::lvalue_property_map_tag` /// Access a property map element. /// /// @tparam Iter Type convertible to `key_type`. template value_type& operator[](Iter it) const { return reference(*it); } }; /// Free function to create a `Dereference_property_map` property map. /// /// \relates Dereference_property_map template // Type convertible to `key_type` Dereference_property_map::type> make_dereference_property_map(Iter) { // value_type_traits is a workaround as back_insert_iterator's `value_type` is void return Dereference_property_map::type>(); } /// \ingroup PkgProperty_map /// A `LvaluePropertyMap` property map mapping a key to itself (by reference). /// /// \cgalModels `LvaluePropertyMap` template struct Identity_property_map { typedef T key_type; ///< typedef to `T` typedef T value_type; ///< typedef to `T` typedef const T& reference; ///< typedef to `T&` typedef boost::lvalue_property_map_tag category; ///< `boost::lvalue_property_map_tag` /// Access a property map element. /// @param k a key which is returned as mapped value. value_type& operator[](key_type& k) const { return k; } typedef Identity_property_map Self; /// \name Put/get free functions /// @{ friend reference get(const Self&,const key_type& k) {return k;} friend void put(const Self&,key_type& k, const value_type& v) {k=v;} /// @} }; /// Free function to create a `Identity_property_map` property map. /// /// \relates Identity_property_map template // Key and value type Identity_property_map make_identity_property_map(T) { return Identity_property_map(); } /// \ingroup PkgProperty_map /// Property map that accesses the first item of a `std::pair`. /// \tparam Pair Instance of `std::pair`. /// \cgalModels `LvaluePropertyMap` /// /// \sa `CGAL::Second_of_pair_property_map` template struct First_of_pair_property_map { typedef Pair key_type; ///< typedef to `Pair` typedef typename Pair::first_type value_type; ///< typedef to `Pair::first_type` typedef const value_type& reference; ///< typedef to `value_type&` typedef boost::lvalue_property_map_tag category; ///< boost::lvalue_property_map_tag /// Access a property map element. /// @param pair a key whose first item is accessed value_type& operator[](key_type& pair) const { return pair.first; } typedef First_of_pair_property_map Self; /// \name Put/get free functions /// @{ friend reference get(const Self&,const key_type& k) {return k.first;} friend void put(const Self&,key_type& k, const value_type& v) {k.first=v;} /// @} }; /// Free function to create a `First_of_pair_property_map` property map. /// /// \relates First_of_pair_property_map template // Pair type First_of_pair_property_map make_first_of_pair_property_map(Pair) { return First_of_pair_property_map(); } /// \ingroup PkgProperty_map /// /// Property map that accesses the second item of a `std::pair`. /// /// \tparam Pair Instance of `std::pair`. /// /// \cgalModels `LvaluePropertyMap` /// /// \sa `CGAL::First_of_pair_property_map` template struct Second_of_pair_property_map { typedef Pair key_type; ///< typedef to `Pair` typedef typename Pair::second_type value_type; ///< typedef to `Pair::second_type` typedef const value_type& reference; ///< typedef to `value_type&` typedef boost::lvalue_property_map_tag category; ///< boost::lvalue_property_map_tag /// Access a property map element. /// @param pair a key whose second item is accessed value_type& operator[](key_type& pair) const { return pair.second; } typedef Second_of_pair_property_map Self; /// \name Put/get free functions /// @{ friend reference get(const Self&,const key_type& k) {return k.second;} friend void put(const Self&,key_type& k, const value_type& v) {k.second=v;} /// @} }; /// Free function to create a Second_of_pair_property_map property map. /// /// \relates Second_of_pair_property_map template // Pair type Second_of_pair_property_map make_second_of_pair_property_map(Pair) { return Second_of_pair_property_map(); } /// \ingroup PkgProperty_map /// /// Property map that accesses the Nth item of a `boost::tuple` or a `std::tuple`. /// /// \tparam N %Index of the item to access. /// \tparam Tuple Instance of `boost::tuple` or `std::tuple`. /// /// \cgalModels `LvaluePropertyMap` template struct Nth_of_tuple_property_map { typedef Tuple key_type; ///< typedef to `Tuple` #ifdef DOXYGEN_RUNNING typedef unspecified_type value_type; ///< typedef to the N-th type of the tuple #else typedef typename boost::tuples::element::type value_type; #endif typedef const value_type& reference; ///< typedef to `value_type&` typedef boost::lvalue_property_map_tag category; ///< `boost::lvalue_property_map_tag` /// Access a property map element. /// @param tuple a key whose Nth item is accessed value_type& operator[](key_type& tuple) const { return tuple.template get(); } typedef Nth_of_tuple_property_map Self; /// \name Put/get free functions /// @{ friend reference get(const Self&,const key_type& k) {return k.template get();} friend void put(const Self&,key_type& k, const value_type& v) {k.template get()=v;} /// @} }; #ifndef CGAL_CFG_NO_CPP0X_TUPLE template struct Nth_of_tuple_property_map > { typedef std::tuple Tuple; typedef Tuple key_type; typedef typename cpp11::tuple_element::type value_type; typedef const value_type& reference; typedef boost::lvalue_property_map_tag category; value_type& operator[](key_type& tuple) const { return get(tuple); } typedef Nth_of_tuple_property_map Self; friend reference get(const Self&,const key_type& k) {return std::get(k);} friend void put(const Self&,key_type& k, const value_type& v) {std::get(k)=v;} }; #endif /// Free function to create a Nth_of_tuple_property_map property map. /// /// \relates Nth_of_tuple_property_map template // Tuple type Nth_of_tuple_property_map make_nth_of_tuple_property_map(Tuple) { return Nth_of_tuple_property_map(); } /// \ingroup PkgProperty_map /// Struct that turns a property map into a unary functor with /// `operator()(key k)` calling the get function with `k` template struct Property_map_to_unary_function{ typedef typename boost::property_traits::key_type argument_type; typedef typename boost::property_traits::reference result_type; PropertyMap map; Property_map_to_unary_function(PropertyMap m=PropertyMap()) : map(m) {} template result_type operator()(const KeyType& a) const { return get(map,a); } }; /// \ingroup PkgProperty_map /// Utility class providing shortcuts to property maps based on raw pointers template struct Pointer_property_map{ typedef boost::iterator_property_map< T*, boost::typed_identity_property_map, T, T&> type; ///< mutable `LvaluePropertyMap` typedef boost::iterator_property_map< const T*, boost::typed_identity_property_map, T, const T&> const_type; ///< non-mutable `LvaluePropertyMap` }; /// \ingroup PkgProperty_map /// Starting from boost 1.55, the use of raw pointers as property maps has been deprecated. /// This function is a shortcut to the recommanded replacement: /// `boost::make_iterator_property_map(, boost::typed_identity_property_map())` /// Note that the property map is a mutable `LvaluePropertyMap` with `std::size_t` as key. template inline typename Pointer_property_map::type make_property_map(T* pointer) { return typename Pointer_property_map::type(pointer); } /// \ingroup PkgProperty_map /// equivalent to `make_property_map(&v[0])` /// Note that `v` must not be modified while using the property map created template inline typename Pointer_property_map::type make_property_map(std::vector& v) { if(v.empty()){ return make_property_map(static_cast(NULL)); } return make_property_map(&v[0]); } /// \ingroup PkgProperty_map /// Non-mutable version template inline typename Pointer_property_map::const_type make_property_map(const T* pointer) { return typename Pointer_property_map::const_type(pointer); } /// \ingroup PkgProperty_map /// equivalent to `make_property_map(&v[0])` /// Note that `v` must not be modified while using the property map created template inline typename Pointer_property_map::const_type make_property_map(const std::vector& v) { return make_property_map(&v[0]); } /// \ingroup PkgProperty_map /// Property map that returns a fixed value. /// Note that this value is chosen when the map is constructed and cannot /// be changed afterwards. Specifically, the free function `put()` does nothing. /// /// \cgalModels `ReadWritePropertyMap` template struct Constant_property_map { const ValueType default_value; typedef KeyType key_type; typedef ValueType value_type; typedef boost::read_write_property_map_tag category; Constant_property_map(const value_type& default_value = value_type()) : default_value (default_value) { } /// Free function that returns `pm.default_value`. inline friend value_type get (const Constant_property_map& pm, const key_type&){ return pm.default_value; } /// Free function that does nothing. inline friend void put (const Constant_property_map&, const key_type&, const value_type&) { } }; /// \ingroup PkgProperty_map /// Read-write property map turning a set (such a `std::set`, /// `boost::unordered_set`, `std::unordered_set`) into a property map /// associating a Boolean to the value type of the set. The function `get` will /// return `true` if the key is inside the set and `false` otherwise. The `put` /// function will insert an element in the set if `true` is passed and erase it /// otherwise. /// \cgalModels `ReadWritePropertyMap` template struct Boolean_property_map { typedef typename Set::value_type key_type; typedef bool value_type; typedef bool reference; typedef boost::read_write_property_map_tag category; Set* set_ptr; /// Constructor taking a copy of the set. Note that `set_` must be valid /// while the property map is in use. Boolean_property_map(Set& set_) : set_ptr(&set_) {} Boolean_property_map() : set_ptr(NULL) {} friend bool get(const Boolean_property_map& pm, const key_type& k) { CGAL_assertion(pm.set_ptr!=NULL); return pm.set_ptr->count(k) != 0; } friend void put(Boolean_property_map& pm, const key_type& k, bool v) { CGAL_assertion(pm.set_ptr!=NULL); if (v) pm.set_ptr->insert(k); else pm.set_ptr->erase(k); } }; /// \ingroup PkgProperty_map /// returns `Boolean_property_map(set_)` template Boolean_property_map make_boolean_property_map(Set& set_) { return Boolean_property_map(set_); } /// \ingroup PkgProperty_map /// Read-write property map doing on-the-fly conversions between two default constructible \cgal %Cartesian kernels. /// Its value type is `GeomObject` and its key type is the same as `Vpm`. /// `GeomObject` must be a geometric object from a \cgal kernel. /// `Vpm` is a model `of ReadWritePropertyMap` and its value type must be /// a geometric object of the same type as `GeomObject` but possibly from /// another kernel. /// Conversions between the two geometric objects are done using `Cartesian_converter`. /// \cgalModels `ReadWritePropertyMap` template struct Cartesian_converter_property_map { typedef typename boost::property_traits::key_type key_type; typedef GeomObject value_type; typedef value_type reference; typedef boost::read_write_property_map_tag category; Vpm vpm; typedef typename Kernel_traits::type K2; typedef typename Kernel_traits::value_type>::type K1; Cartesian_converter_property_map(Vpm vpm):vpm(vpm){} friend value_type get(const Cartesian_converter_property_map& pm, const key_type& k) { return CGAL::Cartesian_converter()(get(pm.vpm, k)); } friend void put(Cartesian_converter_property_map& pm, const key_type& k, const value_type& v) { put(pm.vpm, k, CGAL::Cartesian_converter()(v)); } }; /// \ingroup PkgProperty_map /// returns `Cartesian_converter_property_map(vpm)` template Cartesian_converter_property_map make_cartesian_converter_property_map(Vpm vpm) { return Cartesian_converter_property_map(vpm); } } // namespace CGAL #endif // CGAL_POINT_SET_PROPERTY_MAP_H