B-Spline曲线拟合

B-Spline曲线拟合 – Python实现

1.曲线定义

定义曲线为p阶样条曲线
给定n+1个控制点 P0,P1,...Pn
节点向量 U = {u0,u1....um},且m = n+p+1

B-Spline曲线定义如下:

在这里插入图片描述

N(i,p)为样条基函数
P(i)为控制顶点
参数u为参数节点,一般取0 ≤ u ≤ 1

B-Spline曲线拟合_第1张图片

上式为样条基函数的递推公式

2.De Boor 算法

参考文章:
https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/single-insertion.html
根据链接中的描述,B-Spline公式可以简化为以下公式:

img

img

Pi为控制顶点
ai为比例系数,由当前节点t和节点u(i) u(i+p) 计算得到

B-Spline曲线拟合_第2张图片B-Spline曲线拟合_第3张图片

3.算法实现流程 – 3次B-Spline曲线

第一步:设置曲线次数为p=3,读取控制顶点P0,P1,...Pn,根据控制顶点得到节点向量U = {u0,u1....um},注意m = n+p+1.为了保证拟合的曲线经过第一个、最后一个控制点,节点向量首末重复度要设置为为p+1,即U = {0,0,0,0,u(4)...u(n),1,1,1,1}
第二步:按照本文描述的De Boor算法完成递推函数
第三步:在0 ≤ u ≤ 1取值,即可得到u对应的P(u)位置

4.Python 实现

下面贴出完整python代码,仅供参考
import matplotlib.pyplot as plt
import numpy as nmp
import math
#degree. 3次样条
knotType = 1   #knot的计算方式 0:平均取值  1:根据长度取值
CPointX = []
CPointY = []
#控制轮廓顶点

with open('data.txt', 'r') as f1:
    list1 = f1.readlines()

for i in range(len(list1)):
    str = list1[i]
    str1 = str.split(",")
    CPointX.append(float(str1[0]))
    CPointY.append(float(str1[1]))

n = len(CPointX)
knot = list(nmp.arange(n+3+1))
for i in range(0,4):
    knot[i] = 0.0
    knot[n+i] = 1.0

if knotType:
    L = list(nmp.arange(n-1))
    S = 0
    for i in range(n-1):
        L[i] = nmp.sqrt(pow(CPointX[i+1]- CPointX[i],2) + pow(CPointY[i+1]- CPointY[i],2))
        S = S + L[i]

    tmp = L[0]
    for i in range(4,n):
        tmp = tmp + L[i-3]
        knot[i] = tmp / S
else:
    tmp = 1 / (n-3)
    tmpS = tmp
    for i in range(4,n):
        knot[i] = tmpS
        tmpS = tmpS + tmp
print(knot)
#节点向量
#knot = [0,0,0,0,0.25,0.4,0.8,1,1,1,1]

def de_boor_cal(u,knot,X, Y):
    #判断u在哪个区间
    m = len(knot) #节点个数 且 m = n + k +1
    n = len(X)
    i = 3
    for i in range(3,m-3):
        if u>=knot[i] and u
运行效果:

B-Spline曲线拟合_第4张图片

你可能感兴趣的:(样条曲线,算法,python)