我一直在关注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)时已经存在两条边,但我应该能够创建一些边缘已经存在的面,不应该吗?
到目前为止我尝试过的解决方案
我无法发现其他任何与教程不同的内容。
#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());
}
答案 0 :(得分:3)
这个错误来自某些面孔&#39;顶点以错误的顺序添加。
OpenMesh使用halfedge structure来描述网格的三维结构。半边是顶点之间的方向边。这允许通过跟随属于面部的半边来横向面上的顶点。但是,由于这个原因,顶点被添加到面部的顺序非常重要。
通常,顶点应始终按逆时针顺序添加。这导致相邻面的半边指向相反的方向,如左下图所示。如果顶点的排序不一致,则关于哪个边缘跟随半边缘,A&#39;的底边缘存在模糊性。或者&#39; B&#39;的下边缘,如右下图所示。
在问题的代码中,面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)]
另一个数字移到前面的原因只是实现的一个怪癖;如果结果序列是等价的,那么保持原来的顺序就没有意义了。
需要明确的是,这并不能解决任何边连接两个以上三角形的几何。