OpenMesh:获取边界半边的句柄

时间:2018-11-22 13:32:32

标签: c++ openmesh

我对C ++库OpenMesh有一个非常简单的问题。令人惊讶的是,我在任何地方都找不到答案。

对于给定的网格,我想沿着网格边界进行迭代。从documentation我知道:

  

您可以使用next_halfedge_handle()沿边界进行迭代。如果您位于边界上,则保证下一个半边也是边界半边。

到目前为止,如此清晰。但是如何获得初始边界半边,以便从那时起可以使用next_halfedge_handle()?我真的需要遍历所有半边找到一个在边界上吗?

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

是的

“网格”仅是多边形(通常是三角形)及其局部连接性的集合。在没有明确寻找边界的情况下,实际上没有任何方法可以知道边界在哪里(甚至有多少,或者是否有边界)。

迭代自己非常简单。但是,您确实需要考虑到可能存在多个边界(例如孔)。因此,最好先确定所有边界,然后选择您感兴趣的边界。

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