From 56403e3dc9c8ece2fc4101b57763d97990a72c32 Mon Sep 17 00:00:00 2001 From: Janis Born Date: Wed, 3 Apr 2019 15:44:17 +0200 Subject: [PATCH 1/4] mark more old functions as deprecated --- src/OpenMesh/Core/Utils/PropertyManager.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/OpenMesh/Core/Utils/PropertyManager.hh b/src/OpenMesh/Core/Utils/PropertyManager.hh index ea5f0e1c..5bb6aba1 100644 --- a/src/OpenMesh/Core/Utils/PropertyManager.hh +++ b/src/OpenMesh/Core/Utils/PropertyManager.hh @@ -641,6 +641,7 @@ PropertyManager makePropertyManagerFromExistingOrNew(MeshT &mes */ template +OM_DEPRECATED("Use getOrMakeProperty instead.") PropertyManager makePropertyManagerFromExistingOrNew( MeshT &mesh, const char *propname, const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, @@ -662,6 +663,7 @@ PropertyManager makePropertyManagerFromExistingOrNew( */ template +OM_DEPRECATED("Use getOrMakeProperty instead.") PropertyManager makePropertyManagerFromExistingOrNew( MeshT &mesh, const char *propname, const ITERATOR_RANGE &range, From fc63402d1024cbbc5c852135e66291d8a2e4d680 Mon Sep 17 00:00:00 2001 From: Janis Born Date: Wed, 3 Apr 2019 15:45:23 +0200 Subject: [PATCH 2/4] change PropertyManager::operator* to access the property value for mesh properties --- src/OpenMesh/Core/Utils/PropertyManager.hh | 30 +++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/OpenMesh/Core/Utils/PropertyManager.hh b/src/OpenMesh/Core/Utils/PropertyManager.hh index 5bb6aba1..7ee74f6f 100644 --- a/src/OpenMesh/Core/Utils/PropertyManager.hh +++ b/src/OpenMesh/Core/Utils/PropertyManager.hh @@ -325,17 +325,35 @@ class PropertyManager { } /** - * Access the encapsulated property. + * 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. */ - inline PROPTYPE &operator* () { - return prop_; + typename PROPTYPE::reference& operator*() { + return mesh_->mproperty(prop_)[0]; } /** - * Access the encapsulated property. + * 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. */ - inline const PROPTYPE &operator* () const { - return prop_; + typename PROPTYPE::const_reference& operator*() const { + return mesh_->mproperty(prop_)[0]; } /** From ade4f58f1ae2bb4efcd9073062a8094983f9f73e Mon Sep 17 00:00:00 2001 From: Janis Born Date: Wed, 3 Apr 2019 15:45:44 +0200 Subject: [PATCH 3/4] add hasProperty function --- src/OpenMesh/Core/Utils/PropertyManager.hh | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/OpenMesh/Core/Utils/PropertyManager.hh b/src/OpenMesh/Core/Utils/PropertyManager.hh index 7ee74f6f..fb3860f5 100644 --- a/src/OpenMesh/Core/Utils/PropertyManager.hh +++ b/src/OpenMesh/Core/Utils/PropertyManager.hh @@ -596,6 +596,34 @@ getOrMakeProperty(MeshT &mesh, const char *propname) { return PropertyManager::type, MeshT>::createIfNotExists(mesh, propname); } +/** @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 MeshT &mesh, const char *propname) { + typename HandleToPropHandle::type ph; + return mesh.get_property_handle(ph, propname); +} + /** @relates PropertyManager * @deprecated Use makeTemporaryProperty() instead. * From 7c3d9c303c4dcea68a450cb2ade15025de7fad14 Mon Sep 17 00:00:00 2001 From: Janis Born Date: Wed, 3 Apr 2019 15:46:21 +0200 Subject: [PATCH 4/4] update custom properties tutorial to mention mesh properties and hasProperty --- Doc/tutorial_03.docu | 53 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/Doc/tutorial_03.docu b/Doc/tutorial_03.docu index 3e0cf797..ba76515c 100644 --- a/Doc/tutorial_03.docu +++ b/Doc/tutorial_03.docu @@ -17,11 +17,35 @@ Custom properties can be conveniently created and attached to meshes with the fo - getProperty() is used for accessing an existing permanent named property on a mesh. All three functions take two template arguments: -- First, the type of the mesh element that the property is attached to (i.e. OpenMesh::VertexHandle, OpenMesh::HalfedgeHandle, OpenMesh::EdgeHandle, or OpenMesh::FaceHandle). +- First, the type of the mesh element that the property is attached to (i.e. OpenMesh::VertexHandle, OpenMesh::HalfedgeHandle, OpenMesh::EdgeHandle, or OpenMesh::FaceHandle). Mesh properties (i.e. singleton properties that are attached to an entire mesh instead of individual elements) are accessed by passing \c void instead of a handle type. - Second, the type of the property value that is attached to each element (e.g., \p int, \p double, etc.). All three functions return a handle object (of type OpenMesh::PropertyManager) that manages the lifetime of the property and provides read / write access to its values. +Here are a few examples of how to create and access mesh properties: + +\code +// Add a temporary mesh property that stores a double value for every vertex +auto temperature = OpenMesh::getOrMakeProperty(mesh, "temperature"); +OpenMesh::VertexHandle vh = ...; +temperature[vh] = 1.0; +// The temperature property will be removed from the mesh when the handle reaches the end of the scope. + +// Obtain an existing mesh property that stores a 2D vector for every halfedge +// (Beware: the next line might throw if the expected property doesn't exist.) +auto uv = OpenMesh::getProperty(mesh, "uv"); +OpenMesh::VertexHandle heh = ...; +std::cout << temperature[heh][0] << " " << temperature[heh][1] << std::endl; + +// Add a permanent mesh property containing a description string +auto desc = OpenMesh::getOrMakeProperty(mesh, "desc"); +*desc = "This is a very nice mesh."; +\endcode + +--- + +## Code Example + In this example, we will store the \c cog value (see previous example) in a vertex property instead of keeping it in a separate array. To do so, we first add a (temporary) property of the desired element type (OpenMesh::VertexHandle) and value type (\c %MyMesh::Point) to the mesh: @@ -43,20 +67,26 @@ Finally, we set the new position for each vertex: \until mesh.point \until } +Below is the complete source code: + +\include 03-properties/smooth.cc + --- -Since we chose to use makeTemporaryProperty(), the created property is automatically removed from the mesh as soon as we leave the scope of the associated handle variable \c cog. +## Property Lifetime + +In the above example, we chose to use makeTemporaryProperty(). This causes the created property to automatically be removed from the mesh as soon as we leave the scope of the associated handle variable \c cog. If, instead, a property is desired to survive its local scope, it should be created with using getOrMakeProperty(). In that case, the property must be given a name that can later be used to retrieve the property. For example: \code - auto face_area = OpenMesh::makeTemporaryProperty(mesh, 'face_area'); + auto face_area = OpenMesh::makeTemporaryProperty(mesh, "face_area"); \endcode At a later time, we can use the getProperty() function to obtain a handle to a property that was previously created by refering to its name: \code try { - auto face_area = OpenMesh::getProperty(mesh, 'face_area'); + auto face_area = OpenMesh::getProperty(mesh, "face_area"); // Use the face_area property. } catch (const std::runtime_error& e) { @@ -64,16 +94,27 @@ At a later time, we can use the getProperty() function to obtain a handle to a p } \endcode +Using hasProperty(), we can test whether a mesh has a certain property: +\code + if (OpenMesh::hasProperty(mesh, "is_valley")) { + // Property exists. Do something with it. + auto valley = OpenMesh::getProperty(mesh, "is_valley"); + } + else { + // Property does not exist. Do something else. + } +\endcode + --- +## Low-Level Property API + The functions makeTemporaryProperty(), getOrMakeProperty(), and getProperty() are the convenient high-level interface for creating and accessing mesh properties. Beneath these convenience functions, there is also a low-level property interface where handle and property lifetime must be managed manually. This interface is accessed through a mesh's add_property(), remove_property(), and property() functions and several property handle classes (OpenMesh::VPropHandleT, OpenMesh::HPropHandleT, OpenMesh::EPropHandleT, OpenMesh::FPropHandleT, OpenMesh::MPropHandleT). --- -Below is the complete source code: -\include 03-properties/smooth.cc */