5

我一直在关注 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());

}
4

2 回答 2

8

此错误是由于某些面的顶点以错误的顺序添加造成的。

OpenMesh 使用半边结构来描述网格的 3d 结构。半边是顶点之间的有向边。这允许通过跟随属于该面的半边来横切面上的顶点。但是,出于这个原因,将顶点添加到面的顺序非常重要。

通常,顶点应始终按逆时针顺序添加。这导致相邻面的半边指向相反的方向,如左下图所示。如果顶点的顺序不一致,那么对于哪条边跟在半边、“A”的底边或“B”的底边之后,就会产生歧义,如右下图所示。

有向半边的插图

在问题的代码中,面 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);
于 2014-06-16T08:53:29.987 回答
1

为了扩展塞西莉亚的回答,如果您正在处理生成的数据并且无法手动修复三角形的方向,我制作了一个固定三角形方向的简短算法:

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' 是 3 元组的列表,例如

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

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

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

现在与第一个和第二个元素发生冲突,因此将其交换为:

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

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

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

于 2021-06-04T09:14:31.217 回答