使用(自定义)属性
本例主要说明以下问题:
1.如何添加和移除自定义属性
2.如何获取和设置自定义属性值
上一例,我们计算了每个节点的单环领域内所有节点的重心,从存储在一个外部数组中。而如果将数据存储在mesh中,由OpenMesh管理,将更不容易出错。如果能将这样的属性动态挂接到mesh中,那多好。
OpenMesh提供动态属性,利用动态属性,可以为每个mesh挂接实体数据(节点、面、边缘、半边甚至mesh本身)。区分是自定义属性还是标准属性是比较容易的,自定义属性可使用成员函数property(...),传入句柄和实体数据句柄来访问;而标准属性通过特殊的成员函数访问,例如,使用point(...)函数,传入节点句柄访问节点坐标数据。
在本例中,我们试图将额外的节点属性存储下来,区别于上一个例子的是,这里,我们使用自定义属性,而不是使用独立的外部数组。首先,需要定义一个所谓的属性句柄,这个句柄隶属特定的类型(MyMesh::Point),然后在mesh中注册这个句柄:
// this vertexproperty stores the computed centers of gravity
OpenMesh::VPropHandleT
mesh.add_property(cogs);
mesh将为这个自定义属性分配足够的内存空间,一遍容纳足够数量的Mesh::Point类型的数据,当然,在mesh进行自定义属性的插入和删除操作,mesh对所有节点的操作都可视为同步的。
一旦所需的属性注册完毕,我们将可以使用这个属性,用于存储每个节点的单环领域节点的重心数据。
for(vv_it=mesh.vv_iter( *v_it ); vv_it; ++vv_it)
{
mesh.property(cogs,*v_it)+= mesh.point( *vv_it );
++valence;
}
mesh.property(cogs,*v_it)/= valence;
最后,使用v_it迭代器,为每个节点设置新的位置坐标。
mesh.set_point( *v_it,mesh.property(cogs,*v_it) );
下面是完整的源代码:
#include
#include
//--------------------
#include
#include
typedef OpenMesh::TriMesh_ArrayKernelT<>MyMesh;
int main(int argc, char **argv)
{
MyMesh mesh;
// check commandline options
if (argc != 4)
{
std::cerr <<"Usage:"<< argv[0] << " #iterations infile outfile\n";
return 1;
}
// read mesh fromstdin
if ( ! OpenMesh::IO::read_mesh(mesh,argv[2]) )
{
std::cerr <<"Error:Cannot read mesh from " << argv[2] << std::endl;
return 1;
}
// this vertexproperty stores the computed centers of gravity
OpenMesh::VPropHandleT
mesh.add_property(cogs);
// smoothing meshargv[1] times
MyMesh::VertexIterv_it, v_end(mesh.vertices_end());
MyMesh::VertexVertexItervv_it;
MyMesh::Pointcog;
MyMesh::Scalarvalence;
unsignedint i,N(atoi(argv[1]));
for (i=0; i < N;++i)
{
for(v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
{
mesh.property(cogs,*v_it).vectorize(0.0f);
valence = 0.0;
for(vv_it=mesh.vv_iter( *v_it ); vv_it.is_valid(); ++vv_it)
{
mesh.property(cogs,*v_it)+= mesh.point( *vv_it );
++valence;
}
mesh.property(cogs,*v_it)/= 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.property(cogs,*v_it) );
}
// write mesh tostdout
if ( ! OpenMesh::IO::write_mesh(mesh,argv[3]) )
{
std::cerr <<"Error:cannot write mesh to " << argv[3] << std::endl;
return 1;
}
return 0;
}