Loading...
Searching...
No Matches
Extending the mesh using traits

This examples shows:

- How to extend the behaviour of entities using traits.

In the previous tutorial we used attributes and changed the type of the data types `Point`, `Normal`, `TexCoord`, and `Color`. But we can do even more with traits. We can change the behaviour of the mesh entities `Vertex`, `Face`, `Edge`, and `Halfedge`.

One goal in the design was a highly customizable data structure. Using the traits technique makes it possible. We pick up the smoother again and show an alternative way to implement it. Now we place the necessary data and the functions in the vertex itself

struct MyTraits : public OpenMesh::DefaultTraits
MyTraits
Definition smooth.cc:9
OpenMesh::DefaultTraits
Base class for all traits.
Definition Traits.hh:122
{
// store barycenter of neighbors in this member
VertexTraits
{
private:
Point cog_;
public:
VertexT() : cog_( Point(0.0f, 0.0f, 0.0f ) ) { }
const Point& cog() const { return cog_; }
void set_cog(const Point& _p) { cog_ = _p; }
};
VertexTraits
#define VertexTraits
Macro for defining the vertex traits. See Specifying your MyMesh.
Definition Traits.hh:91

Note the definition of the vertex entity. We use the supplied define `VertexTraits` (which resolves in a rather inconvenient template definition). Similary we can use the defines `FaceTraits`, `EdgeTraits`, and `HalfedgeTraits` to extend these entities. Now we enhanced the vertex, with the additional member variable `cog_`, and the get/set-method pair to access the new member.

As before we compute in a first loop the barycenters for all vertices and store the information at the vertices

mesh.data(*v_it).set_cog(cog / valence);

In the second pass we set the new position of each vertex

mesh.set_point( *v_it, mesh.data(*v_it).cog());

It looks neat, but on the other hand we can't remove the data anymore as we could do with properties! By using traits one creates a 'static' configuration, which can't be changed during runtime.

The complete source looks like this:

#include <iostream>
#include <vector>
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Mesh/Traits.hh>
struct MyTraits : public OpenMesh::DefaultTraits
{
// store barycenter of neighbors in this member
VertexTraits
{
private:
Point cog_;
public:
VertexT() : cog_( Point(0.0f, 0.0f, 0.0f ) ) { }
const Point& cog() const { return cog_; }
void set_cog(const Point& _p) { cog_ = _p; }
};
};
typedef OpenMesh::TriMesh_ArrayKernelT<MyTraits> MyMesh;
typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh2;
// ---------------------------------------------------------------------------
#define SIZEOF( entity,b ) \
std::cout << _prefix << "size of " << #entity << ": " \
<< sizeof( entity ) << std::endl; \
b += sizeof( entity )
template <typename Mesh>
void print_size(const std::string& _prefix = "")
{
size_t total=0;
SIZEOF(typename Mesh::Vertex, total);
SIZEOF(typename Mesh::Halfedge, total);
SIZEOF(typename Mesh::Edge, total);
SIZEOF(typename Mesh::Face, total);
std::cout << _prefix << "total: " << total << std::endl;
}
#undef SIZEOF
// ---------------------------------------------------------------------------
int main(int argc, char **argv)
{
MyMesh mesh;
// check command line options
if (argc < 4 || argc > 5)
{
std::cerr << "Usage: " << argv[0] << " [-s] #iterations infile outfile\n";
exit(1);
}
int idx=2;
// display size of entities of the enhanced and the default mesh type
// when commandline option '-s' has been used.
if (argc == 5)
{
if (std::string("-s")==argv[idx-1])
{
std::cout << "Enhanced mesh size statistics\n";
print_size<MyMesh>(" ");
std::cout << "Default mesh size statistics\n";
print_size<MyMesh2>(" ");
}
// else ignore!
++idx;
}
// read mesh from stdin
std::cout<< " Input mesh: " << argv[idx] << std::endl;
if ( ! OpenMesh::IO::read_mesh(mesh, argv[idx]) )
{
std::cerr << "Error: Cannot read mesh from " << argv[idx] << std::endl;
return 0;
}
// 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[idx-1]));
std::cout<< "Smooth mesh " << N << " times\n";
for (i=0; i < N; ++i)
{
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
{
cog[0] = cog[1] = cog[2] = valence = 0.0;
for (vv_it=mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
{
cog += mesh.point( *vv_it );
++valence;
}
mesh.data(*v_it).set_cog(cog / valence);
}
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
if (!mesh.is_boundary(*v_it))
mesh.set_point( *v_it, mesh.data(*v_it).cog());
}
// write mesh to stdout
std::cout<< "Output mesh: " << argv[idx+1] << std::endl;
if ( ! OpenMesh::IO::write_mesh(mesh, argv[idx+1]) )
{
std::cerr << "Error: cannot write mesh to " << argv[idx+1] << std::endl;
return 0;
}
return 1;
}
OpenMesh::IO::write_mesh
bool write_mesh(const Mesh &_mesh, const std::string &_filename, Options _opt=Options::Default, std::streamsize _precision=6)
Write a mesh to the file _filename.
Definition MeshIO.hh:190
OpenMesh::IO::read_mesh
bool read_mesh(Mesh &_mesh, const std::string &_filename)
Read a mesh from file _filename.
Definition MeshIO.hh:95
OpenMesh::TriMesh_ArrayKernelT
Triangle mesh based on the ArrayKernel.
Definition TriMesh_ArrayKernelT.hh:96
OpenMesh::PolyMesh_ArrayKernelT
Polygonal mesh based on the ArrayKernel.
Definition PolyMesh_ArrayKernelT.hh:96
OpenMesh::PolyMeshT::Vertex
Kernel::Vertex Vertex
Vertex type.
Definition PolyMeshT.hh:124
OpenMesh::PolyMeshT::Scalar
Kernel::Scalar Scalar
Scalar type.
Definition PolyMeshT.hh:110
OpenMesh::PolyMeshT::Halfedge
Kernel::Halfedge Halfedge
Halfedge type.
Definition PolyMeshT.hh:126
OpenMesh::PolyMeshT::Face
Kernel::Face Face
Face type.
Definition PolyMeshT.hh:130
OpenMesh::PolyMeshT::Edge
Kernel::Edge Edge
Edge type.
Definition PolyMeshT.hh:128
OpenMesh::PolyMeshT::VertexVertexIter
Kernel::VertexVertexIter VertexVertexIter
Circulator.
Definition PolyMeshT.hh:162
OpenMesh::PolyMeshT::Point
Kernel::Point Point
Coordinate type.
Definition PolyMeshT.hh:112
OpenMesh::PolyMeshT::VertexIter
Kernel::VertexIter VertexIter
Scalar type.
Definition PolyMeshT.hh:143
Traits.hh
This file defines the default traits and some convenience macros.