/* ========================================================================= * * * * OpenMesh * * Copyright (c) 2001-2015, RWTH-Aachen University * * Department of Computer Graphics and Multimedia * * All rights reserved. * * www.openmesh.org * * * *---------------------------------------------------------------------------* * This file is part of OpenMesh. * *---------------------------------------------------------------------------* * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * * * 1. Redistributions of source code must retain the above copyright notice, * * this list of conditions and the following disclaimer. * * * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * * * 3. Neither the name of the copyright holder nor the names of its * * contributors may be used to endorse or promote products derived from * * this software without specific prior written permission. * * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER * * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ========================================================================= */ #ifndef PROPERTYMANAGER_HH_ #define PROPERTYMANAGER_HH_ #include #include #include #include #include #include namespace OpenMesh { /** * This class is intended to manage the lifecycle of properties. * It also defines convenience operators to access the encapsulated * property's value. * * Note that the second template parameter is depcretated. * * \code * { * TriMesh mesh; * auto visited = makeTemporaryProperty(mesh); * * for (auto vh : mesh.vertices()) { * if (!visited[vh]) { * visitComponent(mesh, vh, visited); * } * } * // The property is automatically removed at the end of the scope * } * \endcode */ template class PropertyManager { public: using Value = typename PROPTYPE::Value; using value_type = typename PROPTYPE::value_type; using Handle = typename PROPTYPE::Handle; using Self = PropertyManager; using Reference = typename PROPTYPE::reference; using ConstReference = typename PROPTYPE::const_reference; private: // Mesh properties (MPropHandleT<...>) are stored differently than the other properties. // This class implements different behavior when initializing a property or when // copying or swapping data from one property manager to a another one. template struct StorageT; // specialization for Mesh Properties template struct StorageT> { static void initialize(PropertyManager& pm, const Value& initial_value ) { pm() = initial_value; } static void copy(const PropertyManager& from, PropertyManager2& to) { *to = *from; } static void swap(PropertyManager& from, PropertyManager2& to) { std::swap(*to, *from); } static ConstReference access_property_const(PolyConnectivity& mesh, const PROPTYPE& prop_handle, const Handle&) { return mesh.property(prop_handle); } static Reference access_property(PolyConnectivity& mesh, const PROPTYPE& prop_handle, const Handle&) { return mesh.property(prop_handle); } }; // definition for other Mesh Properties template struct StorageT { static void initialize(PropertyManager& pm, const Value& initial_value ) { pm.set_range(pm.mesh_.template all_elements(), initial_value); } static void copy(const PropertyManager& from, PropertyManager2& to) { from.copy_to(from.mesh_.template all_elements(), to, to.mesh_.template all_elements()); } static void swap(PropertyManager& lhs, PropertyManager2& rhs) { std::swap(lhs.mesh().property(lhs.prop_).data_vector(), rhs.mesh().property(rhs.prop_).data_vector()); // resize the property to the correct size lhs.mesh().property(lhs.prop_).resize(lhs.mesh().template n_elements()); rhs.mesh().property(rhs.prop_).resize(rhs.mesh().template n_elements()); } static ConstReference access_property_const(PolyConnectivity& mesh, const PROPTYPE& prop_handle, const Handle& handle) { return mesh.property(prop_handle, handle); } static Reference access_property(PolyConnectivity& mesh, const PROPTYPE& prop_handle, const Handle& handle) { return mesh.property(prop_handle, handle); } }; using Storage = StorageT; public: /** * @deprecated Use a constructor without \p existing and check existance with hasProperty() instead. * * Constructor. * * Throws an \p std::runtime_error if \p existing is true and * no property named \p propname of the appropriate property type * exists. * * @param mesh The mesh on which to create the property. * @param propname The name of the property. * @param existing If false, a new property is created and its lifecycle is managed (i.e. * the property is deleted upon destruction of the PropertyManager instance). If true, * the instance merely acts as a convenience wrapper around an existing property with no * lifecycle management whatsoever. * * @see PropertyManager::getOrMakeProperty, PropertyManager::getProperty, * PropertyManager::makeTemporaryProperty */ OM_DEPRECATED("Use the constructor without parameter 'existing' instead. Check for existance with hasProperty") // As long as this overload exists, initial value must be first parameter due to ambiguity for properties of type bool PropertyManager(PolyConnectivity& mesh, const char *propname, bool existing) : mesh_(mesh), retain_(existing), name_(propname) { if (existing) { if (!PropertyManager::mesh().get_property_handle(prop_, propname)) { std::ostringstream oss; oss << "Requested property handle \"" << propname << "\" does not exist."; throw std::runtime_error(oss.str()); } } else { PropertyManager::mesh().add_property(prop_, propname); } } /** * Constructor. * * Asks for a property with name propname and creates one if none exists. Lifetime is not managed. * * @param mesh The mesh on which to create the property. * @param propname The name of the property. */ PropertyManager(PolyConnectivity& mesh, const char *propname) : mesh_(mesh), retain_(true), name_(propname) { if (!PropertyManager::mesh().get_property_handle(prop_, propname)) { PropertyManager::mesh().add_property(prop_, propname); } } /** * Constructor. * * Asks for a property with name propname and creates one if none exists. Lifetime is not managed. * * @param initial_value If the proeprty is newly created, it will be initialized with initial_value. * If the property already existed, nothing is changes. * @param mesh The mesh on which to create the property. * @param propname The name of the property. */ PropertyManager(const Value& initial_value, PolyConnectivity& mesh, const char *propname) : mesh_(mesh), retain_(true), name_(propname) { if (!mesh_.get_property_handle(prop_, propname)) { PropertyManager::mesh().add_property(prop_, propname); Storage::initialize(*this, initial_value); } } /** * Constructor. * * Create an anonymous property. Lifetime is managed. * * @param mesh The mesh on which to create the property. */ PropertyManager(const PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") { PropertyManager::mesh().add_property(prop_, name_); } /** * Constructor. * * Create an anonymous property. Lifetime is managed. * * @param initial_value The property will be initialized with initial_value. * @param mesh The mesh on which to create the property. */ PropertyManager(const Value& initial_value, const PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") { PropertyManager::mesh().add_property(prop_, name_); Storage::initialize(*this, initial_value); } /** * Constructor. * * Create a wrapper around an existing property. Lifetime is not managed. * * @param mesh The mesh on which to create the property. * @param property_handle Handle to an existing property that should be wrapped. */ PropertyManager(PolyConnectivity& mesh, PROPTYPE property_handle) : mesh_(mesh), prop_(property_handle), retain_(true), name_() { } PropertyManager() = delete; PropertyManager(const PropertyManager& rhs) : mesh_(rhs.mesh_), prop_(), retain_(rhs.retain_), name_(rhs.name_) { if (rhs.retain_) // named property -> create a property manager referring to the same { prop_ = rhs.prop_; } else // unnamed property -> create a property manager refering to a new property and copy the contents { PropertyManager::mesh().add_property(prop_, name_); Storage::copy(rhs, *this); } } /** * Create property manager referring to a copy of the current property. * This can be used to explicitely create a copy of a named property. The cloned property * will be unnamed. */ PropertyManager clone() { PropertyManager result(this->mesh()); Storage::copy(*this, result); return result; } PropertyManager& operator=(const PropertyManager& rhs) { if (&mesh_ == &rhs.mesh_ && prop_ == rhs.prop_) ; // nothing to do else Storage::copy(rhs, *this); return *this; } ~PropertyManager() { deleteProperty(); } void swap(PropertyManager &rhs) { // swap the data stored in the properties Storage::swap(rhs, *this); } static bool propertyExists(PolyConnectivity &mesh, const char *propname) { PROPTYPE dummy; return mesh.get_property_handle(dummy, propname); } bool isValid() const { return prop_.is_valid(); } operator bool() const { return isValid(); } const PROPTYPE &getRawProperty() const { return prop_; } const std::string &getName() const { return name_; } /** * Get the mesh corresponding to the property. * * If you use PropertyManager without second template parameter (recommended) * you need to specify the actual mesh type when using this function, e.g.: * \code * { * TriMesh mesh; * auto visited = VProp(mesh); * TriMesh& mesh_ref = visited.getMesh(); * } * */ template const MeshType& getMesh() const { return dynamic_cast(mesh_); } const MeshT& getMesh() const { return dynamic_cast(mesh_); } /** * @deprecated This method no longer has any effect. Instead, named properties are always retained, while unnamed ones are not * * Tells the PropertyManager whether lifetime should be managed or not. */ OM_DEPRECATED("retain no longer has any effect. Instead, named properties are always retained, while unnamed ones are not.") void retain(bool = true) {} /** * Move constructor. Transfers ownership (delete responsibility). */ PropertyManager(PropertyManager &&rhs) : mesh_(rhs.mesh_), prop_(rhs.prop_), retain_(rhs.retain_), name_(rhs.name_) { if (!rhs.retain_) rhs.prop_.invalidate(); // only invalidate unnamed properties } /** * Move assignment. Transfers ownership (delete responsibility). */ PropertyManager& operator=(PropertyManager&& rhs) { if ((&mesh_ != &rhs.mesh_) || (prop_ != rhs.prop_)) { if (rhs.retain_) { // retained properties cannot be invalidated. Copy instead Storage::copy(rhs, *this); } else { // swap the data stored in the properties Storage::swap(rhs, *this); // remove the property from rhs rhs.mesh().remove_property(rhs.prop_); // invalidate prop_ rhs.prop_.invalidate(); } } return *this; } /** * Create a property manager for the supplied property and mesh. * If the property doesn't exist, it is created. In any case, * lifecycle management is disabled. * * @see makePropertyManagerFromExistingOrNew */ static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname) { return PropertyManager(mesh, propname); } /** * Like createIfNotExists() with two parameters except, if the property * doesn't exist, it is initialized with the supplied value over * the supplied range after creation. If the property already exists, * this method has the exact same effect as the two parameter version. * Lifecycle management is disabled in any case. * * @see makePropertyManagerFromExistingOrNew */ template static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname, const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, const PROP_VALUE &init_value) { const bool exists = propertyExists(mesh, propname); PropertyManager pm(mesh, propname, exists); pm.retain(); if (!exists) pm.set_range(begin, end, init_value); return std::move(pm); } /** * Like createIfNotExists() with two parameters except, if the property * doesn't exist, it is initialized with the supplied value over * the supplied range after creation. If the property already exists, * this method has the exact same effect as the two parameter version. * Lifecycle management is disabled in any case. * * @see makePropertyManagerFromExistingOrNew */ template static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname, const ITERATOR_RANGE &range, const PROP_VALUE &init_value) { return createIfNotExists( mesh, propname, range.begin(), range.end(), init_value); } /** * Access the value of the encapsulated mesh property. * * Example: * @code * PolyMesh m; * auto description = getOrMakeProperty(m, "description"); * *description = "This is a very nice mesh."; * @endcode * * @note This method is only used for mesh properties. */ typename PROPTYPE::reference& operator*() { return mesh().mproperty(prop_)[0]; } /** * Access the value of the encapsulated mesh property. * * Example: * @code * PolyMesh m; * auto description = getProperty(m, "description"); * std::cout << *description << std::endl; * @endcode * * @note This method is only used for mesh properties. */ typename PROPTYPE::const_reference& operator*() const { return mesh().mproperty(prop_)[0]; } /** * Enables convenient access to the encapsulated property. * * For a usage example see this class' documentation. * * @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.) */ inline typename PROPTYPE::reference operator[] (Handle handle) { return mesh().property(prop_, handle); } /** * Enables convenient access to the encapsulated property. * * For a usage example see this class' documentation. * * @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.) */ inline typename PROPTYPE::const_reference operator[] (const Handle& handle) const { return mesh().property(prop_, handle); } /** * Enables convenient access to the encapsulated property. * * For a usage example see this class' documentation. * * @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.) */ inline typename PROPTYPE::reference operator() (const Handle& handle = Handle()) { // return mesh().property(prop_, handle); return Storage::access_property(mesh(), prop_, handle); } /** * Enables convenient access to the encapsulated property. * * For a usage example see this class' documentation. * * @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.) */ inline typename PROPTYPE::const_reference operator() (const Handle& handle = Handle()) const { // return mesh().property(prop_, handle); return Storage::access_property_const(mesh(), prop_, handle); } /** * Conveniently set the property for an entire range of values. * * Examples: * \code * MeshT mesh; * PropertyManager> distance( * mesh, "distance.plugin-example.i8.informatik.rwth-aachen.de"); * distance.set_range( * mesh.vertices_begin(), mesh.vertices_end(), * std::numeric_limits::infinity()); * \endcode * or * \code * MeshT::VertexHandle vh; * distance.set_range( * mesh.vv_begin(vh), mesh.vv_end(vh), * std::numeric_limits::infinity()); * \endcode * * @param begin Start iterator. Needs to dereference to HandleType. * @param end End iterator. (Exclusive.) * @param value The value the range will be set to. */ template void set_range(HandleTypeIterator begin, HandleTypeIterator end, const PROP_VALUE &value) { for (; begin != end; ++begin) (*this)[*begin] = value; } #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__) template void set_range(const HandleTypeIteratorRange &range, const PROP_VALUE &value) { set_range(range.begin(), range.end(), value); } #endif /** * Conveniently transfer the values managed by one property manager * onto the values managed by a different property manager. * * @param begin Start iterator. Needs to dereference to HandleType. Will * be used with this property manager. * @param end End iterator. (Exclusive.) Will be used with this property * manager. * @param dst_propmanager The destination property manager. * @param dst_begin Start iterator. Needs to dereference to the * HandleType of dst_propmanager. Will be used with dst_propmanager. * @param dst_end End iterator. (Exclusive.) * Will be used with dst_propmanager. Used to double check the bounds. */ template void copy_to(HandleTypeIterator begin, HandleTypeIterator end, PropertyManager2 &dst_propmanager, HandleTypeIterator2 dst_begin, HandleTypeIterator2 dst_end) const { for (; begin != end && dst_begin != dst_end; ++begin, ++dst_begin) { dst_propmanager[*dst_begin] = (*this)[*begin]; } } template void copy_to(const RangeType &range, PropertyManager2 &dst_propmanager, const RangeType2 &dst_range) const { copy_to(range.begin(), range.end(), dst_propmanager, dst_range.begin(), dst_range.end()); } /** * Copy the values of a property from a source range to * a target range. The source range must not be smaller than the * target range. * * @param prop_name Name of the property to copy. Must exist on the * source mesh. Will be created on the target mesh if it doesn't exist. * * @param src_mesh Source mesh from which to copy. * @param src_range Source range which to copy. Must not be smaller than * dst_range. * @param dst_mesh Destination mesh on which to copy. * @param dst_range Destination range. */ template static void copy(const char *prop_name, PolyConnectivity &src_mesh, const RangeType &src_range, PolyConnectivity &dst_mesh, const RangeType2 &dst_range) { typedef OpenMesh::PropertyManager DstPM; DstPM dst(DstPM::createIfNotExists(dst_mesh, prop_name)); typedef OpenMesh::PropertyManager SrcPM; SrcPM src(src_mesh, prop_name, true); src.copy_to(src_range, dst, dst_range); } /** * Mark whether this property should be stored when mesh is written * to a file * * @param _persistence Property will be stored iff _persistence is true */ void set_persistent(bool _persistence = true) { mesh().property(getRawProperty()).set_persistent(_persistence); } private: void deleteProperty() { if (!retain_ && prop_.is_valid()) mesh().remove_property(prop_); } PolyConnectivity& mesh() const { return const_cast(mesh_); } private: const PolyConnectivity& mesh_; PROPTYPE prop_; bool retain_; std::string name_; }; template class ConstPropertyViewer { public: using Value = typename PropertyT::Value; using value_type = typename PropertyT::value_type; using Handle = typename PropertyT::Handle; ConstPropertyViewer(const PolyConnectivity& mesh, PropertyT property_handle) : mesh_(mesh), prop_(property_handle) {} inline const typename PropertyT::const_reference operator() (const Handle& handle) { return mesh_.property(prop_, handle); } inline const typename PropertyT::const_reference operator[] (const Handle& handle) { return mesh_.property(prop_, handle); } private: const PolyConnectivity& mesh_; PropertyT prop_; }; /** @relates PropertyManager * * @deprecated Temporary properties should not have a name. * * Creates a new property whose lifetime is limited to the current scope. * * Used for temporary properties. Shadows any existing properties of * matching name and type. * * Example: * @code * PolyMesh m; * { * auto is_quad = makeTemporaryProperty(m); * for (auto& fh : m.faces()) { * is_quad[fh] = (m.valence(fh) == 4); * } * // The property is automatically removed from the mesh at the end of the scope. * } * @endcode * * @param mesh The mesh on which the property is created * @param propname (optional) The name of the created property * @tparam ElementT Element type of the created property, e.g. VertexHandle, HalfedgeHandle, etc. * @tparam T Value type of the created property, e.g., \p double, \p int, etc. * @returns A PropertyManager handling the lifecycle of the property */ template PropertyManager::type> OM_DEPRECATED("Named temporary properties are deprecated. Either create a temporary without name or a non-temporary with name") makeTemporaryProperty(PolyConnectivity &mesh, const char *propname) { return PropertyManager::type>(mesh, propname, false); } /** @relates PropertyManager * * Creates a new property whose lifetime is limited to the current scope. * * Used for temporary properties. Shadows any existing properties of * matching name and type. * * Example: * @code * PolyMesh m; * { * auto is_quad = makeTemporaryProperty(m); * for (auto& fh : m.faces()) { * is_quad[fh] = (m.valence(fh) == 4); * } * // The property is automatically removed from the mesh at the end of the scope. * } * @endcode * * @param mesh The mesh on which the property is created * @tparam ElementT Element type of the created property, e.g. VertexHandle, HalfedgeHandle, etc. * @tparam T Value type of the created property, e.g., \p double, \p int, etc. * @returns A PropertyManager handling the lifecycle of the property */ template PropertyManager::type> makeTemporaryProperty(PolyConnectivity &mesh) { return PropertyManager::type>(mesh); } /** @relates PropertyManager * * Tests whether a property with the given element type, value type, and name is * present on the given mesh. * * * Example: * @code * PolyMesh m; * if (hasProperty(m, "is_quad")) { * // We now know the property exists: getProperty won't throw. * auto is_quad = getProperty(m, "is_quad"); * // Use is_quad here. * } * @endcode * * @param mesh The mesh in question * @param propname The property name of the expected property * @tparam ElementT Element type of the expected property, e.g. VertexHandle, HalfedgeHandle, etc. * @tparam T Value type of the expected property, e.g., \p double, \p int, etc. * @tparam MeshT Type of the mesh. Can often be inferred from \p mesh */ template bool hasProperty(const PolyConnectivity &mesh, const char *propname) { typename HandleToPropHandle::type ph; return mesh.get_property_handle(ph, propname); } /** @relates PropertyManager * * Obtains a handle to a named property. * * Example: * @code * PolyMesh m; * { * try { * auto is_quad = getProperty(m, "is_quad"); * // Use is_quad here. * } * catch (const std::runtime_error& e) { * // There is no is_quad face property on the mesh. * } * } * @endcode * * @pre Property with the name \p propname of matching type exists. * @throws std::runtime_error if no property with the name \p propname of * matching type exists. * @param mesh The mesh on which the property is created * @param propname The name of the created property * @tparam ElementT Element type of the created property, e.g. VertexHandle, HalfedgeHandle, etc. * @tparam T Value type of the created property, e.g., \p double, \p int, etc. * @returns A PropertyManager wrapping the property */ template PropertyManager::type> getProperty(PolyConnectivity &mesh, const char *propname) { if (!hasProperty(mesh, propname)) { std::ostringstream oss; oss << "Requested property handle \"" << propname << "\" does not exist."; throw std::runtime_error(oss.str()); } return PropertyManager::type>(mesh, propname); } /** @relates PropertyManager * * Obtains a handle to a named property if it exists or creates a new one otherwise. * * Used for creating or accessing permanent properties. * * Example: * @code * PolyMesh m; * { * auto is_quad = getOrMakeProperty(m, "is_quad"); * for (auto& fh : m.faces()) { * is_quad[fh] = (m.valence(fh) == 4); * } * // The property remains on the mesh after the end of the scope. * } * { * // Retrieve the property from the previous scope. * auto is_quad = getOrMakeProperty(m, "is_quad"); * // Use is_quad here. * } * @endcode * * @param mesh The mesh on which the property is created * @param propname The name of the created property * @tparam ElementT Element type of the created property, e.g. VertexHandle, HalfedgeHandle, etc. * @tparam T Value type of the created property, e.g., \p double, \p int, etc. * @returns A PropertyManager wrapping the property */ template PropertyManager::type> getOrMakeProperty(PolyConnectivity &mesh, const char *propname) { return PropertyManager::type>::createIfNotExists(mesh, propname); } /** @relates PropertyManager * @deprecated Use makeTemporaryProperty() instead. * * Creates a new property whose lifecycle is managed by the returned * PropertyManager. * * Intended for temporary properties. Shadows any existing properties of * matching name and type. */ template OM_DEPRECATED("Use makeTemporaryProperty instead.") PropertyManager makePropertyManagerFromNew(PolyConnectivity &mesh, const char *propname) { return PropertyManager(mesh, propname, false); } /** \relates PropertyManager * @deprecated Use getProperty() instead. * * Creates a non-owning wrapper for an existing mesh property (no lifecycle * management). * * Intended for convenient access. * * @pre Property with the name \p propname of matching type exists. * @throws std::runtime_error if no property with the name \p propname of * matching type exists. */ template OM_DEPRECATED("Use getProperty instead.") PropertyManager makePropertyManagerFromExisting(PolyConnectivity &mesh, const char *propname) { return PropertyManager(mesh, propname, true); } /** @relates PropertyManager * @deprecated Use getOrMakeProperty() instead. * * Creates a non-owning wrapper for a mesh property (no lifecycle management). * If the given property does not exist, it is created. * * Intended for creating or accessing persistent properties. */ template OM_DEPRECATED("Use getOrMakeProperty instead.") PropertyManager makePropertyManagerFromExistingOrNew(PolyConnectivity &mesh, const char *propname) { return PropertyManager::createIfNotExists(mesh, propname); } /** @relates PropertyManager * Like the two parameter version of makePropertyManagerFromExistingOrNew() * except it initializes the property with the specified value over the * specified range if it needs to be created. If the property already exists, * this function has the exact same effect as the two parameter version. * * Creates a non-owning wrapper for a mesh property (no lifecycle management). * If the given property does not exist, it is created. * * Intended for creating or accessing persistent properties. */ template OM_DEPRECATED("Use getOrMakeProperty instead.") PropertyManager makePropertyManagerFromExistingOrNew( PolyConnectivity &mesh, const char *propname, const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, const PROP_VALUE &init_value) { return PropertyManager::createIfNotExists( mesh, propname, begin, end, init_value); } /** @relates PropertyManager * Like the two parameter version of makePropertyManagerFromExistingOrNew() * except it initializes the property with the specified value over the * specified range if it needs to be created. If the property already exists, * this function has the exact same effect as the two parameter version. * * Creates a non-owning wrapper for a mesh property (no lifecycle management). * If the given property does not exist, it is created. * * Intended for creating or accessing persistent properties. */ template OM_DEPRECATED("Use getOrMakeProperty instead.") PropertyManager makePropertyManagerFromExistingOrNew( PolyConnectivity &mesh, const char *propname, const ITERATOR_RANGE &range, const PROP_VALUE &init_value) { return makePropertyManagerFromExistingOrNew( mesh, propname, range.begin(), range.end(), init_value); } /** @relates PropertyManager * Returns a convenience wrapper around the points property of a mesh. */ template PropertyManager> getPointsProperty(MeshT &mesh) { return PropertyManager>(mesh, mesh.points_property_handle()); } /** @relates PropertyManager * Returns a convenience wrapper around the points property of a mesh that only allows const access. */ template ConstPropertyViewer> getPointsProperty(const MeshT &mesh) { using PropType = OpenMesh::VPropHandleT; return ConstPropertyViewer(mesh, mesh.points_property_handle()); } template using Prop = PropertyManager::template type>; template using VProp = PropertyManager>; template using HProp = PropertyManager>; template using EProp = PropertyManager>; template using FProp = PropertyManager>; template using MProp = PropertyManager>; } /* namespace OpenMesh */ #endif /* PROPERTYMANAGER_HH_ */