OpenMesh: Get handle to a boundary halfedge

815 views Asked by At

I have a quite simple question on the C++ library OpenMesh. Surprisingly, I haven't found anywhere an answer on it.

For a given mesh I'd like to iterate along the mesh boundary. From the documentation I know:

You can iterate along boundaries by using the next_halfedge_handle(). If you are on a boundary, the next halfedge is guaranteed to be also a boundary halfedge.

So far, so clear. But how do I get an initial boundary halfedge so that I can use next_halfedge_handle() from then on? Do I really have to iterate over all halfedges to find one being on the boundary?

Thanks a lot for your help.

1

There are 1 answers

3
Mark Loyman On BEST ANSWER

Yes.

The "Mesh" is a just a collection of polygons (most often triangles) and their local connectivity. There isn't really any way to know where the boundaries are (or even how many, or if there are any) without explicitly looking for them.

Iterating yourself is rather simple. You do however need to take into account that there are probably several boundaries (like holes). So it might be wise to identify all boundaries and then choose the one you're interested in.

typedef OpenMesh::TriMesh_ArrayKernelT<>    Mesh;
typedef std::shared_ptr<MeshUtils::Mesh>    MeshPtr;
typedef OpenMesh::HalfedgeHandle            HEdgeHandle;

std::vector<HEdgeHandle> EnumerateBoundryCycles(MeshPtr mesh)
{
    vector<HEdgeHandle> cycles_all;
    size_t maxItr(mesh->n_halfedges());

    mesh->request_halfedge_status();
    for (auto he_itr = mesh->halfedges_begin(); he_itr != mesh->halfedges_end(); ++he_itr)
        mesh->status(he_itr).set_tagged(false);

    for (auto he_itr = mesh->halfedges_begin(); he_itr != mesh->halfedges_end(); ++he_itr)
    {
        if (mesh->status(he_itr).tagged())
            continue;

        mesh->status(he_itr).set_tagged(true);

        if (false == mesh->is_boundary(he_itr))
            continue;

        // boundry found                
        cycles_all.push_back(*he_itr);      
        size_t counter = 1;
        auto next_he = mesh->next_halfedge_handle(he_itr);
        while ( (next_he != he_itr) && counter < maxItr)
        {
            assert(mesh->is_boundary(next_he));
            assert(false == mesh->status(next_he).tagged());

            mesh->status(next_he).set_tagged(true);
            next_he = mesh->next_halfedge_handle(next_he);
            counter++;
        }

        std::cout << "[EnumerateBoundryCycles]: Found cycle of length " << counter << std::endl;
        if (counter >= maxItr)
        {
            std::cout << "WRN [EnumerateBoundryCycles]:  Failed to close boundry loop." << std::endl;
            assert(false);
        }
    }

    mesh->release_halfedge_status();

    return cycles_all;
}