import numpy as np
import matplotlib.pyplot as plt
def b_spline(p_array,degree,num_div):
'''
生成二次或者三次bezier的曲线.\n
p_array:二维或三维的点序列,二次bezier曲线需要三个点,三次bezier曲线需要四个点.\n
degree: bezier曲线的阶次,可选二阶或者三阶.
num_div: 划分的线段数量,数值越大,线段越多,曲线越平滑.\n
'''
dims=np.shape(p_array[0])[0]
points=np.zeros((num_div+1,dims))
scale=1.0/num_div#细分线段的尺度
if degree==2:
for i in range(num_div+1):
t=i*scale
t1=t
t2=t1*t
b0=0.5*(t2-2*t+1)
b1=0.5*(-2*t2+2*t+1)
b2=0.5*t2
for j in range(dims):#计算坐标分量,x,y或z
points[i,j]=p_array[0][j]*b0+p_array[1][j]*b1+p_array[2][j]*b2
elif degree==3:
for i in range(num_div+1):
t=i*scale
t1=t
t2=t1*t
t3=t2*t
b0=(-t3+3*t2-3*t1+1)/6.0
b1=(3*t3-6*t2+4)/6.0
b2=(-3*t3+3*t2+3*t1+1)/6.0
b3=t3/6.0
for j in range(dims):#计算坐标分量,x,y或z
points[i,j]=p_array[0][j]*b0+p_array[1][j]*b1+p_array[2][j]*b2+p_array[3][j]*b3
return points
def b_spline_curve(p_array,degree,num_div):
'''
生成bezier平滑曲线,需要提供至少三个坐标点.\n
p_array:曲线散点序列,数组形状为(N,2),或者(N,3),点的坐标是二维坐标(x,y)或三维坐标(x,y,z).例如,散点输入为[[1,2,3],[2,1,1],...].\n
degree: bezier曲线的阶次,可选二阶或者三阶.
num_div:每段bezier曲线划分的线段数量,数值越大,线段越多,曲线越平滑.\n
'''
num_p,dims=np.shape(p_array)[0:2]#控制点的数量和坐标的维度
num_p=num_p+2
points=np.zeros((num_div*(num_p-degree)+1,dims))
sub_points=None
#为了让样条曲线经过第一个和最后一个控制点,需要另在第一个控制点之前以及最后一个控制点之后分别插入一个控制点
if degree==2:
_p=p_array[0]
p_=p_array[-1]
else:
_p=2*p_array[0]-p_array[1]
p_=2*p_array[-1]-p_array[-2]
p_array=np.array([_p,*p_array,p_])
num_seg=num_p-degree
for i in range(num_seg):
sub_points=b_spline(p_array[i:i+degree+1],degree,num_div)
offset=i*num_div
points[offset:offset+num_div,:]=sub_points[:-1,:]
points[-1:,:]=sub_points[-1,:]
return points