OpenMesh学习笔记4 迭代器和循环器
来源:互联网 发布:java log4j 全局日志 编辑:程序博客网 时间:2024/04/29 06:28
迭代器和循环器
迭代器
OpenMesh提供了遍历网格元素(点,半边,边,面)的迭代器。
所有的迭代器都定义在命名空间OpenMesh::Iterators中的模板类,需要一个具体的网格对象(即已经初始化或者从文件读取的网格对象)作为模板参数。定义迭代器时,需要使用网格对象提供的类型,如MyMesh::VertexIter而不是OpenMesh::Iterators::VertexIterT<MyMesh>。(这样的定义方式,感觉跟模板类的模板参数传递不太一样,自己适应一下就好了。)
下面是各种网格元素迭代器的使用方式:
MyMesh mesh; ...; // specify the mesh data// iterate over all verticesfor (MyMesh::VertexIter v_it=mesh.vertices_begin(); v_it!=mesh.vertices_end(); ++v_it) ...; // do something with *v_it, v_it->, or *v_it// iterate over all halfedgesfor (MyMesh::HalfedgeIter h_it=mesh.halfedges_begin(); h_it!=mesh.halfedges_end(); ++h_it) ...; // do something with *h_it, h_it->, or *h_it// iterate over all edgesfor (MyMesh::EdgeIter e_it=mesh.edges_begin(); e_it!=mesh.edges_end(); ++e_it) ...; // do something with *e_it, e_it->, or *e_it// iterator over all facesfor (MyMesh::FaceIter f_it=mesh.faces_begin(); f_it!=mesh.faces_end(); ++f_it) ...; // do something with *f_it, f_it->, or *f_it
为了效率考虑,建议使用前置递增运算符(++it)。
删除元素
如果一个网格对象中没有元素被标记为已删除,对应元素的序号(idx())是从0到num-1的连续整数(其中num是元素个数),例如点的序号就是从0到n_vertices()-1。
但是相反,如果有元素被标记为已删除,且OpenMesh::ArrayKernel::garbage_collection()没有被调用,这种连续的序号就不成立了,当然,如果调用了garbage_collection()函数,结果就跟上面一样了。原因就是OpenMesh采用了一种”懒“的元素删除方案,用于避免不必要的数据结构更新。当然,半边数据结构会在删除元素的过程中立即更新,以保证以下算法的正确执行:
- 如果你删除了一个面,那么这个面会仍然存在,但留下的洞的半边会立即更新(应该是删除掉这个面上的所有半边,比如如果是三角形面,就会删除三条逆时针方向的首尾相连的半边),这就意味着,邻接顶点的循环器(看下面的内容了解循环器),不会再列出这个面;
- 如果删除了一条边,那么相邻的面也会被移除(即把他们标记为已删除并更新周围的半边),同样的,循环器就不回再”看到“这些已经删除的元素了;
- 如果删除一个点,那么与之相连的边和相应的面也都会被标记为已删除,和上面的方案一样。
迭代器在遍历元素的过程中,仍然会遍历到所有的元素,包括已经标记为已删除元素。除非使用一种特殊的跳跃迭代器(skipping iterators),遍历过程中会跳过已经标记为删除的元素。而循环器总是只遍历没有被删除的元素。
在OpenMesh中如何使用迭代器
迭代一个网格对象中所有的面的示例如下:
MyMesh mesh; ...; // specify the mesh datafor(MyMesh::FaceIter f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it) { std::cout << "The face's valence is " << mesh.valence( *f_it ) << std::endl;}
跳跃迭代器
跳跃迭代器和普通的迭代器一样,只是在初始化迭代器时,不在使用<element>_begin()函数,而是用<element>_sbegin(),多了一个s而已,列举如下:
- vertices_sbegin(),
- edges_sbegin(),
- halfedges_sbegin(),
- faces_sbegin()
循环器
循环器是用来遍历与某一个元素相邻的所有另一种元素。如列出与一个点相邻的所有点(其实就是1-ring领域了),列出一个面上的所有点,或者一个面相邻的所有的面等。具体的有下面这些,就不一一介绍了,比较好理解的。
一个点的循环器:
- VertexVertexIter: iterate over all neighboring vertices.
- VertexIHalfedgeIter: iterate over all incoming halfedges.
- VertexOHalfedgeIter: iterate over all outgoing halfedges.
- VertexEdgeIter: iterate over all incident edges.
- VertexFaceIter: iterate over all adjacent faces.
面的循环器:
- FaceVertexIter: iterate over the face's vertices.
- FaceHalfedgeIter: iterate over the face's halfedges.
- FaceEdgeIter: iterate over the face's edges.
- FaceFaceIter: iterate over all edge-neighboring faces.
其他循环器
- HalfedgeLoopIter: iterate over a sequence of Halfedges. (all Halfedges over a face or a hole)
OpenMesh通过以下函数得到一个特定对象的循环器:
/************************************************** * Vertex circulators **************************************************/// Get the vertex-vertex circulator (1-ring) of vertex _vhVertexVertexIter OpenMesh::PolyConnectivity::vv_iter (VertexHandle _vh);// Get the vertex-incoming halfedges circulator of vertex _vhVertexIHalfedgeIter OpenMesh::PolyConnectivity::vih_iter (VertexHandle _vh);// Get the vertex-outgoing halfedges circulator of vertex _vhVertexOHalfedgeIter OpenMesh::PolyConnectivity::voh_iter (VertexHandle _vh);// Get the vertex-edge circulator of vertex _vhVertexEdgeIter OpenMesh::PolyConnectivity::ve_iter (VertexHandle _vh);// Get the vertex-face circulator of vertex _vhVertexFaceIter OpenMesh::PolyConnectivity::vf_iter (VertexHandle _vh);/************************************************** * Face circulators **************************************************/// Get the face-vertex circulator of face _fhFaceVertexIter OpenMesh::PolyConnectivity::fv_iter (FaceHandle _fh);// Get the face-halfedge circulator of face _fhFaceHalfedgeIter OpenMesh::PolyConnectivity::fh_iter (FaceHandle _fh);// Get the face-edge circulator of face _fhFaceEdgeIter OpenMesh::PolyConnectivity::fe_iter (FaceHandle _fh);// Get the face-face circulator of face _fhFaceFaceIter OpenMesh::PolyConnectivity::ff_iter (FaceHandle _fh);
除了上述常规的迭代器之外,还有一些特定方向的循环器(顺时针和逆时针),在函数中插入“cw”和“ccw”用以得到对应的方向循环器(其实就是说,常规循环器列出的对象顺序是不固定的,可能是跳跃的)。例如:
VertexVertexIter vvit = mesh.vv_iter(some_vertex_handle); // fastest (clock or counterclockwise)VertexVertexCWIter vvcwit = mesh.vv_cwiter(some_vertex_handle); // clockwiseVertexVertexCCWIter vvccwit = mesh.vv_ccwiter(some_vertex_handle); // counter-clockwise
注意,ccw和cw迭代器必须保证OpenMesh::Attributes::PrevHalfedge是可用的(因为在半边结构中,为了节省空间,这个属性是可以关闭的)。
在OpenMesh中如何使用循环器
下面的例子是列出一个点的1-ring领域:
MyMesh mesh;// (linearly) iterate over all verticesfor (MyMesh::VertexIter v_it=mesh.vertices_sbegin(); v_it!=mesh.vertices_end(); ++v_it){ // circulate around the current vertex for (MyMesh::VertexVertexIter vv_it=mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it) { // do something with e.g. mesh.point(*vv_it) }}
列出一个面上的所有内部半边的例子如下:
MyMesh mesh;...// Assuming faceHandle contains the face handle of the target faceMyMesh::FaceHalfedgeIter fh_it = mesh.fh_iter(faceHandle);for(; fh_it.is_valid(); ++fh_it) { std::cout << "Halfedge has handle " << *fh_it << std::endl;}关于具体的例子,下一篇附上,介绍如何使用循环器和迭代器,并在OpenGL中做一些显示。
0 0
- OpenMesh学习笔记4 迭代器和循环器
- OpenMesh学习笔记1 安装配置和入门示例
- OpenMesh学习笔记2 特点和开发目标
- OpenMesh学习笔记5 OpenMesh+OpenGL的一个例子
- OpenMesh学习笔记3 半边数据结构
- OpenMesh学习笔记6 怎样遍历网格
- OpenMesh学习笔记7 网格文件读写
- OpenMesh学习笔记8 两个基本操作-边的翻转和折叠
- 【OpenMesh】网格的迭代器和循环机
- OpenMesh学习记录 1
- OpenMesh
- Python标准库13 循环器 (itertools)学习
- 【OpenMesh】文件读取和写入
- openmesh 基底和减枝
- Android开发笔记(一百二十二)循环器视图RecyclerView
- vs2008和vs2010下配置openmesh
- vs2008和vs2010下配置openmesh
- 【OpenMesh】一些基本操作:翻转和折叠
- android随笔
- iOS获取时间戳,字典转换成json数据
- Linux 查看线程占用情况
- C++:类与对象4(对象成员:点与矩形)
- 自定义控件的一些简单概念
- OpenMesh学习笔记4 迭代器和循环器
- bootstrap利用Font Awesome给选择添加checkbox图标
- 秋农家常菜——老干妈蒜香土豆丝and秘制炝炒莴笋叶
- c++ concurrent progamming(2) thread manage
- lwip TCP客户端 tcp_connect函数源码解析
- Xcode描述文件路径
- Android 软键盘和emoji表情切换方案,和微信几乎一样的体验
- CDI技术第七步 生命周期管理
- 菜鸟学python(4) if语句