B-Spline曲线拟合 – Python实现
1.曲线定义
定义曲线为p阶样条曲线
给定n+1个控制点 P0,P1,...Pn
节点向量 U = {u0,u1....um},且m = n+p+1
B-Spline曲线定义如下:
![在这里插入图片描述](http://img.e-com-net.com/image/info8/93996889c1004a2d81908b0c442d2d80.jpg)
N(i,p)为样条基函数
P(i)为控制顶点
参数u为参数节点,一般取0 ≤ u ≤ 1
![B-Spline曲线拟合_第1张图片](http://img.e-com-net.com/image/info8/48f7ed1895004ce9801f3999c379b044.jpg)
上式为样条基函数的递推公式
2.De Boor 算法
参考文章:
https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/single-insertion.html
根据链接中的描述,B-Spline公式可以简化为以下公式:
![img](http://img.e-com-net.com/image/info8/d85bdb8007d548d090eeb3a3dcb81ba5.jpg)
![img](http://img.e-com-net.com/image/info8/ddf44438159d4d42a565befde2353dda.jpg)
Pi为控制顶点
ai为比例系数,由当前节点t和节点u(i) u(i+p) 计算得到
![B-Spline曲线拟合_第2张图片](http://img.e-com-net.com/image/info8/53b81b9859c7476fb4ef2fc2ccf8a532.jpg)
![B-Spline曲线拟合_第3张图片](http://img.e-com-net.com/image/info8/7ff02fd6213d48e88d5001ae8cec60e7.jpg)
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张图片](http://img.e-com-net.com/image/info8/a16dbb62e6ee485fa7dda886c2b27767.jpg)