英文:
Python 3d line interpolation to increase the line resolution
问题
我正在构建一个用于建模风力涡轮机叶片的Python模块,这些叶片在X,Y
空间沿Z
轴被定义为2D剖面,我已经完成了这一部分。我得到了一个具有相同点数的剖面。问题是我想要为该叶片创建一个STL
文件,我的想法是使用这些剖面生成一个表面,使用三角剖分(我不知道这是否是最佳解决方案),但是翼型剖面之间的距离太远,所以三角剖分效果不佳,因此我想通过在Z方向添加点来增加叶片的分辨率。
在这张图片中,您可以看到剖面的位置:
这里我重新格式化数据以在Z方向连接剖面点:
我认为我可以使用一些3D插值方法在Z
方向的每条线上添加n_points
。为此,我尝试了splprep
和splev
,以下是我使用的代码:
import matplotlib.pyplot as plt
edge = np.array(edge)
x = edge[:, 0]
y = edge[:, 1]
z = edge[:, 2]
z_points = np.linspace(z[0], z[-1], n_points)
tck, u = splprep([x, y, z], s=0)
x_knots, y_knots, z_knots = splev(u, tck)
new_points = splev(z_points, tck)
fig2 = plt.figure(2)
ax3d = fig2.add_subplot(111, projection="3d")
ax3d.plot(new_points[0], new_points[1], new_points[2], "g")
ax3d.plot(x, y, z, "bo")
fig2.show()
plt.show()
但是对于每条线,结果看起来像这样,样条远离了边界:
可以在此链接中找到一个示例数据,可以导入并使用以下代码查看生成的两张图片:
import matplotlib.pyplot as plt
fig = plt.figure()
edges = np.load("edges.npy")
ax = fig.add_subplot(111, projection="3d")
for edge in edges:
ax.plot(edge[:, 0], edge[:, 1], edge[:, 2], "-.")
ax.set_aspect("equal")
ax.set_axis_off()
plt.show()
英文:
I'm building a Python module to model wind turbine blades, those blades are defined as 2D profiles in X, Y
space along a Z
axis, I have already done that. I get a profile with the same number of points. The problem is that I want to create an STL
file for that blade, and my idea is to generate a surface using the profiles, using triangulation (I don't know if this is the best solution), but the airfoils profiles are too far from each other so triangulation it's not good, so I want to increase the resolution of a blade by adding points along the Z.
in this picture you can see the position of profiles:
And here I reformat the data to connect profile points in the Z direction:
I think I can use some 3D interpolation to add n_points
to each line in Z
direction (above picture). To do this I've tried withsplprep
and splev
, here is the code that i use
import matplotlib.pyplot as plt
edge = np.array(edge)
x = edge[:, 0]
y = edge[:, 1]
z = edge[:, 2]
z_points = np.linspace(z[0], z[-1], n_points)
tck, u = splprep([x, y, z], s=0)
x_knots, y_knots, z_knots = splev(u, tck)
new_points = splev(z_points, tck)
fig2 = plt.figure(2)
ax3d = fig2.add_subplot(111, projection="3d")
ax3d.plot(new_points[0], new_points[1], new_points[2], "g")
ax3d.plot(x, y, z, "bo")
fig2.show()
plt.show()
but the result is something like this for every line, whete the spline go far fom the limits:
A sample data can be found here in this link that can be imported and viewed with the following code that produces the 2 picture:
import matplotlib.pyplot as plt
fig = plt.figure()
edges = np.load("edges.npy")
ax = fig.add_subplot(111, projection="3d")
for edge in edges:
ax.plot(edge[:, 0], edge[:, 1], edge[:, 2], "-.")
ax.set_aspect("equal")
ax.set_axis_off()
plt.show()
答案1
得分: 1
看起来你非常接近了。你唯一的错误似乎是创建了一个名为z_points
的变量,其范围从z[0]
到z[1]
。在使用splev
评估样条结果时,你需要传递一个参数向量,该向量的范围从0到1。
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import splprep, splev
plt.close("all")
edges = np.load("edges.npy")
x = edges[:, :, 0]
y = edges[:, :, 1]
z = edges[:, :, 2]
# plotting the original edges
fig, ax = plt.subplots(subplot_kw={"projection":"3d"})
for _x, _y, _z in zip(x, y, z):
ax.plot(_x, _y, _z, "-.")
ax.set_aspect("equal")
ax.set_axis_off()
fig.show()
# generating and plotting new edges with N points
N = 1000
t = np.linspace(0, 1, N) # t is the parameter, which goes from 0 to 1
x_new = np.empty((x.shape[0], N))
y_new = np.empty((x.shape[0], N))
z_new = np.empty((x.shape[0], N))
fig, ax = plt.subplots(subplot_kw={"projection":"3d"})
for i, xyz in enumerate(zip(x, y, z)):
tck, _ = splprep([*xyz], s=0)
xyz_new = splev(t, tck)
ax.scatter(*xyz_new, s=0.05)
x_new[i, :], y_new[i, :], z_new[i, :] = xyz_new
ax.set_aspect("equal")
ax.set_axis_off()
fig.show()
# plotting the surface
fig, ax = plt.subplots(subplot_kw={"projection":"3d"})
ax.plot_surface(x_new, y_new, z_new, color="r", lw=0.2, edgecolor="k")
ax.set_aspect("equal")
ax.set_axis_off()
fig.show()
fig.savefig("temp.png", dpi=600, bbox_inches="tight")
英文:
It looks like you were very close. Your only mistake appears to be creating a variable z_points
that varies from z[0]
to z[1]
. When evaluating the spline result using splev
, you need to pass it a parameter vector that goes from 0 to 1.
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import splprep, splev
plt.close("all")
edges = np.load("edges.npy")
x = edges[:, :, 0]
y = edges[:, :, 1]
z = edges[:, :, 2]
# plotting the original edges
fig, ax = plt.subplots(subplot_kw={"projection":"3d"})
for _x, _y, _z in zip(x, y, z):
ax.plot(_x, _y, _z, "-.")
ax.set_aspect("equal")
ax.set_axis_off()
fig.show()
# generating and plotting new edges with N points
N = 1000
t = np.linspace(0, 1, N) # t is the parameter, which goes from 0 to 1
x_new = np.empty((x.shape[0], N))
y_new = np.empty((x.shape[0], N))
z_new = np.empty((x.shape[0], N))
fig, ax = plt.subplots(subplot_kw={"projection":"3d"})
for i, xyz in enumerate(zip(x, y, z)):
tck, _ = splprep([*xyz], s=0)
xyz_new = splev(t, tck)
ax.scatter(*xyz_new, s=0.05)
x_new[i, :], y_new[i, :], z_new[i, :] = xyz_new
ax.set_aspect("equal")
ax.set_axis_off()
fig.show()
# plotting the surface
fig, ax = plt.subplots(subplot_kw={"projection":"3d"})
ax.plot_surface(x_new, y_new, z_new, color="r", lw=0.2, edgecolor="k")
ax.set_aspect("equal")
ax.set_axis_off()
fig.show()
fig.savefig("temp.png", dpi=600, bbox_inches="tight")
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论