贝塞尔曲线
三次贝塞尔曲线:
由此可见其系数规律:
分别为一阶到四阶的系数规律,变化规律为杨辉三角,并且
与
的规律是一个逐渐转变的一个过程。
一段贝塞尔曲线拟合程序:
import matplotlib.pyplot as plt
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
y = [12, 2, 78, 12, 34, 23, 67, 87, 98, 10]
xnew = []
ynew = []
def Bazier_3(m1, m2):
for i in range(101):
t = i / 100
xnew.append(m1[0] * (1 - t) ** 3 + 3 * m1[1] * t * (1 - t) ** 2 + 3 * m1[2] * t ** 2 * (1 - t) + m1[3] * t ** 3)
ynew.append(m2[0] * (1 - t) ** 3 + 3 * m2[1] * t * (1 - t) ** 2 + 3 * m2[2] * t ** 2 * (1 - t) + m2[3] * t ** 3)
for i in range(len(x) // 3):
Bazier_3(x[i * 3:(i + 1) * 3 + 1], y[i * 3:(i + 1) * 3 + 1])
plt.plot(xnew, ynew)
plt.plot(x, y)
plt.scatter(x, y)
plt.show()
可以看到 ,在3,6这两个点,并不满族c2连续。
B样条曲线
其基本形式与贝塞尔曲线相似
用的最多的是三次B样条曲线。
其中:
为了使其闭合,要取最后一个点与与第一个控制点相同,即 , , ,这样的曲线满足 连续。
一个拼接示例:
import matplotlib.pyplot as plt
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
y = [12, 2, 78, 12, 34, 23, 67, 87, 98, 10]
xnew = []
ynew = []
arg = [[-1, 3, -3, 1], [3, -6, 0, 4], [-3, 3, 3, 1], [1, 0, 0, 0]]
def Ba(t, coefficient):
return (coefficient[0] * t ** 3 + coefficient[1] * t ** 2 + coefficient[2] * t + coefficient[3]) / 6
def creat(n):
for i in range(101):
t = i / 100
xnew.append(
x[n + 0] * Ba(t, arg[0]) + x[n + 1] * Ba(t, arg[1]) + x[n + 2] * Ba(t, arg[2]) + x[n + 3] * Ba(t, arg[3]))
ynew.append(
y[n + 0] * Ba(t, arg[0]) + y[n + 1] * Ba(t, arg[1]) + y[n + 2] * Ba(t, arg[2]) + y[n + 3] * Ba(t, arg[3]))
for i in range(7):
creat(i)
plt.plot(xnew, ynew)
plt.plot(x, y)
plt.scatter(x, y)
plt.show()
拼接后的图片如下所示,满足
连续。
贝塞尔曲线与B样条曲线的结合:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
arg = [[-1, 3, -3, 1], [3, -6, 0, 4], [-3, 3, 3, 1], [1, 0, 0, 0]] # B样条曲线的拟合参数
mar = [[0, -93.70105743, -7.71050644, 11.30164337],
[0, -81.51637268, 2.65858841, 21.85936928],
[0, -100.43165588, -506.84307861, -277.47509766],
[0, -413.89691162, -244.77906799, -228.4907074],
[0, -74.61241913, 22.23334312, 28.80702591],
[0, -57.65986252, 33.13808441, 40.01465988],
[0, -23.39715576, -46.36453247, -68.40002441],
[0, -427.99655151, -242.35075378, -246.75854492],
[0, -93.70105743, -7.71050644, 11.30164337]] # 原数据
def Bazier_3(m1, m2): # 贝塞尔曲线拟合
x = []
y = []
for i in range(101):
t = i / 100
x.append(m1[0] * (1 - t) ** 3 + 3 * m1[1] * t * (1 - t) ** 2 + 3 * m1[2] * t ** 2 * (1 - t) + m1[3] * t ** 3)
y.append(m2[0] * (1 - t) ** 3 + 3 * m2[1] * t * (1 - t) ** 2 + 3 * m2[2] * t ** 2 * (1 - t) + m2[3] * t ** 3)
return x, y
def Ba(t, coefficient): # 参数合成
return (coefficient[0] * t ** 3 + coefficient[1] * t ** 2 + coefficient[2] * t + coefficient[3]) / 6
def creat_mart(mart): # 贝塞尔曲线生成
re = []
for i in range(len(mart)):
temp_x, temp_y = Bazier_3([0, 1, 2, 3], mart[i])
re.append(temp_y)
return re, temp_x
def creat_mart_finnally(data): # 最终生成
out = []
times = data.shape[0]
for j in range(times - 1):
for i in range(45):
t = i / 45
temp = 0
for k in range(4):
temp += data[(j + k) % times] * Ba(t, arg[k])
out.append(temp)
return out
def draw(mat1, mat2, mat3):
x = np.linspace(0, 8, 9)
y = np.linspace(0, 3, 4)
x, y = np.meshgrid(x, y)
x = x.T
y = y.T
xs = np.ravel(x)
ys = np.ravel(y)
zs = np.ravel(mat1)
xnew = np.linspace(0, 8, 360)
ynew = np.linspace(0, 3, 101)
xn, yn = np.meshgrid(xnew, ynew)
x_min = np.linspace(0, 8, 9)
y_min = np.linspace(0, 3, 101)
x_min, y_min = np.meshgrid(x_min, y_min)
plt.figure("原数据")
ax = plt.subplot(1, 1, 1, projection='3d')
ax.plot_trisurf(xs, ys, zs, cmap='coolwarm')
ax.set_xlabel('angle')
ax.set_ylabel('stepsize')
ax.set_zlabel('Z')
plt.title('raw')
plt.figure("最终数据")
ax2 = plt.subplot(1, 1, 1, projection='3d')
ax2.plot_surface(xn.T, yn.T, mat2, rstride=2, cstride=2, cmap='coolwarm', linewidth=0.5, antialiased=True)
ax2.set_xlabel('angle')
ax2.set_ylabel('stepsize')
ax2.set_zlabel('Z')
plt.title('processed')
plt.figure("中间数据")
ax3 = plt.subplot(1, 1, 1, projection='3d')
ax3.plot_surface(x_min.T, y_min.T, mat3, rstride=2, cstride=2, cmap='coolwarm', linewidth=0.5, antialiased=True)
ax3.set_xlabel('angle')
ax3.set_ylabel('stepsize')
ax3.set_zlabel('Z')
plt.title('min')
plt.show()
mat_new, _ = creat_mart(mar)
mat_new = np.array(mat_new)
mat_f = []
for i in range(mat_new.shape[1]):
mat_f.append(creat_mart_finnally(mat_new[:, i]))
mat_f = np.array(mat_f).T
draw(np.array(mar), mat_f, mat_new)
生成的图片如下:
源数据:
在步长方向上进行了贝塞尔曲线插值之后的数据是这样的:
在角度方向上面进行了B样条曲线插值: