点云的Delaunay三角剖分
Delaunay triangulation of point cloud
我想使用 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()
在我 运行 这段代码之后,我得到了以下结果:
结果:
该算法不会对点云的外表面进行三角测量。我不明白为什么我会得到这个结果。有什么建议吗?
已编辑:我刚刚发现函数 point_cloud 提供了重复的点,因为它们是直接从 STL 文件中提取的。
您在显示网格时获得网格的原因是您没有(也不能)向 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})
用它做一个之字形应该也很容易。
其他网格生成器:
您可以尝试使用四面体进行 delaunay 三角剖分。然后手动去除孔。 IMO 它是一个四面体体积网格。尤其是Bowyer-Watson算法很简单
我想使用 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()
在我 运行 这段代码之后,我得到了以下结果:
结果:
该算法不会对点云的外表面进行三角测量。我不明白为什么我会得到这个结果。有什么建议吗?
已编辑:我刚刚发现函数 point_cloud 提供了重复的点,因为它们是直接从 STL 文件中提取的。
您在显示网格时获得网格的原因是您没有(也不能)向 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})
用它做一个之字形应该也很容易。
其他网格生成器:
您可以尝试使用四面体进行 delaunay 三角剖分。然后手动去除孔。 IMO 它是一个四面体体积网格。尤其是Bowyer-Watson算法很简单