PropertyManager.hh
/* ========================================================================= *
* *
* 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. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef PROPERTYMANAGER_HH_
#define PROPERTYMANAGER_HH_
#include <sstream>
#include <stdexcept>
#include <string>
namespace OpenMesh {
template<typename PROPTYPE, typename MeshT>
class PropertyManager {
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
public:
PropertyManager(const PropertyManager&) = delete;
PropertyManager& operator=(const PropertyManager&) = delete;
#else
private:
PropertyManager(const PropertyManager&);
PropertyManager& operator=(const PropertyManager&);
#endif
public:
PropertyManager(MeshT &mesh, const char *propname, bool existing = false) : mesh_(&mesh), retain_(existing), name_(propname) {
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() : mesh_(0), retain_(false) {
}
~PropertyManager() {
deleteProperty();
}
void swap(PropertyManager &rhs) {
std::swap(mesh_, rhs.mesh_);
std::swap(prop_, rhs.prop_);
std::swap(retain_, rhs.retain_);
std::swap(name_, rhs.name_);
}
static bool propertyExists(MeshT &mesh, const char *propname) {
PROPTYPE dummy;
return mesh.get_property_handle(dummy, propname);
}
bool isValid() const { return mesh_ != 0; }
operator bool() const { return isValid(); }
const PROPTYPE &getRawProperty() const { return prop_; }
const std::string &getName() const { return name_; }
MeshT &getMesh() const { return *mesh_; }
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
typedef PropertyManager<PROPTYPE, MeshT> Proxy;
PropertyManager(PropertyManager &&rhs) : mesh_(rhs.mesh_), prop_(rhs.prop_), retain_(rhs.retain_), name_(rhs.name_) {
rhs.retain_ = true;
}
PropertyManager &operator=(PropertyManager &&rhs) {
if (&rhs != this) {
deleteProperty();
mesh_ = rhs.mesh_;
prop_ = rhs.prop_;
retain_ = rhs.retain_;
name_ = rhs.name_;
rhs.retain_ = true;
}
return *this;
}
static PropertyManager createIfNotExists(MeshT &mesh, const char *propname) {
PROPTYPE dummy_prop;
PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
pm.retain();
return std::move(pm);
}
template<typename PROP_VALUE, typename ITERATOR_TYPE>
static PropertyManager createIfNotExists(MeshT &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);
}
template<typename PROP_VALUE, typename ITERATOR_RANGE>
static PropertyManager createIfNotExists(MeshT &mesh, const char *propname,
const ITERATOR_RANGE &range, const PROP_VALUE &init_value) {
return createIfNotExists(
mesh, propname, range.begin(), range.end(), init_value);
}
PropertyManager duplicate(const char *clone_name) {
PropertyManager pm(*mesh_, clone_name, false);
pm.mesh_->property(pm.prop_) = mesh_->property(prop_);
return pm;
}
PropertyManager move() {
return std::move(*this);
}
#else
class Proxy {
private:
Proxy(MeshT *mesh_, PROPTYPE prop_, bool retain_, const std::string &name_) :
mesh_(mesh_), prop_(prop_), retain_(retain_), name_(name_) {}
MeshT *mesh_;
PROPTYPE prop_;
bool retain_;
std::string name_;
friend class PropertyManager;
};
operator Proxy() {
Proxy p(mesh_, prop_, retain_, name_);
mesh_ = 0;
retain_ = true;
return p;
}
Proxy move() {
return (Proxy)*this;
}
PropertyManager(Proxy p) : mesh_(p.mesh_), prop_(p.prop_), retain_(p.retain_), name_(p.name_) {}
PropertyManager &operator=(Proxy p) {
PropertyManager(p).swap(*this);
return *this;
}
static Proxy createIfNotExists(MeshT &mesh, const char *propname) {
PROPTYPE dummy_prop;
PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
pm.retain();
return (Proxy)pm;
}
template<typename PROP_VALUE, typename ITERATOR_TYPE>
static Proxy createIfNotExists(MeshT &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 (Proxy)pm;
}
Proxy duplicate(const char *clone_name) {
PropertyManager pm(*mesh_, clone_name, false);
pm.mesh_->property(pm.prop_) = mesh_->property(prop_);
return (Proxy)pm;
}
#endif
inline void retain(bool doRetain = true) {
retain_ = doRetain;
}
inline PROPTYPE &operator* () {
return prop_;
}
inline const PROPTYPE &operator* () const {
return prop_;
}
template<typename HandleType>
inline typename PROPTYPE::reference operator[] (const HandleType &handle) {
return mesh_->property(prop_, handle);
}
template<typename HandleType>
inline typename PROPTYPE::const_reference operator[] (const HandleType &handle) const {
return mesh_->property(prop_, handle);
}
template<typename HandleTypeIterator, typename PROP_VALUE>
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<typename HandleTypeIteratorRange, typename PROP_VALUE>
void set_range(const HandleTypeIteratorRange &range,
const PROP_VALUE &value) {
set_range(range.begin(), range.end(), value);
}
#endif
template<typename HandleTypeIterator, typename PROPTYPE_2,
typename MeshT_2, typename HandleTypeIterator_2>
void copy_to(HandleTypeIterator begin, HandleTypeIterator end,
PropertyManager<PROPTYPE_2, MeshT_2> &dst_propmanager,
HandleTypeIterator_2 dst_begin, HandleTypeIterator_2 dst_end) const {
for (; begin != end && dst_begin != dst_end; ++begin, ++dst_begin) {
dst_propmanager[*dst_begin] = (*this)[*begin];
}
}
template<typename RangeType, typename PROPTYPE_2,
typename MeshT_2, typename RangeType_2>
void copy_to(const RangeType &range,
PropertyManager<PROPTYPE_2, MeshT_2> &dst_propmanager,
const RangeType_2 &dst_range) const {
copy_to(range.begin(), range.end(), dst_propmanager,
dst_range.begin(), dst_range.end());
}
template<typename RangeType, typename MeshT_2, typename RangeType_2>
static void copy(const char *prop_name,
MeshT &src_mesh, const RangeType &src_range,
MeshT_2 &dst_mesh, const RangeType_2 &dst_range) {
typedef OpenMesh::PropertyManager<PROPTYPE, MeshT> DstPM;
DstPM dst(DstPM::createIfNotExists(dst_mesh, prop_name));
typedef OpenMesh::PropertyManager<PROPTYPE, MeshT_2> SrcPM;
SrcPM src(src_mesh, prop_name, true);
src.copy_to(src_range, dst, dst_range);
}
private:
void deleteProperty() {
if (!retain_)
mesh_->remove_property(prop_);
}
private:
MeshT *mesh_;
PROPTYPE prop_;
bool retain_;
std::string name_;
};
template<typename PROPTYPE, typename MeshT>
PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromNew(MeshT &mesh, const char *propname) {
return PropertyManager<PROPTYPE, MeshT>(mesh, propname, false);
}
template<typename PROPTYPE, typename MeshT>
PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExisting(MeshT &mesh, const char *propname) {
return PropertyManager<PROPTYPE, MeshT>(mesh, propname, true);
}
template<typename PROPTYPE, typename MeshT>
PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname) {
return PropertyManager<PROPTYPE, MeshT>::createIfNotExists(mesh, propname);
}
template<typename PROPTYPE, typename MeshT,
typename ITERATOR_TYPE, typename PROP_VALUE>
PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(
MeshT &mesh, const char *propname,
const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
const PROP_VALUE &init_value) {
return PropertyManager<PROPTYPE, MeshT>::createIfNotExists(
mesh, propname, begin, end, init_value);
}
template<typename PROPTYPE, typename MeshT,
typename ITERATOR_RANGE, typename PROP_VALUE>
PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(
MeshT &mesh, const char *propname,
const ITERATOR_RANGE &range,
const PROP_VALUE &init_value) {
return makePropertyManagerFromExistingOrNew<PROPTYPE, MeshT>(
mesh, propname, range.begin(), range.end(), init_value);
}
} /* namespace OpenMesh */
#endif /* PROPERTYMANAGER_HH_ */
OpenMesh::PropertyManager::PropertyManager
PropertyManager(MeshT &mesh, const char *propname, bool existing=false)
Constructor.
Definition: PropertyManager.hh:130
OpenMesh::PropertyManager::makePropertyManagerFromExistingOrNew
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname, const ITERATOR_RANGE &range, const PROP_VALUE &init_value)
Definition: PropertyManager.hh:568
OpenMesh::PropertyManager::operator[]
PROPTYPE::reference operator[](const HandleType &handle)
Enables convenient access to the encapsulated property.
Definition: PropertyManager.hh:366
OpenMesh::PropertyManager::createIfNotExists
static Proxy createIfNotExists(MeshT &mesh, const char *propname)
Create a property manager for the supplied property and mesh.
Definition: PropertyManager.hh:299
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:64
OpenMesh::PropertyManager::makePropertyManagerFromExistingOrNew
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname)
Definition: PropertyManager.hh:530
OpenMesh::PropertyManager::copy_to
void copy_to(HandleTypeIterator begin, HandleTypeIterator end, PropertyManager< PROPTYPE_2, MeshT_2 > &dst_propmanager, HandleTypeIterator_2 dst_begin, HandleTypeIterator_2 dst_end) const
Conveniently transfer the values managed by one property manager onto the values managed by a differe...
Definition: PropertyManager.hh:437
OpenMesh::PropertyManager::set_range
void set_range(HandleTypeIterator begin, HandleTypeIterator end, const PROP_VALUE &value)
Conveniently set the property for an entire range of values.
Definition: PropertyManager.hh:407
OpenMesh::PropertyManager::operator*
PROPTYPE & operator*()
Access the encapsulated property.
Definition: PropertyManager.hh:347
OpenMesh::PropertyManager::copy
static void copy(const char *prop_name, MeshT &src_mesh, const RangeType &src_range, MeshT_2 &dst_mesh, const RangeType_2 &dst_range)
Copy the values of a property from a source range to a target range.
Definition: PropertyManager.hh:470
OpenMesh::PropertyManager::retain
void retain(bool doRetain=true)
Disable lifecycle management for this property.
Definition: PropertyManager.hh:340
OpenMesh::PropertyManager::Proxy
Definition: PropertyManager.hh:262
OpenMesh::PropertyManager::makePropertyManagerFromExisting
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExisting(MeshT &mesh, const char *propname)
Definition: PropertyManager.hh:519
OpenMesh::PropertyManager::makePropertyManagerFromNew
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromNew(MeshT &mesh, const char *propname)
Definition: PropertyManager.hh:504
OpenMesh::PropertyManager::createIfNotExists
static Proxy createIfNotExists(MeshT &mesh, const char *propname, const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, const PROP_VALUE &init_value)
Like createIfNotExists() with two parameters except, if the property doesn&#39;t exist, it is initialized with the supplied value over the supplied range after creation.
Definition: PropertyManager.hh:316
OpenMesh::PropertyManager
This class is intended to manage the lifecycle of properties.
Definition: PropertyManager.hh:94
OpenMesh::PropertyManager::makePropertyManagerFromExistingOrNew
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname, const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, const PROP_VALUE &init_value)
Definition: PropertyManager.hh:547