【Python】B样条曲线绘制

B样条曲线绘制

1.B样条曲线原理

  • 看书,有点懒

2. 固定基函数进行测试

# 固定了B样条基函数

def B_curve_uni(V,n):   # V存储坐标点,V = [[x], [y]]   # n为曲线次数
    U = np.linspace(0,1,100)
    X = V[0]
    Y = V[1]
    n = 3 # 测试只用n=3
    coef_matrix = 1/6*np.matrix([[1,4,1,0],[-3,0,3,0],[3,-6,3,0],[-1,3,-3,1]])
    if len(X) < n+1:
        return '型值点个数不够'
    else:
        # n+1个点绘制一条曲线段,len(x)-n为需要绘制的曲线段数
        x = []
        y = []
        fig = plt.figure()
        plt.plot(X,Y,marker='o',markerfacecolor='white')
        for i in range(len(X)-n):         
            for u in U:
                x.append((np.matrix([1,u,np.power(u,2),np.power(u,3)])*coef_matrix*(np.matrix(X[i:i+n+1]).T))[0,0])
                y.append((np.matrix([1,u,np.power(u,2),np.power(u,3)])*coef_matrix*(np.matrix(Y[i:i+n+1]).T))[0,0])
            plt.plot(x,y)
        plt.plot([x[0],x[100],x[200],x[-1]],[y[0],y[100],y[200],y[-1]],'o')
        plt.xticks(fontsize=14)
        plt.yticks(fontsize=14)
        plt.show()
V = [[0,0,2,3,2,1],[1,3,3,2,1,1]]
# V = [[0,0,2],[1,3,3]]
B_curve_uni(V,3)

3.B样条曲线绘制(基函数随曲线次数改变)

def N(i,k,T,t):  # 曲线N_ik
    if k == 0:
        if t<T[i] or t>T[i+1]:
            return 0
        else:
            return 1
    else:
        result = (t-T[i])/(T[i+k]-T[i])*N(i,k-1,T,t) + (T[i+k+1]-t)/(T[i+k+1]-T[i+1])*N(i+1,k-1,T,t)
        return result

def main(n,V,V_num):
    T = np.linspace(0,1,n+V_num+1)  # T存储节点
    t_x = np.linspace(0,1,160) # t_x存储每一个t值
    X = V[0]
    Y = V[1]
    x = [] # 用来存储曲线的x值
    y = [] # 用来存储曲线的y值
    for i in range(V_num-n):  # for循环用作获取第几条曲线段的数值
        result = pd.DataFrame(t_x,columns=['t'])
        for j in range(n+1):
            result1 = []
            for t in t_x:
                result1.append(N(i+j,n,T,t))
            result['N_{0}{1}'.format(i+j,n)] = result1  # 将N_ij存入dataframe
        # 把Dataframe中 T[i+n]<=t<=T[i+n+1] 的数据取出来 保存为 matrix, 然后用matrix*np.matrix(X[i:i+n+1]).T获取曲线的x值
        
        # lambda x: x>T[i+n] and x= 或 <= 曲线有时会有问题 比如 V = [[0,0,2,3,2,1],[1,3,3,2,1,1]]
        Ni_matrix = np.matrix(result[result['t'].apply(lambda x: x>=T[i+n] and x<=T[i+n+1])].iloc[:,1:]) # Ni_matrix 是一个 t_ba*j 维矩阵
        
        x = x+((Ni_matrix*np.matrix(X[i:i+n+1]).T).T).tolist()[0]
        y = y+((Ni_matrix*np.matrix(Y[i:i+n+1]).T).T).tolist()[0]
        

    fig = plt.figure()
    plt.plot(X,Y,marker='o',markerfacecolor='white')
    plt.plot(x,y)
    plt.show()
    
if __name__ == '__main__':
    n = int(input('请输入曲线的次数:'))
    V_num = int(input('请输入控制顶点个数:'))
    V = [[1,1,1.5,3,3.8,3.2,5,8,8],[0,0,2.6,3,2.2,-0.3,-0.8,2,2]]   # 有重复型值点坐标
    main(n,V,V_num)

你可能感兴趣的:(CAGD,python,几何学)