addface :: OpenMesh中的复杂边缘错误

时间:2014-06-13 12:22:42

标签: c++ openmesh

我一直在关注OpenMesh教程First Steps - Building a Cube并做了一些修改,我使用的是TriMesh而不是PolyMesh,并且正在构建金字塔而不是立方体。

不知何故,我的第二和第三张脸都出现了错误PolymeshT::add_face:complex edge。这些面应位于点(0,0,0),(0,1,0)和(0,0,1)之间以及点(0,0,0),(0,0,1)和(1,0,0)。

每个面构造(0,0,0)到(0,1,0)和(0,0,0)到(0,0,1)时已经存在两条边,但我应该能够创建一些边缘已经存在的面,不应该吗?

到目前为止我尝试过的解决方案

  • 更改坐标
  • 使用PolyMesh代替TriMesh

我无法发现其他任何与教程不同的内容。

#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
typedef OpenMesh::TriMesh_ArrayKernelT<> MyTriMesh;

// Make a pyramid
int main()
{
    MyTriMesh tin;

    // generate vertices
    MyTriMesh::VertexHandle vhandle[4];
    vhandle[0] = tin.add_vertex(MyTriMesh::Point(0, 0, 0));
    vhandle[1] = tin.add_vertex(MyTriMesh::Point(0, 1, 0));
    vhandle[2] = tin.add_vertex(MyTriMesh::Point(1, 0, 0));
    vhandle[3] = tin.add_vertex(MyTriMesh::Point(0, 0, 1));

    // generate (trianglar) faces
    std::vector<MyTriMesh::VertexHandle> face_vhandles;
    face_vhandles.clear();
    face_vhandles.push_back(vhandle[0]);
    face_vhandles.push_back(vhandle[1]);
    face_vhandles.push_back(vhandle[2]);
    tin.add_face(face_vhandles);

    printf("Vertices: %u\nEdges: %u\nTriangles: %u\n",
        tin.n_vertices(), tin.n_edges(), tin.n_faces());

    face_vhandles.clear();
    face_vhandles.push_back(vhandle[0]);
    face_vhandles.push_back(vhandle[1]);
    face_vhandles.push_back(vhandle[3]);
    tin.add_face(face_vhandles);

    printf("Vertices: %u\nEdges: %u\nTriangles: %u\n",
        tin.n_vertices(), tin.n_edges(), tin.n_faces());

    face_vhandles.clear();
    face_vhandles.push_back(vhandle[0]);
    face_vhandles.push_back(vhandle[3]);
    face_vhandles.push_back(vhandle[2]);
    tin.add_face(face_vhandles);

    printf("Vertices: %u\nEdges: %u\nTriangles: %u\n",
        tin.n_vertices(), tin.n_edges(), tin.n_faces());

    face_vhandles.clear();
    face_vhandles.push_back(vhandle[1]);
    face_vhandles.push_back(vhandle[3]);
    face_vhandles.push_back(vhandle[2]);
    tin.add_face(face_vhandles);

    printf("Vertices: %u\nEdges: %u\nTriangles: %u\n",
        tin.n_vertices(), tin.n_edges(), tin.n_faces());

}

2 个答案:

答案 0 :(得分:3)

这个错误来自某些面孔&#39;顶点以错误的顺序添加。

OpenMesh使用halfedge structure来描述网格的三维结构。半边是顶点之间的方向边。这允许通过跟随属于面部的半边来横向面上的顶点。但是,由于这个原因,顶点被添加到面部的顺序非常重要。

通常,顶点应始终按逆时针顺序添加。这导致相邻面的半边指向相反的方向,如左下图所示。如果顶点的排序不一致,则关于哪个边缘跟随半边缘,A&#39;的底边缘存在模糊性。或者&#39; B&#39;的下边缘,如右下图所示。

Illustration of directed halfedges

在问题的代码中,面1和4逆时针排序,面2和3顺时针排序。简单的解决方法是切换这两个面的第一个和第三个顶点。

face_vhandles.clear();
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[0]);
tin.add_face(face_vhandles);

face_vhandles.clear();
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[0]);
tin.add_face(face_vhandles);

答案 1 :(得分:1)

为了扩展 Cecilia 的答案,如果您正在处理生成的数据并且无法手动固定三角形的方向,我制作了一个用于固定三角形方向的简短算法:

def calc_transitions(path):
    return ((path[0], path[1]),
            (path[1], path[2]),
            (path[2], path[0]))

def swap_path_match(path1, path2):
    tr1 = calc_transitions(path1)
    tr2 = calc_transitions(path2)
    
    for t in tr1:
        try:
            loc = tr2.index(t)
            swapped = (path2[(loc+2)%3], path2[(loc+1)%3], path2[loc])
            print('From', path1, ': matched (', t[0], '->', t[1], ') in', path2)
            print('Swapping', path2, 'to', swapped)
            return swapped
        except ValueError:
            continue
    
    return path2

要使用它,您只需遍历您的面孔列表:

for i in range(len(mesh)):
    for j in range(i+1, len(mesh)):
        mesh[j] = swap_path_match(mesh[i], mesh[j])

其中“mesh”是一个三元组列表,例如

[(1, 2, 3), (2, 3, 4), (4, 3, 5)]

在这个列表中,第 0 个和第 1 个元素有一个冲突的边缘,所以它们将被交换为:

[(1, 2, 3), (4, 3, 2), (4, 3, 5)]

现在和第1个和第2个元素有冲突,所以交换为:

[(1, 2, 3), (4, 3, 2), (5, 3, 4)]

另一个数字移到前面的原因只是实现的一个怪癖;如果结果序列是等价的,那么保持原来的顺序就没有意义了。

需要明确的是,这并不能解决任何边连接两个以上三角形的几何。