Commit 82708a35 authored by Janis Born's avatar Janis Born

update custom properties tutorial to use PropertyManager and the new factory functions

parent 7bd56c6f
#include <iostream>
#include <vector>
// --------------------
#include <OpenMesh/Core/IO/MeshIO.hh> #include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh> #include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Utils/PropertyManager.hh>
typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh; #include <iostream>
#include <vector>
using MyMesh = OpenMesh::TriMesh_ArrayKernelT<>;
int main(int argc, char **argv) int main(int argc, char** argv)
{ {
MyMesh mesh; // Read command line options
MyMesh mesh;
if (argc != 4) {
// check command line options std::cerr << "Usage: " << argv[0] << " #iterations infile outfile" << std::endl;
if (argc != 4) return 1;
std::cerr << "Usage: " << argv[0] << " #iterations infile outfile\n";
return 1;
// read mesh from stdin
if ( ! OpenMesh::IO::read_mesh(mesh, argv[2]) )
std::cerr << "Error: Cannot read mesh from " << argv[2] << std::endl;
return 1;
// this vertex property stores the computed centers of gravity
OpenMesh::VPropHandleT<MyMesh::Point> cogs;
// smoothing mesh argv[1] times
MyMesh::VertexIter v_it, v_end(mesh.vertices_end());
MyMesh::VertexVertexIter vv_it;
MyMesh::Point cog;
MyMesh::Scalar valence;
unsigned int i, N(atoi(argv[1]));
for (i=0; i < N; ++i)
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
valence = 0.0;
for (vv_it=mesh.vv_iter( *v_it ); vv_it; ++vv_it)
{,*v_it) += mesh.point( *vv_it );
},*v_it) /= valence;
} }
const int iterations = argv[1];
const std::string infile = argv[2];
const std::string outfile = argv[3];
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it) // Read mesh file
if ( !mesh.is_boundary( *v_it ) ) if (!OpenMesh::IO::read_mesh(mesh, infile)) {
mesh.set_point( *v_it,,*v_it) ); std::cerr << "Error: Cannot read mesh from " << infile << std::endl;
} return 1;
// write mesh to stdout {
if ( ! OpenMesh::IO::write_mesh(mesh, argv[3]) ) // Add a vertex property storing the computed centers of gravity
{ auto cog = OpenMesh::makeTemporaryProperty<OpenMesh::VertexHandle, MyMesh::Point>(mesh);
std::cerr << "Error: cannot write mesh to " << argv[3] << std::endl;
return 1; // Smooth the mesh several times
} for (int i = 0; i < iterations; ++i) {
// Iterate over all vertices to compute centers of gravity
return 0; for (const auto& vh : mesh.vertices()) {
cog[vv] = {0,0,0};
int valence = 0;
// Iterate over all 1-ring vertices around vh
for (const auto& vvh : mesh.vv_range(vh)) {
cog[vv] += mesh.point(vvh);
cog[vv] /= valence;
// Move all vertices to the previously computed positions
for (const auto& vh : mesh.vertices()) {
mesh.point(vv) = cog[vv];
// The cog vertex property is removed from the mesh at the end of this scope
// Write mesh file
if (!OpenMesh::IO::read_mesh(mesh, outfile)) {
std::cerr << "Error: Cannot write mesh to " << outfile << std::endl;
return 1;
} }
/** \page tutorial_03 Using (custom) properties /** \page tutorial_03 Using (custom) properties
This examples shows: This examples shows:
- How to add and remove custom properties, - How to add and remove custom properties
- How to get and set the value of a custom property - How to get and set the value of a custom property
In the last example we computed the barycenter of each vertex' In the last example we computed the barycenter of each vertex'
...@@ -11,44 +11,69 @@ let %OpenMesh manage the data. ...@@ -11,44 +11,69 @@ let %OpenMesh manage the data.
It would be even more helpful if we could attach such properties It would be even more helpful if we could attach such properties
dynamically to the mesh. dynamically to the mesh.
%OpenMesh provides dynamic properties, which can be attached to each Custom properties can be conveniently created and attached to meshes with the following functions:
mesh entity (vertex, face, edge, halfedge, and the mesh itself). We - makeTemporaryProperty() creates a property that is temporary to the current scope.
distinguish between custom and standard properties. A custom property - getOrMakeProperty() is used for creating and accessing permanent named properties on a mesh.
is any user-defined property and is accessed via the member function - getProperty() is used for accessing an existing permanent named property on a mesh.
\c property(..) via a handle and an entity handle
(e.g. VertexHandle). Whereas the standard properties are accessed via
special member functions, e.g. the vertex position is accessed with \c
point(..) and a vertex handle.
In this example we will store the \c cog-value (see previous example) All three functions take two template arguments:
in an additional vertex property instead of keeping it in a separate - First, the type of the mesh element that the property is attached to (i.e. OpenMesh::VertexHandle, OpenMesh::HalfedgeHandle, OpenMesh::EdgeHandle, or OpenMesh::FaceHandle).
array. To do so we define first a so-called property handle with the desired - Second, the type of the property value that is attached to each element (e.g., \p int, \p double, etc.).
type (\c MyMesh::Point) and register the handle at the mesh:
All three functions return a handle object (of type PropertyManager) that manages the lifetime of the property and provides read / write access to its values.
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:
\dontinclude 03-properties/ \dontinclude 03-properties/
\skipline vertex property stores \skipline makeTemporaryProperty
\until mesh.add
<br>The \c mesh allocates enough memory to hold as many elements of type Enough memory is allocated to hold as many values of \c %MyMesh::Point as there are vertices.
\c MyMesh::Point as number of vertices exist, and of course the mesh All insert and delete operations on the mesh are synchronized with the attached properties.
synchronizes all insert and delete operations on the vertices with the
vertex properties.
Once the wanted property is registered we can use the property to Once the property is created, we can use it to compute the centers of the neighborhood of each vertex:
calculate the barycenter of the neighborhood of each vertex \c v_it
\dontinclude 03-properties/ \skipline mesh.vertices
\skipline vv_it= \until cog[vv] /= valence
\until } \until }
\until mesh.prop
<br>and finally set the new position for each vertex \c v_it Finally, we set the new position for each vertex:
\dontinclude 03-properties/ \skipline mesh.vertices
\skipline mesh.set_point \until mesh.point
\until }
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.
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:
auto face_area = OpenMesh::makeTemporaryProperty<OpenMesh::FaceHandle, double>(mesh, 'face_area');
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:
try {
auto face_area = OpenMesh::getProperty<OpenMesh::FaceHandle, double>(mesh, 'face_area');
// Use the face_area property.
catch (const std::runtime_error& e) {
// Property not found. Handle the error here.
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).
<br>Below is the complete source code: Below is the complete source code:
\include 03-properties/ \include 03-properties/
*/ */
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment