OpenMesh

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Mesh Iterators and Circulators

- Iterators
- How to use iterators in OpenMesh
- Skipping Iterators
- Circulators
- How to use circulators in OpenMesh

# Iterators

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.

## Deleted Elements

If no elements of a mesh are marked as deleted, the indices provided by `idx()` are consecutive numbers from 0 to number of elements-1 (in the case of vertices this would be from 0 to n_vertices()-1).

However, note that this is not the case when elements are marked as deleted and OpenMesh::ArrayKernel::garbage_collection() has not yet been called.

After garbage_collection() has been called the elements are reorganized and their handles and iterators are guaranteed to be consecutive numbers again.

Note
  - If you delete elements on the mesh, they will still be enumerated by the standard iterators. To skip deleted elements, use the Skipping Iterators
  - An iterator to an item usually needs more memory than a handle of an item. To store many references to an item, it is therefore better to use handles.

# How to use iterators in OpenMesh

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;
}

# Skipping Iterators

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()` ).

# Circulators

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);

Note
  For every circulator there also exists a constant version. To make use of these constant circulators just add the prefix
  "Const" to the type specifier and add the prefix "c" to the function used to request the circulator of an item. Example:

ConstVertexVertexIter cvvit = mesh.cvv_iter(some_vertex_handle);

Note
  When constructing Circulators from iterators, make sure you don't create a circulator of an deleted element(e.g. FaceVertexiter of a deleted Face), as this will lead to unpredictable behaviour. Using skipping iterators for iterating over the elements and creating circulators from them is safe as they don't contain deleted elements.

# How to use circulators in OpenMesh

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;
}