介绍
在这篇指南中你会学到如何使用OpenMesh类库操纵网格。在之前的一章中(参考Mesh Iterators and Circulators),你已经学了如何迭代顶点,边,halfedge和面,以及循环遍历某些结构比如1-ring。所以这篇指南中我们将会关注如何高效的使用halfedge数据结构和其中有用的特性比如说边界标志(boundary flag)。我们假定你已经熟悉OpenMesh中的halfedge数据结构。更多的信息参考:The Halfedge Data Structure。
操纵halfedge
让我们开始操作网格中的halfedge。假定我们有以下的拓扑结构:
我们可以选择网格中任意的halfedge,能够提供两种可能的操作方式:
- 如果我们选择了halfedge位于边界上,也就是说没有与面相接,我们可以遍历整个边界,使用next_halfedge_handle()或者prev_halfedge_handle():
- 如果选择的halfedge在一个面里面,我们可以遍历这个面里面所有的halfedge。换句话说,就是循环遍历一个面的内部halfedge:
在这两种情况里面,代码示例如下。我们遍历的是边界halfedge还是面内部的halfedge,取决于初始的halfedge是否是邻接一个面:
[...] TriMesh::HalfedgeHandle heh, heh_init; // Get the halfedge handle assigned to vertex[0] heh = heh_init = mesh.halfedge_handle(vertex[0].handle()); // heh now holds the handle to the initial halfedge. // We now get further on the boundary by requesting // the next halfedge adjacent to the vertex heh // points to... heh = mesh.next_halfedge_handle(heh); // We can do this as often as we want: while(heh != heh_init) { heh = mesh.next_halfedge_handle(heh); } [...]
参考:
OpenMesh::Concepts::KernelT< FinalMeshItems >::next_halfedge_handle() OpenMesh::Concepts::KernelT< FinalMeshItems >::prev_halfedge_handle()
网格边界
如你之前所见,遍历边界是非常容易的。OpenMesh也给边,顶点和面提供了边界属性。一个面是否是边界也是相当简单的:
OpenMesh::PolyConnectivity::is_boundary()
所以对于每一种类型我们可以使用以下一种函数:
// Test if a halfedge lies at a boundary (is not adjacent to a face) bool is_boundary (HalfedgeHandle _heh) const // Test if an edge lies at a boundary bool is_boundary (EdgeHandle _eh) const // Test if a vertex is adjacent to a boundary edge bool is_boundary (VertexHandle _vh) const // Test if a face has at least one adjacent boundary edge. // If _check_vertex=true, this function also tests if at least one // of the adjacent vertices is a boundary vertex bool is_boundary (FaceHandle _fh, bool _check_vertex=false) const
使用传入型和传出型halfdedge:
OpenMesh提供相当多的迭代器和循环器轻松地迭代网格数据结构。一个非常有用的迭代器是OpenMesh::PolyConnectivity::VertexIHalfedgeIter和 OpenMesh::PolyConnectivity::VertexOHalfedgeIter,用于迭代顶点的incoming/outgoing halfedges。所以,如下所述,OpenMesh::PolyConnectivity:V:ertexIHalfedgeIter遍历最下面的顶点所有的传入halfedge,OpenMesh::PolyConnectivity::OpenMesh::PolyConnectivity::VertexOHalfedgeIter遍历所有传出的halfedge:
代码如下:
[...] // Get some vertex handle PolyMesh::VertexHandle v = ...; for(PolyMesh::VertexIHalfedgeIter vih_it = mesh.vih_iter(v); vih_it; ++vih_it) { // Iterate over all incoming halfedges... } for(PolyMesh::VertexOHalfedgeIter voh_it = mesh.voh_iter(v); voh_it; ++voh_it) { // Iterate over all outgoing halfedges... } [...]
使用反向的halfedge:
Halfedge数据结构将一条无向边分成两个有向边。对于每个halfedge,存在一个反向的边。OpenMesh调用函数OpenMesh::Concepts::KernelT< FinalMeshItems >::opposite_halfedge_handle()操作反向的halfedge。所以下图中蓝色的halfedge将返回红色的halfedge:
代码例子:
// Get the halfedge handle of i.e. the halfedge // that is associated to the first vertex // of our set of vertices PolyMesh::HalfedgeHandle heh = mesh.halfedge_handle(mesh.vertices_begin().handle()); // Now get the handle of its opposing halfedge PolyMesh::HalfedgeHandle opposite_heh = mesh.opposite_halfedge_handle(heh);
更多的函数提供访问反向结构:
// Get the face adjacent to the opposite halfedge OpenMesh::PolyConnectivity::opposite_face_handle(); // Get the handle to the opposite halfedge OpenMesh::Concepts::KernelT::opposite_halfedge_handle(); // Get the opposite vertex to the opposite halfedge OpenMesh::TriConnectivity::opposite_he_opposite_vh(); // Get the vertex assigned to the opposite halfedge OpenMesh::TriConnectivity::opposite_vh();