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
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 抖音账号封手机怎么办 手机号码绑定被别人占用了怎么办 DNF账号给找回了怎么办 转转上被骗了200怎么办 7彩账号被锁定怎么办 猪不吃食没精神怎么办 cf手游签到没给怎么办 cf说停止运行了怎么办 cf端游永久禁赛怎么办 cf端游爆破怕死怎么办 王者荣耀累计扣分12分怎么办 去医院看病没带身份证怎么办 ps4星战2鬼服怎么办 冒险岛英雄五转怎么办 6儿童视力低常怎么办 腰干活累的酸痛怎么办 狗狗体力很差怎么办啊 脉差总是五十多怎么办 吃过敏药嗜睡乏力怎么办 写字紧张心跳的快手抖怎么办 怀孕食欲差没精神怎么办 爬个三楼就喘了怎么办 头被篮球砸了怎么办 打球手指肿了很久怎么办 客人吃饭跑单了怎么办 脑子总是记不住东西怎么办 穿的鞋有味道怎么办 生完孩子血糖高怎么办 生了孩子子宫大怎么办 生完孩子阴吹怎么办 怀孕初期感冒嗓子发炎怎么办 脑子转不过来弯怎么办 他说我道行不深怎么办 鞋子内测磨破了怎么办 老公拉肚子拉的很厉害怎么办 老公拉肚子拉得很厉害怎么办 和老公吵架很厉害怎么办 新鞋鞋底吱吱响怎么办 新鞋鞋底滑了怎么办 工作中同事不配合怎么办 做体力活一身疼怎么办