2015-04-28 11:54:17 +00:00
|
|
|
/* ========================================================================= *
|
2012-07-24 17:52:32 +00:00
|
|
|
* *
|
|
|
|
|
* OpenMesh *
|
2015-04-28 11:33:32 +00:00
|
|
|
* Copyright (c) 2001-2015, RWTH-Aachen University *
|
2015-04-28 13:07:46 +00:00
|
|
|
* Department of Computer Graphics and Multimedia *
|
2015-04-28 11:33:32 +00:00
|
|
|
* All rights reserved. *
|
|
|
|
|
* www.openmesh.org *
|
2012-07-24 17:52:32 +00:00
|
|
|
* *
|
|
|
|
|
*---------------------------------------------------------------------------*
|
2015-04-28 11:33:32 +00:00
|
|
|
* This file is part of OpenMesh. *
|
|
|
|
|
*---------------------------------------------------------------------------*
|
2012-07-24 17:52:32 +00:00
|
|
|
* *
|
2015-04-28 11:33:32 +00:00
|
|
|
* 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. *
|
2015-04-28 11:54:17 +00:00
|
|
|
* *
|
|
|
|
|
* ========================================================================= */
|
2012-07-24 17:52:32 +00:00
|
|
|
|
|
|
|
|
#ifndef PROPERTYMANAGER_HH_
|
|
|
|
|
#define PROPERTYMANAGER_HH_
|
|
|
|
|
|
2018-11-30 20:13:05 +01:00
|
|
|
#include <OpenMesh/Core/System/config.h>
|
|
|
|
|
#include <OpenMesh/Core/Utils/HandleToPropHandle.hh>
|
2019-10-31 14:09:08 +01:00
|
|
|
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
2012-07-24 17:52:32 +00:00
|
|
|
#include <sstream>
|
2013-05-23 09:36:41 +00:00
|
|
|
#include <stdexcept>
|
2013-08-07 08:03:39 +00:00
|
|
|
#include <string>
|
2012-07-24 17:52:32 +00:00
|
|
|
|
|
|
|
|
namespace OpenMesh {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This class is intended to manage the lifecycle of properties.
|
|
|
|
|
* It also defines convenience operators to access the encapsulated
|
|
|
|
|
* property's value.
|
|
|
|
|
*
|
2018-11-30 20:13:05 +01:00
|
|
|
* It is recommended to use the factory functions
|
|
|
|
|
* makeTemporaryProperty(), getProperty(), and getOrMakeProperty()
|
|
|
|
|
* to construct a PropertyManager, e.g.
|
2016-04-14 09:58:54 +02:00
|
|
|
*
|
2019-10-31 14:09:08 +01:00
|
|
|
* Note that the second template parameter is depcretated.
|
|
|
|
|
*
|
2016-04-14 09:58:54 +02:00
|
|
|
* \code
|
2018-11-30 20:13:05 +01:00
|
|
|
* {
|
|
|
|
|
* TriMesh mesh;
|
|
|
|
|
* auto visited = makeTemporaryProperty<VertexHandle, bool>(mesh);
|
2016-04-14 09:58:54 +02:00
|
|
|
*
|
2018-11-30 20:13:05 +01:00
|
|
|
* for (auto vh : mesh.vertices()) {
|
|
|
|
|
* if (!visited[vh]) {
|
|
|
|
|
* visitComponent(mesh, vh, visited);
|
|
|
|
|
* }
|
2016-04-14 09:58:54 +02:00
|
|
|
* }
|
2018-11-30 20:13:05 +01:00
|
|
|
* // The property is automatically removed at the end of the scope
|
2016-04-14 09:58:54 +02:00
|
|
|
* }
|
|
|
|
|
* \endcode
|
2012-07-24 17:52:32 +00:00
|
|
|
*/
|
2019-10-31 14:09:08 +01:00
|
|
|
template<typename PROPTYPE, typename MeshT = int>
|
2012-07-24 17:52:32 +00:00
|
|
|
class PropertyManager {
|
|
|
|
|
|
|
|
|
|
public:
|
2019-10-31 15:27:34 +01:00
|
|
|
using Value = typename PROPTYPE::Value;
|
|
|
|
|
using value_type = typename PROPTYPE::value_type;
|
|
|
|
|
using Handle = typename PROPTYPE::Handle;
|
2019-10-31 17:56:37 +01:00
|
|
|
using Self = PropertyManager<PROPTYPE, MeshT>;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// Mesh properties (MPropHandleT<...>) are stored differently than the other properties.
|
|
|
|
|
// This class implements different behavior when copying or swapping data from one
|
|
|
|
|
// property manager to a another one.
|
|
|
|
|
template <typename PropertyManager2, typename PropHandleT>
|
|
|
|
|
struct StorageT;
|
|
|
|
|
|
|
|
|
|
// specialization for Mesh Properties
|
|
|
|
|
template <typename PropertyManager2>
|
|
|
|
|
struct StorageT<PropertyManager2, MPropHandleT<Value>> {
|
|
|
|
|
static void copy(const PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
|
|
|
|
|
*to = *from;
|
|
|
|
|
}
|
|
|
|
|
static void swap(PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
|
|
|
|
|
std::swap(*to, *from);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// definition for other Mesh Properties
|
|
|
|
|
template <typename PropertyManager2, typename PropHandleT>
|
|
|
|
|
struct StorageT {
|
|
|
|
|
static void copy(const PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
|
|
|
|
|
from.copy_to(from.mesh_.template all_elements<Handle>(), to, to.mesh_.template all_elements<Handle>());
|
|
|
|
|
}
|
|
|
|
|
static void swap(PropertyManager<PROPTYPE, MeshT>& 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<Handle>());
|
|
|
|
|
rhs.mesh_.property(rhs.prop_).resize(rhs.mesh_.template n_elements<Handle>());
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using Storage = StorageT<Self, PROPTYPE>;
|
|
|
|
|
|
|
|
|
|
public:
|
2019-10-31 15:27:34 +01:00
|
|
|
|
2012-07-24 17:52:32 +00:00
|
|
|
/**
|
2019-10-31 15:27:34 +01:00
|
|
|
* @deprecated Use a constructor without \p existing and check existance with hasProperty() instead.
|
|
|
|
|
*
|
2012-07-24 17:52:32 +00:00
|
|
|
* 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.
|
2016-04-14 09:58:54 +02:00
|
|
|
*
|
2019-10-31 15:27:34 +01:00
|
|
|
* @see PropertyManager::getOrMakeProperty, PropertyManager::getProperty,
|
|
|
|
|
* PropertyManager::makeTemporaryProperty
|
2012-07-24 17:52:32 +00:00
|
|
|
*/
|
2019-10-31 15:27:34 +01:00
|
|
|
OM_DEPRECATED("Use the constructor without parameter 'existing' instead. Check for existance with hasProperty")
|
|
|
|
|
PropertyManager(PolyConnectivity& mesh, const char *propname, bool existing) : mesh_(mesh), retain_(existing), name_(propname) {
|
2012-07-24 17:52:32 +00:00
|
|
|
if (existing) {
|
2019-10-31 15:27:34 +01:00
|
|
|
if (!mesh_.get_property_handle(prop_, propname)) {
|
2012-07-24 17:52:32 +00:00
|
|
|
std::ostringstream oss;
|
|
|
|
|
oss << "Requested property handle \"" << propname << "\" does not exist.";
|
|
|
|
|
throw std::runtime_error(oss.str());
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2019-10-31 15:27:34 +01:00
|
|
|
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 (!mesh_.get_property_handle(prop_, propname)) {
|
|
|
|
|
mesh_.add_property(prop_, propname);
|
2012-07-24 17:52:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-31 15:27:34 +01:00
|
|
|
/**
|
|
|
|
|
* Constructor.
|
|
|
|
|
*
|
|
|
|
|
* Asks for a property with name propname and creates one if none exists. Lifetime is not managed.
|
|
|
|
|
* If the property is created it is initialized with \p initial_value
|
|
|
|
|
*
|
|
|
|
|
* @param mesh The mesh on which to create the property.
|
|
|
|
|
* @param initial_value
|
|
|
|
|
* @param propname The name of the property.
|
|
|
|
|
*/
|
2019-10-31 17:56:37 +01:00
|
|
|
PropertyManager(PolyConnectivity& mesh, const char *propname, const Value& intial_value) : mesh_(mesh), retain_(true), name_(propname) {
|
2019-10-31 15:27:34 +01:00
|
|
|
if (!mesh_.get_property_handle(prop_, propname)) {
|
|
|
|
|
mesh_.add_property(prop_, propname);
|
|
|
|
|
set_range(mesh_.all_elements<Handle>(), intial_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructor.
|
|
|
|
|
*
|
|
|
|
|
* Create an anonymous property. Lifetime is managed.
|
|
|
|
|
*
|
|
|
|
|
* @param mesh The mesh on which to create the property.
|
|
|
|
|
*/
|
|
|
|
|
PropertyManager(PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
|
|
|
|
|
mesh_.add_property(prop_, name_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructor.
|
|
|
|
|
*
|
|
|
|
|
* Create an anonymous property. Lifetime is managed.
|
|
|
|
|
* If the property is created it is initialized with \p initial_value
|
|
|
|
|
*
|
|
|
|
|
* @param mesh The mesh on which to create the property.
|
|
|
|
|
*/
|
2019-10-31 17:56:37 +01:00
|
|
|
PropertyManager(PolyConnectivity& mesh, const Value& intial_value) : mesh_(mesh), retain_(false), name_("") {
|
2019-10-31 15:27:34 +01:00
|
|
|
mesh_.add_property(prop_, name_);
|
|
|
|
|
set_range(mesh_.all_elements<Handle>(), intial_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructor.
|
|
|
|
|
*
|
|
|
|
|
* Create a wrapper around an existing property. Lifetime is not managed.
|
|
|
|
|
*
|
|
|
|
|
* @param mesh The mesh on which to create the property.
|
|
|
|
|
*/
|
|
|
|
|
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
|
|
|
|
|
{
|
|
|
|
|
mesh_.add_property(prop_, name_);
|
2019-10-31 17:56:37 +01:00
|
|
|
Storage::copy(rhs, *this);
|
2019-10-31 15:27:34 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PropertyManager& operator=(const PropertyManager& rhs)
|
|
|
|
|
{
|
|
|
|
|
if (&mesh_ == &rhs.mesh_ && prop_ == rhs.prop_)
|
|
|
|
|
; // nothing to do
|
|
|
|
|
else
|
2019-10-31 17:56:37 +01:00
|
|
|
Storage::copy(rhs, *this);
|
2019-10-31 15:27:34 +01:00
|
|
|
return *this;
|
2013-05-23 09:36:41 +00:00
|
|
|
}
|
|
|
|
|
|
2012-07-24 17:52:32 +00:00
|
|
|
~PropertyManager() {
|
|
|
|
|
deleteProperty();
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-17 06:28:07 +00:00
|
|
|
void swap(PropertyManager &rhs) {
|
|
|
|
|
std::swap(mesh_, rhs.mesh_);
|
|
|
|
|
std::swap(prop_, rhs.prop_);
|
|
|
|
|
std::swap(retain_, rhs.retain_);
|
2013-08-07 08:03:39 +00:00
|
|
|
std::swap(name_, rhs.name_);
|
2012-09-17 06:28:07 +00:00
|
|
|
}
|
|
|
|
|
|
2019-10-31 14:09:08 +01:00
|
|
|
static bool propertyExists(PolyConnectivity &mesh, const char *propname) {
|
2013-02-20 12:19:26 +00:00
|
|
|
PROPTYPE dummy;
|
|
|
|
|
return mesh.get_property_handle(dummy, propname);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-31 14:09:08 +01:00
|
|
|
bool isValid() const { return prop_.is_valid(); }
|
2013-05-23 09:36:41 +00:00
|
|
|
operator bool() const { return isValid(); }
|
|
|
|
|
|
|
|
|
|
const PROPTYPE &getRawProperty() const { return prop_; }
|
|
|
|
|
|
2013-08-07 08:03:39 +00:00
|
|
|
const std::string &getName() const { return name_; }
|
|
|
|
|
|
2019-10-31 14:09:08 +01:00
|
|
|
/**
|
|
|
|
|
* 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<bool>(mesh);
|
|
|
|
|
* TriMesh& mesh_ref = visited.getMesh<TriMesh>();
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
template <typename MeshType >
|
|
|
|
|
MeshType& getMesh() const { return dynamic_cast<MeshType&>(mesh_); }
|
|
|
|
|
|
|
|
|
|
MeshT& getMesh() const { return dynamic_cast<MeshT&>(mesh_); }
|
2013-10-03 09:12:12 +00:00
|
|
|
|
2017-04-25 15:50:30 +02:00
|
|
|
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
2015-06-19 13:18:43 +00:00
|
|
|
/// Only for pre C++11 compatibility.
|
|
|
|
|
|
2019-10-31 14:09:08 +01:00
|
|
|
typedef PropertyManager<PROPTYPE> Proxy;
|
2015-06-19 13:18:43 +00:00
|
|
|
|
2012-07-24 17:52:32 +00:00
|
|
|
/**
|
|
|
|
|
* Move constructor. Transfers ownership (delete responsibility).
|
|
|
|
|
*/
|
2019-10-31 15:27:34 +01:00
|
|
|
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
|
2012-07-24 17:52:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Move assignment. Transfers ownership (delete responsibility).
|
|
|
|
|
*/
|
2019-10-31 15:27:34 +01:00
|
|
|
PropertyManager& operator=(PropertyManager&& rhs)
|
|
|
|
|
{
|
|
|
|
|
if ((&mesh_ != &rhs.mesh_) || (prop_ != rhs.prop_))
|
|
|
|
|
{
|
|
|
|
|
if (rhs.retain_)
|
|
|
|
|
{
|
|
|
|
|
// retained properties cannot be invalidated. Copy instead
|
2019-10-31 17:56:37 +01:00
|
|
|
Storage::copy(rhs, *this);
|
2019-10-31 15:27:34 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// switch the data stored in the properties
|
2019-10-31 17:56:37 +01:00
|
|
|
Storage::swap(rhs, *this);
|
2019-10-31 15:27:34 +01:00
|
|
|
// remove the property from rhs
|
|
|
|
|
rhs.mesh_.remove_property(rhs.prop_);
|
|
|
|
|
// invalidate prop_
|
|
|
|
|
rhs.prop_.invalidate();
|
|
|
|
|
}
|
2016-04-14 09:58:54 +02:00
|
|
|
}
|
2012-07-24 17:52:32 +00:00
|
|
|
return *this;
|
|
|
|
|
}
|
2012-09-11 18:16:01 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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.
|
2016-04-14 09:58:54 +02:00
|
|
|
*
|
|
|
|
|
* @see makePropertyManagerFromExistingOrNew
|
2012-09-11 18:16:01 +00:00
|
|
|
*/
|
2019-10-31 14:09:08 +01:00
|
|
|
static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname) {
|
2019-10-31 15:27:34 +01:00
|
|
|
return PropertyManager(mesh, propname);
|
2012-09-11 18:16:01 +00:00
|
|
|
}
|
2012-09-17 06:28:07 +00:00
|
|
|
|
2016-09-12 16:58:03 +02:00
|
|
|
/**
|
|
|
|
|
* 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<typename PROP_VALUE, typename ITERATOR_TYPE>
|
2019-10-31 14:09:08 +01:00
|
|
|
static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname,
|
2016-09-12 16:58:03 +02:00
|
|
|
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<typename PROP_VALUE, typename ITERATOR_RANGE>
|
2019-10-31 14:09:08 +01:00
|
|
|
static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname,
|
2016-09-12 16:58:03 +02:00
|
|
|
const ITERATOR_RANGE &range, const PROP_VALUE &init_value) {
|
|
|
|
|
return createIfNotExists(
|
|
|
|
|
mesh, propname, range.begin(), range.end(), init_value);
|
|
|
|
|
}
|
2014-02-13 09:25:46 +00:00
|
|
|
|
|
|
|
|
PropertyManager duplicate(const char *clone_name) {
|
2019-10-31 15:27:34 +01:00
|
|
|
PropertyManager pm(mesh_, clone_name, false);
|
|
|
|
|
pm.mesh_.property(pm.prop_) = mesh_.property(prop_);
|
2016-04-14 09:58:54 +02:00
|
|
|
return pm;
|
2014-02-13 09:25:46 +00:00
|
|
|
}
|
|
|
|
|
|
2014-06-26 11:38:13 +00:00
|
|
|
/**
|
|
|
|
|
* Included for backwards compatibility with non-C++11 version.
|
|
|
|
|
*/
|
|
|
|
|
PropertyManager move() {
|
|
|
|
|
return std::move(*this);
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-17 06:28:07 +00:00
|
|
|
#else
|
|
|
|
|
class Proxy {
|
|
|
|
|
private:
|
2019-10-31 14:09:08 +01:00
|
|
|
Proxy(PolyConnectivity *mesh_, PROPTYPE prop_, bool retain_, const std::string &name_) :
|
2013-08-07 08:03:39 +00:00
|
|
|
mesh_(mesh_), prop_(prop_), retain_(retain_), name_(name_) {}
|
2019-10-31 14:09:08 +01:00
|
|
|
PolyConnectivity *mesh_;
|
2012-09-17 06:28:07 +00:00
|
|
|
PROPTYPE prop_;
|
|
|
|
|
bool retain_;
|
2013-08-07 08:03:39 +00:00
|
|
|
std::string name_;
|
2012-09-17 06:28:07 +00:00
|
|
|
|
|
|
|
|
friend class PropertyManager;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
operator Proxy() {
|
2013-08-07 08:03:39 +00:00
|
|
|
Proxy p(mesh_, prop_, retain_, name_);
|
2012-09-17 06:28:07 +00:00
|
|
|
mesh_ = 0;
|
|
|
|
|
retain_ = true;
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-26 11:38:13 +00:00
|
|
|
Proxy move() {
|
|
|
|
|
return (Proxy)*this;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-07 08:03:39 +00:00
|
|
|
PropertyManager(Proxy p) : mesh_(p.mesh_), prop_(p.prop_), retain_(p.retain_), name_(p.name_) {}
|
2012-09-17 06:28:07 +00:00
|
|
|
|
|
|
|
|
PropertyManager &operator=(Proxy p) {
|
|
|
|
|
PropertyManager(p).swap(*this);
|
|
|
|
|
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.
|
2016-04-14 09:58:54 +02:00
|
|
|
*
|
|
|
|
|
* @see makePropertyManagerFromExistingOrNew
|
2012-09-17 06:28:07 +00:00
|
|
|
*/
|
2019-10-31 14:09:08 +01:00
|
|
|
static Proxy createIfNotExists(PolyConnectivity &mesh, const char *propname) {
|
2012-09-17 06:28:07 +00:00
|
|
|
PROPTYPE dummy_prop;
|
|
|
|
|
PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
|
|
|
|
|
pm.retain();
|
|
|
|
|
return (Proxy)pm;
|
|
|
|
|
}
|
2014-02-13 09:25:46 +00:00
|
|
|
|
2016-09-12 16:58:03 +02:00
|
|
|
/**
|
|
|
|
|
* 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<typename PROP_VALUE, typename ITERATOR_TYPE>
|
2019-10-31 14:09:08 +01:00
|
|
|
static Proxy createIfNotExists(PolyConnectivity &mesh, const char *propname,
|
2016-09-12 16:58:03 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-13 09:25:46 +00:00
|
|
|
Proxy duplicate(const char *clone_name) {
|
|
|
|
|
PropertyManager pm(*mesh_, clone_name, false);
|
2019-10-31 15:27:34 +01:00
|
|
|
pm.mesh_.property(pm.prop_) = mesh_.property(prop_);
|
2014-02-13 09:25:46 +00:00
|
|
|
return (Proxy)pm;
|
|
|
|
|
}
|
2012-07-24 17:52:32 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/**
|
2019-04-03 15:45:23 +02:00
|
|
|
* Access the value of the encapsulated mesh property.
|
|
|
|
|
*
|
|
|
|
|
* Example:
|
|
|
|
|
* @code
|
|
|
|
|
* PolyMesh m;
|
|
|
|
|
* auto description = getOrMakeProperty<void, std::string>(m, "description");
|
|
|
|
|
* *description = "This is a very nice mesh.";
|
|
|
|
|
* @endcode
|
|
|
|
|
*
|
|
|
|
|
* @note This method is only used for mesh properties.
|
2012-07-24 17:52:32 +00:00
|
|
|
*/
|
2019-04-03 15:45:23 +02:00
|
|
|
typename PROPTYPE::reference& operator*() {
|
2019-10-31 15:27:34 +01:00
|
|
|
return mesh_.mproperty(prop_)[0];
|
2012-07-24 17:52:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-04-03 15:45:23 +02:00
|
|
|
* Access the value of the encapsulated mesh property.
|
|
|
|
|
*
|
|
|
|
|
* Example:
|
|
|
|
|
* @code
|
|
|
|
|
* PolyMesh m;
|
|
|
|
|
* auto description = getProperty<void, std::string>(m, "description");
|
|
|
|
|
* std::cout << *description << std::endl;
|
|
|
|
|
* @endcode
|
|
|
|
|
*
|
|
|
|
|
* @note This method is only used for mesh properties.
|
2012-07-24 17:52:32 +00:00
|
|
|
*/
|
2019-04-03 15:45:23 +02:00
|
|
|
typename PROPTYPE::const_reference& operator*() const {
|
2019-10-31 15:27:34 +01:00
|
|
|
return mesh_.mproperty(prop_)[0];
|
2012-07-24 17:52:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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<typename HandleType>
|
|
|
|
|
inline typename PROPTYPE::reference operator[] (const HandleType &handle) {
|
2019-10-31 15:27:34 +01:00
|
|
|
return mesh_.property(prop_, handle);
|
2012-07-24 17:52:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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<typename HandleType>
|
|
|
|
|
inline typename PROPTYPE::const_reference operator[] (const HandleType &handle) const {
|
2019-10-31 15:27:34 +01:00
|
|
|
return mesh_.property(prop_, handle);
|
2012-07-24 17:52:32 +00:00
|
|
|
}
|
|
|
|
|
|
2014-02-25 14:01:12 +00:00
|
|
|
/**
|
|
|
|
|
* Conveniently set the property for an entire range of values.
|
|
|
|
|
*
|
|
|
|
|
* Examples:
|
|
|
|
|
* \code
|
|
|
|
|
* MeshT mesh;
|
2019-10-31 14:09:08 +01:00
|
|
|
* PropertyManager<VPropHandleT<double>> distance(
|
2014-02-25 14:01:12 +00:00
|
|
|
* mesh, "distance.plugin-example.i8.informatik.rwth-aachen.de");
|
|
|
|
|
* distance.set_range(
|
|
|
|
|
* mesh.vertices_begin(), mesh.vertices_end(),
|
|
|
|
|
* std::numeric_limits<double>::infinity());
|
|
|
|
|
* \endcode
|
|
|
|
|
* or
|
|
|
|
|
* \code
|
|
|
|
|
* MeshT::VertexHandle vh;
|
|
|
|
|
* distance.set_range(
|
|
|
|
|
* mesh.vv_begin(vh), mesh.vv_end(vh),
|
|
|
|
|
* std::numeric_limits<double>::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.
|
|
|
|
|
*/
|
2015-05-12 09:55:33 +00:00
|
|
|
template<typename HandleTypeIterator, typename PROP_VALUE>
|
2014-02-25 14:01:12 +00:00
|
|
|
void set_range(HandleTypeIterator begin, HandleTypeIterator end,
|
2015-05-12 09:55:33 +00:00
|
|
|
const PROP_VALUE &value) {
|
2014-02-25 14:01:12 +00:00
|
|
|
for (; begin != end; ++begin)
|
|
|
|
|
(*this)[*begin] = value;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 15:50:30 +02:00
|
|
|
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
2016-09-12 16:57:33 +02:00
|
|
|
template<typename HandleTypeIteratorRange, typename PROP_VALUE>
|
2016-09-12 17:06:56 +02:00
|
|
|
void set_range(const HandleTypeIteratorRange &range,
|
2016-09-12 16:57:33 +02:00
|
|
|
const PROP_VALUE &value) {
|
|
|
|
|
set_range(range.begin(), range.end(), value);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2014-10-08 08:49:06 +00:00
|
|
|
/**
|
|
|
|
|
* 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<typename HandleTypeIterator, typename PROPTYPE_2,
|
2019-10-31 14:09:08 +01:00
|
|
|
typename HandleTypeIterator_2>
|
2014-10-08 08:49:06 +00:00
|
|
|
void copy_to(HandleTypeIterator begin, HandleTypeIterator end,
|
2019-10-31 14:09:08 +01:00
|
|
|
PropertyManager<PROPTYPE_2> &dst_propmanager,
|
2014-10-08 08:49:06 +00:00
|
|
|
HandleTypeIterator_2 dst_begin, HandleTypeIterator_2 dst_end) const {
|
|
|
|
|
|
|
|
|
|
for (; begin != end && dst_begin != dst_end; ++begin, ++dst_begin) {
|
2014-11-05 17:03:36 +00:00
|
|
|
dst_propmanager[*dst_begin] = (*this)[*begin];
|
2014-10-08 08:49:06 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename RangeType, typename PROPTYPE_2,
|
2019-10-31 14:09:08 +01:00
|
|
|
typename RangeType_2>
|
2014-11-05 17:03:36 +00:00
|
|
|
void copy_to(const RangeType &range,
|
2019-10-31 14:09:08 +01:00
|
|
|
PropertyManager<PROPTYPE_2> &dst_propmanager,
|
2014-11-05 17:03:36 +00:00
|
|
|
const RangeType_2 &dst_range) const {
|
2014-10-08 08:49:06 +00:00
|
|
|
copy_to(range.begin(), range.end(), dst_propmanager,
|
|
|
|
|
dst_range.begin(), dst_range.end());
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-31 17:56:37 +01:00
|
|
|
|
2014-11-05 17:03:36 +00:00
|
|
|
/**
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
2019-10-31 14:09:08 +01:00
|
|
|
template<typename RangeType, typename RangeType_2>
|
2014-11-05 17:03:36 +00:00
|
|
|
static void copy(const char *prop_name,
|
2019-10-31 14:09:08 +01:00
|
|
|
PolyConnectivity &src_mesh, const RangeType &src_range,
|
|
|
|
|
PolyConnectivity &dst_mesh, const RangeType_2 &dst_range) {
|
2014-11-05 17:03:36 +00:00
|
|
|
|
2019-10-31 14:09:08 +01:00
|
|
|
typedef OpenMesh::PropertyManager<PROPTYPE> DstPM;
|
2014-11-05 17:03:36 +00:00
|
|
|
DstPM dst(DstPM::createIfNotExists(dst_mesh, prop_name));
|
|
|
|
|
|
2019-10-31 14:09:08 +01:00
|
|
|
typedef OpenMesh::PropertyManager<PROPTYPE> SrcPM;
|
2014-11-05 17:03:36 +00:00
|
|
|
SrcPM src(src_mesh, prop_name, true);
|
|
|
|
|
|
|
|
|
|
src.copy_to(src_range, dst, dst_range);
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-24 17:52:32 +00:00
|
|
|
private:
|
|
|
|
|
void deleteProperty() {
|
2019-10-31 15:27:34 +01:00
|
|
|
if (!retain_ && prop_.is_valid())
|
|
|
|
|
mesh_.remove_property(prop_);
|
2012-07-24 17:52:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2019-10-31 15:27:34 +01:00
|
|
|
PolyConnectivity& mesh_;
|
2012-07-24 17:52:32 +00:00
|
|
|
PROPTYPE prop_;
|
|
|
|
|
bool retain_;
|
2013-08-07 08:03:39 +00:00
|
|
|
std::string name_;
|
2012-07-24 17:52:32 +00:00
|
|
|
};
|
|
|
|
|
|
2018-11-30 20:13:05 +01:00
|
|
|
/** @relates PropertyManager
|
2019-10-31 17:56:37 +01:00
|
|
|
*
|
|
|
|
|
* @deprecated Temporary properties should not have a name.
|
2018-11-30 20:13:05 +01:00
|
|
|
*
|
|
|
|
|
* 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<FaceHandle, bool>(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
|
|
|
|
|
*/
|
2019-10-31 14:09:08 +01:00
|
|
|
template<typename ElementT, typename T>
|
|
|
|
|
PropertyManager<typename HandleToPropHandle<ElementT, T>::type>
|
2019-10-31 17:56:37 +01:00
|
|
|
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) {
|
2019-10-31 14:09:08 +01:00
|
|
|
return PropertyManager<typename HandleToPropHandle<ElementT, T>::type>(mesh, propname, false);
|
2018-11-30 20:13:05 +01:00
|
|
|
}
|
|
|
|
|
|
2019-10-31 17:56:37 +01:00
|
|
|
/** @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<FaceHandle, bool>(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<typename ElementT, typename T>
|
|
|
|
|
PropertyManager<typename HandleToPropHandle<ElementT, T>::type>
|
|
|
|
|
makeTemporaryProperty(PolyConnectivity &mesh) {
|
|
|
|
|
return PropertyManager<typename HandleToPropHandle<ElementT, T>::type>(mesh);
|
|
|
|
|
}
|
2019-10-31 15:27:34 +01:00
|
|
|
|
|
|
|
|
|
2019-10-31 17:56:37 +01:00
|
|
|
/** @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<FaceHandle, bool>(m, "is_quad")) {
|
|
|
|
|
* // We now know the property exists: getProperty won't throw.
|
|
|
|
|
* auto is_quad = getProperty<FaceHandle, bool>(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<typename ElementT, typename T>
|
|
|
|
|
bool
|
|
|
|
|
hasProperty(const PolyConnectivity &mesh, const char *propname) {
|
|
|
|
|
typename HandleToPropHandle<ElementT, T>::type ph;
|
|
|
|
|
return mesh.get_property_handle(ph, propname);
|
|
|
|
|
}
|
2019-10-31 15:27:34 +01:00
|
|
|
|
2018-11-30 20:13:05 +01:00
|
|
|
/** @relates PropertyManager
|
|
|
|
|
*
|
|
|
|
|
* Obtains a handle to a named property.
|
|
|
|
|
*
|
|
|
|
|
* Example:
|
|
|
|
|
* @code
|
|
|
|
|
* PolyMesh m;
|
|
|
|
|
* {
|
|
|
|
|
* try {
|
|
|
|
|
* auto is_quad = getProperty<FaceHandle, bool>(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
|
|
|
|
|
*/
|
2019-10-31 14:09:08 +01:00
|
|
|
template<typename ElementT, typename T>
|
|
|
|
|
PropertyManager<typename HandleToPropHandle<ElementT, T>::type>
|
|
|
|
|
getProperty(PolyConnectivity &mesh, const char *propname) {
|
2019-10-31 17:56:37 +01:00
|
|
|
if (!hasProperty<ElementT, T>(mesh, propname))
|
|
|
|
|
{
|
|
|
|
|
std::ostringstream oss;
|
|
|
|
|
oss << "Requested property handle \"" << propname << "\" does not exist.";
|
|
|
|
|
throw std::runtime_error(oss.str());
|
|
|
|
|
}
|
|
|
|
|
return PropertyManager<typename HandleToPropHandle<ElementT, T>::type>(mesh, propname);
|
2018-11-30 20:13:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @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<FaceHandle, bool>(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<FaceHandle, bool>(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
|
|
|
|
|
*/
|
2019-10-31 14:09:08 +01:00
|
|
|
template<typename ElementT, typename T>
|
|
|
|
|
PropertyManager<typename HandleToPropHandle<ElementT, T>::type>
|
|
|
|
|
getOrMakeProperty(PolyConnectivity &mesh, const char *propname) {
|
|
|
|
|
return PropertyManager<typename HandleToPropHandle<ElementT, T>::type>::createIfNotExists(mesh, propname);
|
2018-11-30 20:13:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @relates PropertyManager
|
|
|
|
|
* @deprecated Use makeTemporaryProperty() instead.
|
|
|
|
|
*
|
2016-04-14 09:58:54 +02:00
|
|
|
* Creates a new property whose lifecycle is managed by the returned
|
|
|
|
|
* PropertyManager.
|
|
|
|
|
*
|
2018-11-30 20:13:05 +01:00
|
|
|
* Intended for temporary properties. Shadows any existing properties of
|
2016-04-14 09:58:54 +02:00
|
|
|
* matching name and type.
|
|
|
|
|
*/
|
2019-10-31 14:09:08 +01:00
|
|
|
template<typename PROPTYPE>
|
2018-11-30 20:13:05 +01:00
|
|
|
OM_DEPRECATED("Use makeTemporaryProperty instead.")
|
2019-10-31 14:09:08 +01:00
|
|
|
PropertyManager<PROPTYPE> makePropertyManagerFromNew(PolyConnectivity &mesh, const char *propname)
|
2018-11-30 20:13:05 +01:00
|
|
|
{
|
2019-10-31 14:09:08 +01:00
|
|
|
return PropertyManager<PROPTYPE>(mesh, propname, false);
|
2016-04-14 09:58:54 +02:00
|
|
|
}
|
|
|
|
|
|
2016-05-23 15:04:28 +02:00
|
|
|
/** \relates PropertyManager
|
2018-11-30 20:13:05 +01:00
|
|
|
* @deprecated Use getProperty() instead.
|
|
|
|
|
*
|
2016-04-14 09:58:54 +02:00
|
|
|
* 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.
|
|
|
|
|
*/
|
2019-10-31 14:09:08 +01:00
|
|
|
template<typename PROPTYPE>
|
2018-11-30 20:13:05 +01:00
|
|
|
OM_DEPRECATED("Use getProperty instead.")
|
2019-10-31 14:09:08 +01:00
|
|
|
PropertyManager<PROPTYPE> makePropertyManagerFromExisting(PolyConnectivity &mesh, const char *propname)
|
2018-11-30 20:13:05 +01:00
|
|
|
{
|
2019-10-31 14:09:08 +01:00
|
|
|
return PropertyManager<PROPTYPE>(mesh, propname, true);
|
2016-04-14 09:58:54 +02:00
|
|
|
}
|
|
|
|
|
|
2018-11-30 20:13:05 +01:00
|
|
|
/** @relates PropertyManager
|
|
|
|
|
* @deprecated Use getOrMakeProperty() instead.
|
|
|
|
|
*
|
2016-04-14 09:58:54 +02:00
|
|
|
* 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.
|
|
|
|
|
*/
|
2019-10-31 14:09:08 +01:00
|
|
|
template<typename PROPTYPE>
|
2018-11-30 20:13:05 +01:00
|
|
|
OM_DEPRECATED("Use getOrMakeProperty instead.")
|
2019-10-31 14:09:08 +01:00
|
|
|
PropertyManager<PROPTYPE> makePropertyManagerFromExistingOrNew(PolyConnectivity &mesh, const char *propname)
|
2018-11-30 20:13:05 +01:00
|
|
|
{
|
2019-10-31 14:09:08 +01:00
|
|
|
return PropertyManager<PROPTYPE>::createIfNotExists(mesh, propname);
|
2016-04-14 09:58:54 +02:00
|
|
|
}
|
|
|
|
|
|
2018-11-30 20:13:05 +01:00
|
|
|
/** @relates PropertyManager
|
2016-09-12 16:58:03 +02:00
|
|
|
* 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.
|
|
|
|
|
*/
|
2019-10-31 15:27:34 +01:00
|
|
|
template<typename PROPTYPE,
|
2016-09-12 16:58:03 +02:00
|
|
|
typename ITERATOR_TYPE, typename PROP_VALUE>
|
2019-04-03 15:44:17 +02:00
|
|
|
OM_DEPRECATED("Use getOrMakeProperty instead.")
|
2019-10-31 15:27:34 +01:00
|
|
|
PropertyManager<PROPTYPE> makePropertyManagerFromExistingOrNew(
|
|
|
|
|
PolyConnectivity &mesh, const char *propname,
|
2016-09-12 16:58:03 +02:00
|
|
|
const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
|
|
|
|
|
const PROP_VALUE &init_value) {
|
2019-10-31 15:27:34 +01:00
|
|
|
return PropertyManager<PROPTYPE>::createIfNotExists(
|
2016-09-12 16:58:03 +02:00
|
|
|
mesh, propname, begin, end, init_value);
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-30 20:13:05 +01:00
|
|
|
/** @relates PropertyManager
|
2016-09-12 16:58:03 +02:00
|
|
|
* 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.
|
|
|
|
|
*/
|
2019-10-31 14:09:08 +01:00
|
|
|
template<typename PROPTYPE,
|
2016-09-12 16:58:03 +02:00
|
|
|
typename ITERATOR_RANGE, typename PROP_VALUE>
|
2019-04-03 15:44:17 +02:00
|
|
|
OM_DEPRECATED("Use getOrMakeProperty instead.")
|
2019-10-31 14:09:08 +01:00
|
|
|
PropertyManager<PROPTYPE> makePropertyManagerFromExistingOrNew(
|
|
|
|
|
PolyConnectivity &mesh, const char *propname,
|
2016-09-12 16:58:03 +02:00
|
|
|
const ITERATOR_RANGE &range,
|
|
|
|
|
const PROP_VALUE &init_value) {
|
2019-10-31 14:09:08 +01:00
|
|
|
return makePropertyManagerFromExistingOrNew<PROPTYPE>(
|
2016-09-12 16:58:03 +02:00
|
|
|
mesh, propname, range.begin(), range.end(), init_value);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-31 15:27:34 +01:00
|
|
|
|
|
|
|
|
/** @relates PropertyManager
|
|
|
|
|
* Returns a convenience wrapper around the points property of a mesh.
|
|
|
|
|
*/
|
|
|
|
|
template<typename MeshT>
|
|
|
|
|
PropertyManager<OpenMesh::VPropHandleT<typename MeshT::Point>>
|
|
|
|
|
getPointsProperty(MeshT &mesh) {
|
|
|
|
|
return PropertyManager<OpenMesh::VPropHandleT<typename MeshT::Point>>(mesh, mesh.points_property_handle());
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-31 17:56:37 +01:00
|
|
|
template <typename HandleT, typename T>
|
|
|
|
|
using Prop = PropertyManager<typename PropHandle<HandleT>::template type<T>>;
|
2019-10-31 15:27:34 +01:00
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
using VProp = PropertyManager<OpenMesh::VPropHandleT<T>>;
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
using HProp = PropertyManager<OpenMesh::HPropHandleT<T>>;
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
using EProp = PropertyManager<OpenMesh::EPropHandleT<T>>;
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
using FProp = PropertyManager<OpenMesh::FPropHandleT<T>>;
|
|
|
|
|
|
2019-10-31 17:56:37 +01:00
|
|
|
template <typename T>
|
|
|
|
|
using MProp = PropertyManager<OpenMesh::MPropHandleT<T>>;
|
|
|
|
|
|
2019-10-31 15:27:34 +01:00
|
|
|
|
2012-07-24 17:52:32 +00:00
|
|
|
} /* namespace OpenMesh */
|
|
|
|
|
#endif /* PROPERTYMANAGER_HH_ */
|