在我的作业中,我试图在python中为过山车创建一个闭合的三次贝塞尔曲线。我在我的代码中使用了三次贝塞尔公式,如下所述:https://en.wikipedia.org/wiki/B%C3%A9zier_curve#:/www.wiki/B%C3%A9zier_curve#:/www.wiki/B%C3%A9zier_curve#:/www.wiki/B%C3%A9zier_curve#:/www.wiki/B9zier_curve#:/www.w.wiki/B%C3%A9zier_curve#:/www.w.wiki/B9zier_curve#:/www.wiki/B9zier_curve#:/www.wiki/B9zier_curve#:/www.wiki/b text = Cubic%20B%C3%A9zier%20curve%20with%20four,that%20can%20be%20scaled%20 indefinite.我有支持点(P0,P3)但没有控制点(P1,P2),知道控制点应该用线性方程和高斯算法得到,但因为找不到一种方法将它们作为代码植入,所以操作p0,p3在任何部分,使一些控制点。我知道这是错误的,但这样做,至少检查代码的其他部分。现在有一个曲线,这是不类似于我的曲线,由精确点植入在CAD应用程序(rhino3d).我想它是因为控制点实现或我的可视化有一些错误. cheers.
import numpy as np
import matplotlib.pyplot as plt
with open("C:\\Users\poori\Desktop\support points.txt") as file:
text = file.read()#.split("Track")[1][4:]
lines = text.split('\n')
non_empty_lines = [line for line in lines if line.strip() != '']
text = ('\n'.join(non_empty_lines))
text_list = text.replace(" ", ",").splitlines()
for i,y in enumerate(text_list):
text_list[i]=[float(text_list[i].split(",")[0]) , float(text_list[i].split(",")[1]), float(text_list[i].split(",")[2])]
#g = [[sum(a * b for a, b in zip(aa_row, bb_col)) for bb_col in zip(*bb)] for aa_row in bb]
s = len(text_list)-1
x = np.array([])
y = np.array([])
z = np.array([])
p1x = np.array([])
p1y = np.array([])
p1z = np.array([])
p2x = np.array([])
p2y = np.array([])
p2z = np.array([])
for i in text_list:
x = np.append(x, np.array(i[0]))
y = np.append(y, np.array(i[1]))
z = np.append(z, np.array(i[2]))
for i in range(len(x)):
if i == len(x)-1:
break
if (i + 2) == len(x):
p1x = np.append(p1x, np.array((x[i] + x[i + 1] + x[1]) / 6))
p1y = np.append(p1y, np.array((y[i] + y[i + 1] + y[1]) / 6))
p1z = np.append(p1z, np.array((z[i] + z[i + 1] + z[1]) / 6))
p2x = np.append(p2x, np.array((x[i] + x[i + 1] + x[1]) / 3))
p2y = np.append(p2y, np.array((y[i] + y[i + 1] + y[1]) / 3))
p2z = np.append(p2z, np.array((z[i] + z[i + 1] + z[1]) / 3))
else:
p1x = np.append(p1x, np.array((x[i] + x[i + 1] + x[i + 2]) / 6))
print(x[i])
p1y = np.append(p1y, np.array((y[i] + y[i + 1] + y[i + 2]) / 6))
p1z = np.append(p1z, np.array((z[i] + z[i + 1] + z[i + 2]) / 6))
p2x = np.append(p2x, np.array((x[i] + x[i + 1] + x[i + 2]) / 3))
p2y = np.append(p2y, np.array((y[i] + y[i + 1] + y[i + 2]) / 3))
p2z = np.append(p2z, np.array((z[i] + z[i + 1] + z[i + 2]) / 3))
s = np.linspace(0, 1, 300, endpoint = False)
Bx = np.array([])
By = np.array([])
Bz = np.array([])
for v in range(len(x)-1):
for i in s:
B = (((1-i)**3) * (np.array((x[v],y[v],z[v])))) + (3* ((1-i)**2)* i * (np.array((p1x[v],p1y[v],p1z[v])))) + (3 * (1-i) * (i**2) * (np.array((p2x[v],p2y[v],p2z[v])))) + ((i**3)*(np.array((x[v+1],y[v+1],z[v+1]))))
Bx = np.append(Bx , B[0])
By = np.append(By, B[1])
Bz = np.append(Bz, B[2])
CELLS = 200
nCPTS = np.size(x, 0)
n = nCPTS -1
i = 0
t = np.linspace(0,1, CELLS)
b = []
xBezier = np.zeros((1, CELLS))
yBezier = np.zeros((1, CELLS))
zBezier = np.zeros((1, CELLS))
plt.figure().add_subplot(projection='3d')
plt.plot(Bx,By,Bz)#,out[0],out[1])
plt.show()
#support points(needs to find control points by these)
#0, 0, 0
#0,-20.836,0
#0,-38.948,0
#14.277,-38.948,0
#30.064,-38.948,0
#47.36,-38.948,0
#63.942,-38.948,3
#78.327,-38.948,6
#78.327,-30.509,9
#78.327,-22.191,12
#64.542,-22.191,15
#47.662,-22.191,18
#25.768,-22.191,21
#25.768,0.98532,24
#25.768,13.24,27.261
#25.768,23.53,30
#25.768,30.216,33
#42.9,30.216,33
#57.202,30.216,33
#75.909,30.216,33
#75.909,-0.99106,33
#75.909,-2.4834,40
#75.909,-2.6028,49
#76.909,3.2814,53
#77.909,8.2948,53
#78.909,14.468,49
#78.909,14.307,40
#78.909,11.782,33
#78.909,-15.121,36
#60.112,-15.121,39
#43.57,-15.121,42
#27.405,-15.121,48
#15.597,-15.121,48
#15.597,-3.0904,48
#15.597,11.195,48
#15.597,27.638,48
#26.208,27.638,48
#34.6,27.638,48
#34.6,14.052,48
#34.6,3.8624,48
#34.6,-5.5279,45
#44.19,-5.5279,42
#57.776,-5.5279,39
#67.565,-5.5279,33
#67.565,2.9199,27
#67.565,11.511,24
#67.565,19.902,21
#67.565,27.894,18
#67.565,39.226,15
#54.779,39.226,12
#43.924,39.226,9
#30.976,39.226,6
#18.356,39.226,3
#0,39.226,0
#0,17.662,0
#0,0,0
1条答案
按热度按时间ivqmmu1c1#
正如我在前面的评论中所写的,对于一个平滑的复合贝塞尔曲线,你需要确保每个贝塞尔曲线末端的梯度是连续的。
如果--就像在你的帖子里一样--你打算使用给定的“支撑点”作为每个三次贝塞尔曲线的端点(P0和P3),那么您需要估计这些支撑点处的切线方向,并选择P1和P2,以将P1-P0和P3-P2的方向与它们的相关切线相匹配。(距离,即P1-P0和P3-P2的长度,不固定的这个要求.一个粗略的猜测是把它们作为端点之间的直线距离的三分之一.)**注意:**现在有什么我认为是一个更好的方法在这篇文章的结尾.
在下面的代码中,你可以看到函数smooth()在做这件事,并从支撑点(又名“结”)设置所有的P0,P1,P2,P3。
我已经硬编码了您的支撑点,并将它们与复合Bezier代码一起绘制。我已经将图稍微旋转了一下,试图从与您的CAD相同的视图查看它;似乎有一个小的额外垂直环-您确定支撑点完全相同吗?最后,您的CAD并没有使用复合三次Bezier曲线-它似乎使用您所谓的支持点作为高阶Bezier曲线的实际控制点。
请注意,我创建了一个简单的Bezier类,以简化代码。
输出(略微旋转以匹配CAD):x1c 0d1x
编辑:
更好的方法(一个看起来更像你的rhino 3d CAD)是把给定的点作为Bezier曲线的P1和P2点,然后通过将一个段的P2点与下一个段的P1点平均来选择P3点。(对于P0点也是类似的)。这确保了在连接的立方Bezier处的公共相切。注意,在这种情况下,曲线不一定要通过任何给定的点-他们都是贝塞尔控制点。
这一次过山车稍微平稳一些: