OpenMesh
|
The mesh provides linear iterators (that enumerate vertices, halfedges, edges, and faces). These can be used to easily navigate through a mesh. Each iterator XYZIter
also exists in a const version ConstXYZIter
.
All iterators are defined in the namespace OpenMesh::Iterators. They are template classes that expect a mesh as template argument to be fully specified. You should use the iterator types provided by the mesh itself, i.e. MyMesh::VertexIter
instead of OpenMesh::Iterators::VertexIterT<MyMesh>
.
The iterators are:
MyMesh mesh; // iterate over all vertices for (MyMesh::VertexIter v_it=mesh.vertices_begin(); v_it!=mesh.vertices_end(); ++v_it) ...; // do something with *v_it, v_it->, or v_it.handle() // iterate over all halfedges for (MyMesh::HalfedgeIter h_it=mesh.halfedges_begin(); h_it!=mesh.halfedges_end(); ++h_it) ...; // do something with *h_it, h_it->, or h_it.handle() // iterate over all edges for (MyMesh::EdgeIter e_it=mesh.edges_begin(); e_it!=mesh.edges_end(); ++e_it) ...; // do something with *e_it, e_it->, or e_it.handle() // iterator over all faces for (MyMesh::FaceIter f_it=mesh.faces_begin(); f_it!=mesh.faces_end(); ++f_it) ...; // do something with *f_it, f_it->, or f_it.handle()
The corresponding const
counterparts are
ConstVertexIter
, ConstHalfedgeIter
, ConstEdgeIter
, ConstFaceIter
.The linear iterators are (almost) conformant to STL iterators. For a description of their interface see OpenMesh::Concepts::IteratorT.
For efficiency reasons the operation++
(int) (post-increment) and operation--
(int) (post-decrement) are not implemented. Hence, when using iterators, use the pre-increment operation (++it). Additionally to the standard operations, each linear iterator provides a method handle()
, which returns the handle of the item referred to by the iterator.
This example shows how to iterate over all faces of a mesh:
MyMesh mesh; for(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.handle() ) << std::endl; }
All iterators are also available as skipping iterators. If elements are deleted on a mesh, the standard iterators go over all elements, even deleted ones(which are available until a garbage_collection is done). The skipping iterators ignore these elements. You can retrieve a skipping iterator by calling one of the following functions:
vertices_sbegin()
, edges_sbegin()
, halfedges_sbegin()
, faces_sbegin()
The ends for these iterators are equal to the standard iterator ends (e.g. vertices_end()
).
OpenMesh also provides so called Circulators that provide means to enumerate items adjacent to another item of the same or another type. For example, a VertexVertexIter
allows to enumerate all vertices immediately adjacent to a (center) vertex (i.e. it allows to enumerate the so-called 1-ring of the center vertex). Analogously, a FaceHalfedgeIter
enumerates all the halfedges belonging to a face. In general, CenterItem_AuxiliaryInformation_TargetItem_Iter
designates a circulator that enumerates all the target items around a given center item.
The constructor of a circulator is of the form Circulator(MeshType mesh, TargetHandle center_handle)
, i.e. it takes a mesh and the handle of the item to circulate around.
The circulators around a vertex are:
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.The circulators around a face are:
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.All circulators provide the operations listed in CirculatorT<Mesh>, which are basically the same as the iterator funtions.
Furthermore, circulators provide operator
bool()
, which returns true, as long as the circulator hasn't reached the end of the sequence.
OpenMesh provides the following functions (defined in OpenMesh::PolyConnectivity) to get circulators around a specified center item:
/************************************************** * Vertex circulators **************************************************/ // Get the vertex-vertex circulator (1-ring) of vertex _vh VertexVertexIter OpenMesh::PolyConnectivity::vv_iter (VertexHandle _vh); // Get the vertex-incoming halfedges circulator of vertex _vh VertexIHalfedgeIter OpenMesh::PolyConnectivity::vih_iter (VertexHandle _vh); // Get the vertex-outgoing halfedges circulator of vertex _vh VertexOHalfedgeIter OpenMesh::PolyConnectivity::voh_iter (VertexHandle _vh); // Get the vertex-edge circulator of vertex _vh VertexEdgeIter OpenMesh::PolyConnectivity::ve_iter (VertexHandle _vh); // Get the vertex-face circulator of vertex _vh VertexFaceIter OpenMesh::PolyConnectivity::vf_iter (VertexHandle _vh); /************************************************** * Face circulators **************************************************/ // Get the face-vertex circulator of face _fh FaceVertexIter OpenMesh::PolyConnectivity::fv_iter (FaceHandle _fh); // Get the face-halfedge circulator of face _fh FaceHalfedgeIter OpenMesh::PolyConnectivity::fh_iter (FaceHandle _fh); // Get the face-edge circulator of face _fh FaceEdgeIter OpenMesh::PolyConnectivity::fe_iter (FaceHandle _fh); // Get the face-face circulator of face _fh FaceFaceIter OpenMesh::PolyConnectivity::ff_iter (FaceHandle _fh);
ConstVertexVertexIter cvvit = mesh.cvv_iter(some_vertex_handle);
The following code example now shows how to enumerate the 1-ring of each vertex:
MyMesh mesh; // (linearly) iterate over all vertices for (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.handle()); vv_it; ++vv_it) { // do something with e.g. mesh.point(*vv_it) } }
Enumerating all halfedges adjacent to a certain face (the inner halfedges) is accomplished as follows:
MyMesh mesh; ... // Assuming faceHandle contains the face handle of the target face MyMesh::FaceHalfedgeIter fh_it = mesh.fh_iter(faceHandle); for(; fh_it; ++fh_it) { std::cout << "Halfedge has handle " << fh_it.handle() << std::endl; }