当前位置: 首页 > 工具软件 > MeshViewer > 使用案例 >

OpenMesh入门4(译自OpenMesh6.3 Documents)

乐正洲
2023-12-01

使用标准模板库算法

由于OpenMesh迭代器(几乎)是于标准模板库(STL)迭代器一致的,因此,可以将标准模板库的算法应用于mesh

下面的例子演示了如何使用标准模板库中的for_each结构,而这种结构要比手写循环高效的多。

我们将定义一个类,这个类提供mesh的光滑算法,然后定义一个可重用组件。由于STL中没有类似于OpenMesh这样的类,因此,我们要定义的这个类必须是模板类:

template <class Mesh> class SmootherT

SmootherT类有两个函数,一个用于计算指定点单环领域节点的重心,第二个将节点位置设置为相关的重心位置。仿函数是一种类似于operator()(...)形式的操作符重载函数。第一个仿函数ComputeCOG计算重心位置,并存储于自定义属性cog_中:

void operator()(consttypename Mesh::VertexHandle& _vh)

{

typename Mesh::VertexVertexIter vv_it;

typename Mesh::Scalar valence(0.0);

mesh_.property(cog_, _vh) = typename Mesh::Point(0.0,0.0, 0.0);

for (vv_it=mesh_.vv_iter(_vh);vv_it.is_valid(); ++vv_it)

{

mesh_.property(cog_, _vh) += mesh_.point(*vv_it );

++valence;

}

mesh_.property(cog_, _vh ) /= valence;

}

注意:ComputeCOG函数需要访问mesh对象及其属性句柄。这两者都是smoother对象的成员变量的引用。

第二个仿函数classSetCOG,用于设置节点位置,构造方法类似。

使用这些仿函数均实现了对标准模板库中的std::for_each循环形式的应用。

void smooth(unsignedint _iterations)

{

for (unsignedint i=0; i < _iterations; ++i)

{

std::for_each(mesh_.vertices_begin(),

mesh_.vertices_end(),

ComputeCOG(mesh_, cog_));

std::for_each(mesh_.vertices_begin(),

mesh_.vertices_end(),

SetCOG(mesh_, cog_));

}

}

完整代码如下:

#include <algorithm>

#include<OpenMesh/Core/Utils/Property.hh>

#ifndef DOXY_IGNORE_THIS

template <class Mesh> class SmootherT

{

public:

typedeftypename Mesh::Point cog_t;

typedef OpenMesh::VPropHandleT<cog_t > Property_cog;

public:

// construct with a given mesh

SmootherT(Mesh& _mesh)

: mesh_(_mesh)

{

mesh_.add_property( cog_ );

}

~SmootherT()

{

mesh_.remove_property( cog_ );

}

// smooth mesh _iterations times

void smooth(unsignedint _iterations)

{

for (unsignedint i=0; i < _iterations; ++i)

{

std::for_each(mesh_.vertices_begin(),

mesh_.vertices_end(),

ComputeCOG(mesh_, cog_));

std::for_each(mesh_.vertices_begin(),

mesh_.vertices_end(),

SetCOG(mesh_, cog_));

}

}

private:

//--- private classes ---

class ComputeCOG

{

public:

ComputeCOG(Mesh& _mesh,Property_cog& _cog)

: mesh_(_mesh), cog_(_cog)

{}

void operator()(consttypename Mesh::VertexHandle& _vh)

{

typename Mesh::VertexVertexIter vv_it;

typename Mesh::Scalar valence(0.0);

mesh_.property(cog_, _vh) = typename Mesh::Point(0.0,0.0, 0.0);

for (vv_it=mesh_.vv_iter(_vh);vv_it.is_valid(); ++vv_it)

{

mesh_.property(cog_, _vh) += mesh_.point(*vv_it );

++valence;

}

mesh_.property(cog_, _vh ) /= valence;

}

private:

Mesh& mesh_;

Property_cog& cog_;

};

class SetCOG

{

public:

SetCOG(Mesh& _mesh, Property_cog&_cog)

: mesh_(_mesh), cog_(_cog)

{}

void operator()(consttypename Mesh::VertexHandle& _vh)

{

if (!mesh_.is_boundary(_vh))

mesh_.set_point( _vh, mesh_.property(cog_,_vh) );

}

private:

Mesh& mesh_;

Property_cog& cog_;

};

//--- private elements ---

Mesh& mesh_;

Property_cog cog_;

};

#endif


and

#include <iostream>

#include <vector>

// -------------------- OpenMesh

#include<OpenMesh/Core/IO/MeshIO.hh>

#include<OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>

// --------------------

#include "smooth_algo.hh"

//----------------------------------------------------------------------------

#ifndef DOXY_IGNORE_THIS

struct MyTraits: public OpenMesh::DefaultTraits

{

HalfedgeAttributes(OpenMesh::Attributes::PrevHalfedge);

};

#endif

typedef OpenMesh::TriMesh_ArrayKernelT<MyTraits>MyMesh;

//----------------------------------------------------------------------------

int main(int argc, char **argv)

{

MyMesh mesh;

// check command line options

if (argc != 4)

{

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;

}

// smoothing mesh argv[1] times

SmootherT<MyMesh> smoother(mesh);

smoother.smooth(atoi(argv[1]));

// write mesh to stdout

if ( ! OpenMesh::IO::write_mesh(mesh,argv[3]) )

{

std::cerr << "Error:cannot write mesh to " << argv[3] << std::endl;

return 1;

}

return 0;

}


 

 类似资料: