点云的德劳内三角剖分

4

我想使用Delaunay算法对3D点云进行三角剖分。为了测试我的代码,我从一个STL文件中提取点云,然后尝试重新生成它。这是我的代码:

import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import Delaunay

#--------------def funtion extract point cloud-------------------
def point_cloud(inp):
    node = []
    for line in inp:
        temp1 = line.strip()
        x = temp1.split()
        if x[0] == "vertex": 
            del x[0]
            node.append(x)
    node = set(map(tuple,node))
    return node
#--------------------end function---------------------------------

with open("D:\\cilinder.stl","r") as fo:
    pc = point_cloud(fo)

u = []
v = []
w = []

for l in pc:
    u.append(float(l[0]))
    v.append(float(l[1]))
    w.append(float(l[2])) 

ua = np.array(u)
va = np.array(v)

#tri = mtri.Triangulation(u, v)
tri = Delaunay(np.array([u,v]).T)

points = []
vertex = []

for i in range(ua.shape[0]):
    points.append([ua[i],va[i],w[i]])

for vert in tri.simplices:
#for vert in tri.triangles:
    vertex.append(vert)      

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')
ax.plot_trisurf(ua, va, w, triangles=tri.simplices, cmap=plt.cm.Spectral)
#ax.plot_trisurf(ua, va, w, triangles=tri.triangles, cmap=plt.cm.Spectral)
plt.show()

运行此代码后,我得到了以下结果:
结果: enter image description here enter image description here 该算法未对点云的外部表面进行三角剖分。我无法弄清楚为什么会出现这种结果。有什么建议吗?
编辑:我刚刚发现函数point_cloud提供了重复的点,因为它们直接从STL文件中提取出来。

你是想生成一个三角形表面网格还是四面体体积网格? - Nico Schlömer
一个三角形表面网格 - drSlump
好的,问题很明显:仅给定一个点云,Delaunay无法知道哪些连接应该是结果形状的“外部”。它只是连接一些点,导致你得到了那个看起来有趣的东西。 - Nico Schlömer
有什么建议吗? - drSlump
2个回答

4
您得到的网格显示是因为您没有(也不能)向scipy的Delaunay网格提供拓扑信息。您只提供了一个点云,它连接了所有的点,就这样。生成网格是一个复杂的话题,不幸的是我不知道有哪个软件可以在给定点云和拓扑信息的情况下给出网格。然而,有各种方法可以从头开始生成网格,只需给出对象的几何形状即可。对于您所想要的圆柱体,一种方法是自己做;请查看meshzoo
import meshio
import numpy as np


def create_mesh(width=5.0, n=30, radius=1.0):
    # Number of nodes along the width of the strip (>= 2)
    # Choose it such that we have approximately square boxes.
    nw = int(round(width * n / (2 * np.pi * radius)))

    # Generate suitable ranges for parametrization
    u_range = np.linspace(0.0, 2 * np.pi, num=n, endpoint=False)
    v_range = np.linspace(-0.5 * width, 0.5 * width, num=nw)

    # Create the vertices.
    nodes = []
    for u in u_range:
        x = radius * np.cos(u)
        y = radius * np.sin(u)
        for v in v_range:
            nodes.append(np.array([x, y, v]))

    # create the elements (cells)
    elems = []
    for i in range(n - 1):
        for j in range(nw - 1):
            elems.append([i * nw + j, (i + 1) * nw + j + 1, i * nw + j + 1])
            elems.append([i * nw + j, (i + 1) * nw + j, (i + 1) * nw + j + 1])
    # close the geometry
    for j in range(nw - 1):
        elems.append([(n - 1) * nw + j, j + 1, (n - 1) * nw + j + 1])
        elems.append([(n - 1) * nw + j, j, j + 1])

    return np.array(nodes), np.array(elems)


points, cells = create_mesh()
meshio.write_points_cells("tube.vtu", points, {"triangle": cells})

enter image description here

做出这样的锯齿形应该也很容易。
其他网格生成器:

1
问题在于我必须从一个点云开始做。 - drSlump
1
除了点云,您还需要几何信息;否则您将得到您所得到的内容。如果您有几何信息,则不需要点云。这就是为什么没有您正在寻找的那种网格生成器。对于拓扑等价于平面表面的域,您可以将点映射到表面上,在那里进行 Delaunay,然后再映回来。 - Nico Schlömer
谢谢你的回答,我明白了你的意思。但如果你拥有一些来自扫描几何的点云呢?你将不会拥有任何关于几何形状的信息。我的目标是处理来自复杂几何扫描的点云数据。 - drSlump
那是不可能的,非常简单。 - Nico Schlömer

1
你可以尝试使用四面体的 Delaunay 三角网格化,然后手动移除孔洞。在我看来这是一个四面体体积网格。特别是 Bowyer-Watson 算法很容易实现。

1
谢谢您的建议。不幸的是,我正在寻找一种自动化处理过程的方法,因为点云来自已知特征(例如凹面)具有相当规则的表面的扫描几何体。我会继续寻找解决方案,并在我找到它时尽快更新讨论。 - drSlump

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接