open mesh
Using (custom) properties
이전 포스팅에서 정점의 이웃한 정점들의 무게중심을 계산하고 이를 배열에 저장하였다. 이 데이터를 메시에 저장하고 openMesh가 데이터를 관리할 수 있도록 하면 더욱 편리하고 오류가 줄어들 것이다. 따라서 이러한 속성을 메쉬에 동적으로 넣는 것을 목표로 한다.
OpenMesh는 각 메시 개체(정점, 면, 가장자리, 절반 가장자리 및 메시 자체)에 연결할 수 있는 동적 속성을 제공한다.
add_property 메소드를 사용하여 정점 속성을 메쉬에 추가한다.
OpenMesh::VPropHandleT<MyMesh::Point> cogs; //Vertex Property Handle Type
mesh.add_property(cogs);
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;
.
.
mesh.set_point( *v_it, mesh.property(cogs,*v_it) );
마지막 줄 mesh.set_point( v_it, mesh.property(cogs,v_it) ); 는 해당 정점의 위치를 cogs 속성으로 설정된 값으로 변경하는 작업을 수행한다
full code
#include <iostream>
#include <vector>
// --------------------
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
typedef OpenMesh::TriMesh_ArrayKernelT<> 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;
}
// this vertex property stores the computed centers of gravity
OpenMesh::VPropHandleT<MyMesh::Point> cogs;
mesh.add_property(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)
{
mesh.property(cogs,*v_it).vectorize(0.0f);
valence = 0.0;
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;
}
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 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;
}
작성 중인 프로젝트에 함수로 넣은 코드 (나중에 참고용...)
void addProperty(MyMesh& mesh, MyMesh::VertexIter v_it, MyMesh::VertexVertexIter vv_it, MyMesh::VertexIter v_end, OpenMesh::VPropHandleT<MyMesh::Point> cogs, MyMesh::Scalar valence) {
// 메쉬의 모든 정점을 반복하면서, 각 정점에 대한 중심점 속성을 초기화하고 이웃 정점들의 위치를 누적하여 중심점을 계산
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));
}
//속성 출력 부분
for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it) {
MyMesh::Point cog = mesh.property(cogs, *v_it);
std::cout << "Vertex " << *v_it << " COG: (" << cog[0] << ", " << cog[1] << ", " << cog[2] << ")" << std::endl;
}
}