diff --git a/src/OpenMesh/Core/Utils/PropertyManager.hh b/src/OpenMesh/Core/Utils/PropertyManager.hh new file mode 100644 index 00000000..243e8cee --- /dev/null +++ b/src/OpenMesh/Core/Utils/PropertyManager.hh @@ -0,0 +1,197 @@ +/*===========================================================================*\ + * * + * OpenMesh * + * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * + * www.openmesh.org * + * * + *---------------------------------------------------------------------------* + * This file is part of OpenMesh. * + * * + * OpenMesh is free software: 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 with the * + * following exceptions: * + * * + * If other files instantiate templates or use macros * + * or inline functions from this file, or you compile this file and * + * link it with other files to produce an executable, this file does * + * not by itself cause the resulting executable to be covered by the * + * GNU Lesser General Public License. This exception does not however * + * invalidate any other reasons why the executable file might be * + * covered by the GNU Lesser General Public License. * + * * + * OpenMesh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU LesserGeneral Public * + * License along with OpenMesh. If not, * + * see . * + * * +\*===========================================================================*/ + +/*===========================================================================*\ + * * + * $Revision$ * + * $Date$ * + * * +\*===========================================================================*/ + +#ifndef PROPERTYMANAGER_HH_ +#define PROPERTYMANAGER_HH_ + +#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. + * + * Usage example: + * + * \code + * TriMesh mesh; + * PropertyManager, MeshT> visited(mesh, "visited.plugin-example.i8.informatik.rwth-aachen.de"); + * + * for (TriMesh::VertexIter vh_it = mesh.begin(); ... ; ...) { + * if (!visited[*vh_it]) { + * visitComponent(mesh, *vh_it, visited); + * } + * } + * \endcode + * + */ +template +class PropertyManager { + private: + /** + * Noncopyable because there aren't not straightforward copy semantics. + */ + PropertyManager(const PropertyManager&); + + /** + * Noncopyable because there aren't not straightforward copy semantics. + */ + const PropertyManager& operator=(const PropertyManager&); + + public: + /** + * 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. + */ + PropertyManager(MeshT &mesh, const char *propname, bool existing = false) : mesh_(&mesh), retain_(existing) { + if (existing) { + if (!mesh_->get_property_handle(prop_, propname)) { + std::ostringstream oss; + oss << "Requested property handle \"" << propname << "\" does not exist."; + throw std::runtime_error(oss.str()); + } + } else { + mesh_->add_property(prop_, propname); + } + } + + ~PropertyManager() { + deleteProperty(); + } + +#if __cplusplus > 199711L or __GXX_EXPERIMENTAL_CXX0X__ + /** + * Move constructor. Transfers ownership (delete responsibility). + */ + PropertyManager(PropertyManager &&rhs) : mesh_(rhs.mesh_), prop_(rhs.prop_), retain_(rhs.retain_) { + rhs.retain_ = true; + } + + /** + * Move assignment. Transfers ownership (delete responsibility). + */ + PropertyManager &operator=(PropertyManager &&rhs) { + + deleteProperty(); + + mesh_ = rhs.mesh_; + prop_ = rhs.prop_; + retain_ = rhs.retain_; + rhs.retain_ = true; + + return *this; + } +#endif + + /** + * \brief Disable lifecycle management for this property. + * + * If this method is called, the encapsulated property will not be deleted + * upon destruction of the PropertyManager instance. + */ + inline void retain() { + retain_ = true; + } + + /** + * Access the encapsulated property. + */ + inline PROPTYPE &operator* () { + return prop_; + } + + /** + * Access the encapsulated property. + */ + inline const PROPTYPE &operator* () const { + return prop_; + } + + /** + * 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.) + */ + template + inline typename PROPTYPE::reference operator[] (const HandleType &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.) + */ + template + inline typename PROPTYPE::const_reference operator[] (const HandleType &handle) const { + return mesh_->property(prop_, handle); + } + + private: + void deleteProperty() { + if (!retain_) + mesh_->remove_property(prop_); + } + + private: + MeshT *mesh_; + PROPTYPE prop_; + bool retain_; +}; + +} /* namespace OpenMesh */ +#endif /* PROPERTYMANAGER_HH_ */