前言: 这篇是“样条曲线”的接续,前面主要集中在了理论部分,这篇文章主要内容是贝塞尔曲线与B样条是如何应用到插值中的。
前篇:样条曲线
问题是一切发展的动力。还是从问题出发,考虑怎么通过数学手段解决问题。
对于插值问题,就是已知一些离散点,插值出一些新的点,使得所有点形成一条光滑曲线。
如已知六个点 P 0 , P 1 , ⋯ , P 5 P_0,P_1,\cdots,P_5 P0,P1,⋯,P5 ,如图红色点 ( 1 , 1 ) , ( 3 , 6 ) , ( 6 , 3 ) , ( 8 , 0 ) , ( 11 , 6 ) , ( 12 , 12 ) (1,1),(3,6),(6,3),(8,0),(11,6),(12,12) (1,1),(3,6),(6,3),(8,0),(11,6),(12,12) ,如何通过插值生成类似于图中蓝色光滑曲线,而非僵硬的绿色多线段。
依据前篇的数学描述,假设一共 n + 1 n+1 n+1 个控制点 P 0 , P 1 , ⋯ , P n P_0,P_1,\cdots,P_n P0,P1,⋯,Pn ,这 n + 1 n+1 n+1 个点可以确定一条 n n n 次贝塞尔曲线。可以用如下式计算曲线上任意点坐标
B ( t ) = ∑ i = 0 n C n i ( 1 − t ) n − i t i P i B(t) = \sum\limits_{i=0}^n C_n^i(1-t)^{n-i}t^i P_i B(t)=i=0∑nCni(1−t)n−itiPi
特别的,有几个常用贝塞尔曲线
二次贝塞尔曲线
B ( t ) = ( 1 − t ) 2 P 0 + 2 t ( 1 − t ) P 1 + t 2 P 2 , t ∈ [ 0 , 1 ] B(t) = (1-t)^2P_0 + 2t(1-t)P_1 + t^2 P_2, \ \ \ \ \ t\in[0,1] B(t)=(1−t)2P0+2t(1−t)P1+t2P2, t∈[0,1]
三次贝塞尔曲线
B ( t ) = ( 1 − t ) 3 P 0 + 3 t ( 1 − t ) 2 P 1 + 3 t 2 ( 1 − t ) P 2 + t 3 P 3 B(t) = (1-t)^3P_0 + 3t(1-t)^2P_1 + 3t^2(1-t)P_2 + t^3P_3 B(t)=(1−t)3P0+3t(1−t)2P1+3t2(1−t)P2+t3P3
这里以最常用的三次贝塞尔曲线为例,探究其插值应用。
对于贝塞尔曲线,有三个要点:
基于要点2,可以在把两个已知点作为三次贝塞尔曲线的两个端点 P 0 , P 3 P_0,P_3 P0,P3,然后想办法再指定两个控制点 P 2 , P 3 P_2,P_3 P2,P3 即可。
且控制点设定要满足贝塞尔曲线相连时平滑。
总结一下就是:
如上图是由两个贝塞尔曲线组成的一条平滑曲线,经过点 P 1 , P 2 , P 3 P_1,P_2,P_3 P1,P2,P3 ,且 P 1 , P 2 P_1,P_2 P1,P2 是第一条三次贝塞尔曲线的两端点, P 2 , P 3 P_2,P_3 P2,P3 是第二条三次贝塞尔曲线的两端点。我们需要的是每个贝塞尔曲线再设定两个控制点即可。
最简单直接的思路就是列方程,解方程。如上,两条贝塞尔曲线,一共四个未知点(控制点),需要四个方程。
令其连接点满足 c 1 c^1 c1 连续,也即 P 1 2 , P 2 , P 2 1 P_1^2,P_2,P_2^1 P12,P2,P21 共线。此处有一个方程。
对连接点处 c 2 c^2 c2 连续也加以考虑。此处也有一个方程。
还差两个方程。限制两端点即可。比如二阶导为某一定值,或三阶导为某一定值。诸如此类,这一点在后面会有详细描述。B样条中,简单的三次样条中都有详细描述。
这种思路原理直接且简单,不再用代码实现。无非就是列方程、解方程的问题。这一点在B样条中有详细类似的过程,但比这复杂的多。
下面详细描述一种有趣的解决方案:
最重要的一点是满足 P 1 2 , P 2 , P 2 1 P_1^2,P_2,P_2^1 P12,P2,P21 三点共线,所以只要关注 P 1 2 , P 2 1 P_1^2,P_2^1 P12,P21 的设定即可,因为 P 1 1 , P 2 2 P_1^1,P_2^2 P11,P22 可以依据同样的规则设定。解决方案如下, P 1 2 , P 2 1 P_1^2,P_2^1 P12,P21 肯定不是凭空产生,需要依赖于已有的一些点。而其中可依赖的点有 P 1 , P 2 , P 3 P_1,P_2,P_3 P1,P2,P3 。
第一种思路可以在 P 1 , P 2 P_1,P_2 P1,P2 连线上,控制一个比例因子生成一点,同样 P 2 , P 3 P_2,P_3 P2,P3 连线上亦如是。如上图中的蓝色两点,然后连接两点形成一条线段,平移线段,使其通过 P 2 P_2 P2 ,平移后的两点就是我们需要的 P 1 2 , P 2 1 P_1^2,P_2^1 P12,P21 。
第二种思路可以直接在 P 1 , P 3 P_1,P_3 P1,P3 连线上直接根据某特定比例因此生成两点,按照同样的平移步骤,平移后的该两点当作控制点。当然比例因此可以根据先验信息,比如参考线 P 1 P 2 P_1P_2 P1P2 和线 P 2 , P 3 P_2,P_3 P2,P3 长度比的数值。等等。
import numpy as np
import matplotlib.pyplot as plt
def getInterpolationPoints(controlPoints, tList):
n = len(controlPoints)-1
interPoints = []
for t in tList:
Bt = np.zeros(2, np.float64)
for i in range(len(controlPoints)):
Bt = Bt + comb(n,i) * np.power(1-t,n-i) * np.power(t,i) * np.array(controlPoints[i])
interPoints.append(list(Bt))
return interPoints
def getControlPointList(pointsArray, k1=-1, k2=1):
points = np.array(pointsArray)
index = points.shape[0] - 2
res = []
for i in range(index):
tmp = points[i:i+3]
p1 = tmp[0]
p2 = tmp[1]
p3 = tmp[2]
if k1 == -1:
l1 = np.sqrt(np.sum((p1-p2)**2))
l2 = np.sqrt(np.sum((p2-p3)**2))
k1 = l1/(l1+l2)
k2 = l2/(l1+l2)
p01 = k1*p1 + (1-k1)*p2
p02 = (1-k2)*p2 + k2*p3
p00 = k2*p01 + (1-k2)*p02
sub = p2 - p00
p12 = p01 + sub
p21 = p02 + sub
res.append(p12)
res.append(p21)
pFirst = points[0] + 0.1*(res[0] - points[0])
pEnd = points[-1] + 0.1*(res[-1] - points[-1])
res.insert(0,pFirst)
res.append(pEnd)
return np.array(res)
if __name__ == '__main__':
points = [[1,1],[3,6],[6,3],[8,0],[11,6],[12,12]]
controlP = getControlPointList(points)
l = len(points) - 1
figure = plt.figure()
t = np.linspace(0,1,50)
for i in range(l):
p = np.array([points[i], controlP[2*i], controlP[2*i+1], points[i+1]])
interPoints = getInterpolationPoints(p, t)
x = np.array(interPoints)[:,0]
y = np.array(interPoints)[:,1]
plt.plot(x,y)
plt.scatter(np.array(points)[:,0],np.array(points)[:,1],color='gray')
plt.show()
结果
分析
结果如预期一样,不会特别好,但可以确定该种方法是可行的。结果受比例因子 k 1 , k 2 k1,k2 k1,k2 影响很大,受原始点(型值点)的密度、趋势变化影响。
观察也知,该想法对于没有明显趋势反转(凸曲线变为凹曲线)的点效果还行,但对于转折点,效果不太行。分析其原因,是在起初分析时,使用的图是便没有考虑这种情况。如下,
而该问题的本质原因,是因为该思路只限制了连接点处 c 1 c^1 c1 连续,而对 c 2 c^2 c2 连续没有考虑,所以就出现了结果图中连接点确实看起来很平滑,但后面的过渡不太好。这也侧面说明了插值问题中 c 2 c^2 c2 连续对于平滑是很重要的。
具体推导见前篇:样条曲线
对于 n+1 个控制点 P 0 , P 1 , ⋯ , P n P_0,P_1,\cdots,P_n P0,P1,⋯,Pn ,有一个包含 m+1 个节点的列表(或节点向量) t 0 , t 1 , ⋯ , t m {t_0,t_1,\cdots,t_{m}} t0,t1,⋯,tm ,其 k 次B样条曲线表达式为(且m=n+k+1)
P ( t ) = ∑ i = 0 n B i , k ( t ) P i P(t) = \sum\limits_{i=0}^n B_{i,k}(t)\ P_i P(t)=i=0∑nBi,k(t) Pi
其中 B i , k ( t ) B_{i,k}(t) Bi,k(t) 称为 k 次 B 样条基函数,也叫调和函数。且 B i , k ( t ) B_{i,k}(t) Bi,k(t) 满足如下递推式(de Boor递推式)
k = 0 , B i , 0 ( t ) = { 0 , t ∈ [ t i , t i + 1 ] 1 , O t h e r w i s e k > 0 , B i , k ( t ) = t − t i t i + k − t i B i , k − 1 ( t ) + t i + k + 1 − t t i + k + 1 − t i + 1 B i + 1 , k − 1 ( t ) k = 0,\ \ \ \ B_{i,0}(t) = \left\{ \begin{matrix} 0, \ \ \ \ t\in[t_i,t_i+1] \\ 1, \ \ \ \ \ \ \ \ Otherwise \end{matrix} \right.\\ k > 0,\ \ \ \ B_{i,k}(t) = \frac{t-t_i}{t_{i+k}-t_i} B_{i,k-1}(t) + \frac{t_{i+k+1}-t}{t_{i+k+1}-t_{i+1}} B_{i+1,k-1}(t) k=0, Bi,0(t)={0, t∈[ti,ti+1]1, Otherwisek>0, Bi,k(t)=ti+k−tit−tiBi,k−1(t)+ti+k+1−ti+1ti+k+1−tBi+1,k−1(t)
前篇中在尝试各种节点列表时,得到了很多结果,但对结果总结分析较少,以下是一些非常重要的小总结和补充
前篇实例中许多曲线看起来很奇怪,是因为没有考虑定义域,也即由基函数完全支持的部分。该定义域在前篇中有提到,是 [ t k , t n + 1 ] o r [ t k , t m − k ] [t_k,t_{n+1}]\ \ or\ \ [t_k,t_{m-k}] [tk,tn+1] or [tk,tm−k] ,这点十分重要。在考虑定义域的情况下,曲线平滑且不会显示地很奇怪。
定义域是依赖于节点列表的,值得一提的是,如果想要较广定义域 [ t k , t n + 1 ] [t_k,t_{n+1}] [tk,tn+1],从式子上来看,至少有两种思路
使得定义域内 t 区间数量尽量多,这种情况在节点均匀分布时可用,别的情况可能没用。即 k k k 尽量小, n + 1 n+1 n+1 尽量大,也即 m − ( n + 1 ) m-(n+1) m−(n+1) 尽量小, n + 1 n+1 n+1 尽量大。也即 m m m 与 n+1 尽量接近,n+1 尽量大。换句话说,节点个数尽量多,控制点数与节点数接近。
使用该方法重新设定节点列表绘制前篇中第一个实例曲线
c o n t r o l P o n t s = [ [ 50 , 50 ] , [ 100 , 300 ] , [ 300 , 100 ] , [ 380 , 200 ] , [ 400 , 600 ] ] k n o t s = { 0 , 1 20 , 2 20 , 8 20 , 14 20 , 19 20 , 1 , 1 } n = 4 , m = 7 , k = 2 d o m a i n = [ t 3 , t 5 ] = [ 2 20 , 19 20 ] controlPonts = [[50,50], [100,300], [300,100], [380,200], [400,600]]\\ knots = \{0,\frac{1}{20},\frac{2}{20},\frac{8}{20},\frac{14}{20},\frac{19}{20},1,1\} \\ n=4,m=7,k=2 \\ domain = [t_3,t_5] = [\frac{2}{20},\frac{19}{20}] controlPonts=[[50,50],[100,300],[300,100],[380,200],[400,600]]knots={0,201,202,208,2014,2019,1,1}n=4,m=7,k=2domain=[t3,t5]=[202,2019]
定义域已经几乎包括了所有区间,最终定义域内曲线如下
曲线没有包含全部,但 [ 2 20 , 19 20 ] [\frac{2}{20},\frac{19}{20}] [202,2019] 也几乎包含全部了。Excellent!
使得定义域内 t 区间跨度大,其实严格来说就是我们要解决的问题本质,第一种思路只是实现第二种的一种解决方案。跨度大,也即 t n + 1 − t k t_{n+1} - t_k tn+1−tk 尽量大。如果 m , n , k m,n,k m,n,k 确定的情况下,如何确保呢。可以改变节点列表中的 t 的分布。我们需要的是区间 [ t k , t m − k ] [t_k,t_{m-k}] [tk,tm−k] ,如果前 k+1 个 t 数据全部设为 0,而第 m-k 个 t 之后的数据全部设为 1。那么区间 [ t k , t m − k ] [t_k,t_{m-k}] [tk,tm−k] 跨度不就是 [ 0 , 1 ] [0,1] [0,1] 嘛,也就是整个曲线嘛,很棒的想法。从曲线的角度来看,此时就是我们绘制出的整个曲线。就没有之前绘图中出现的奇奇怪怪的曲线变化了。
使用该方法重新设定节点列表绘制前篇中第一个实例曲线
c o n t r o l P o n t s = [ [ 50 , 50 ] , [ 100 , 300 ] , [ 300 , 100 ] , [ 380 , 200 ] , [ 400 , 600 ] ] k n o t s = { 0 , 0 , 0 , 0 , 1 2 , 1 , 1 , 1 , 1 } n = 4 , m = 8 , k = 3 d o m a i n = [ 0 , 1 ] controlPonts = [[50,50], [100,300], [300,100], [380,200], [400,600]]\\ knots = \{0,0,0,0,\frac{1}{2},1,1,1,1\} \\ n=4,m=8,k=3 \\ domain = [0,1] controlPonts=[[50,50],[100,300],[300,100],[380,200],[400,600]]knots={0,0,0,0,21,1,1,1,1}n=4,m=8,k=3domain=[0,1]
不再有奇怪的点,生成的曲线也十分"完美"。
第二种思路极其重要,如果 [ t k , t m − k ] [t_k,t_{m-k}] [tk,tm−k] 区间内节点又均匀分布,该样条曲线也被称作为准均匀样条。在首末两端设定一定数量的 0,1 的方法在样条曲线中极其常见,因为它确实很实用啊。
前篇中也提到了一个有趣且及其重要的现象,即 当节点列表中首末两端 0,1 重复 k+1次时,那么生成的样条曲线首末两端同贝塞尔曲线一样,都是实际原始点(型值点)的首末两点。该样条曲线也有个特定的名字,叫 clamped B-spline curves 。结合上面第二种思路提到的内容,我们得到的样条曲线也就是整条曲线。
其中还有一个 Wrapping 问题,即,使得生成曲线形成闭环。待用到时再探究和总结(挖坑)。
贝塞尔曲线中应用插值时提到了生成曲线端点为数据点(型值点)的重要性,该特点是实现插值的基础,或者说是实现两点间插值的基础。幸运的是,B样条中有一种样条满足这样的条件,即上述的 clamped B-spline。需要节点首末的 0 , 1 0,1 0,1 重复 k + 1 k+1 k+1 次。
我们常用三次的样条插值,下面就以三次样条插值为例,对其进行详细分析。
对于三次 camped B-样条,有以下要点
次数 k
k = 3 k = 3 k=3
型值点个数 n + 1 n+1 n+1 与 节点个数 m + 1 m+1 m+1 满足
m = n + k + 1 ⇒ m − n = 4 m = n + k + 1\ \ \Rightarrow\ \ m - n = 4 m=n+k+1 ⇒ m−n=4
为了形象展示,使用之前类似图表来表示
注意,其中橙色标注的区间为 [ 0 , 0 ] o r [ 1 , 1 ] [0,0] or [1,1] [0,0]or[1,1] 长度为 0,另,又因为其不在定义域内,我们不作计算,也即,其 0 次 基函数值始终记为 0。假设我们计算定义域内某区间 [ t j , t j + 1 ] [t_j,t_{j+1}] [tj,tj+1] 的曲线,按照前篇介绍的递推计算公式,0 次基函数 b j , 0 = 1 b_{j,0} = 1 bj,0=1 其余为 0 ,正如上表所示。
我们要得到 n+1 个点的权重,即 B 0 , 3 , B 1 , 3 , ⋯ , B n , 3 B_{0,3},B_{1,3},\cdots,B_{n,3} B0,3,B1,3,⋯,Bn,3 ,由上我们知道,对于一段区间(如 [ t j , t j + 1 ] [t_j,t_{j+1}] [tj,tj+1]),三次基函数只会有四个非零值,分别为 B j , 3 , B j − 1 , 3 , B j − 2 , 3 , B j − 3 , 3 B_{j,3},B_{j-1,3},B_{j-2,3},B_{j-3,3} Bj,3,Bj−1,3,Bj−2,3,Bj−3,3
如前篇所述,递推公式为
b j , k ( t ) = t − t j t j + k − t j b j , k − 1 ( t ) + t j + k + 1 − t t j + k + 1 − t j + 1 b j + 1 , k − 1 ( t ) b_{j,k}(t) = \frac{t-t_j}{t_{j+k}-t_j}\ b_{j,k-1}(t)+\frac{t_{j+k+1}-t}{t_{j+k+1}-t_{j+1}}\ b_{j+1,k-1}(t) bj,k(t)=tj+k−tjt−tj bj,k−1(t)+tj+k+1−tj+1tj+k+1−t bj+1,k−1(t)
四个权重求解具体如下,当 t ∈ [ j , j + 1 ] t\in[j,j+1] t∈[j,j+1]
0 次 基函数有一个非零 b j , 0 b_{j,0} bj,0
b j , 0 = 1 b_{j,0}=1 bj,0=1
1 次 基函数有两个非零 b j , 1 , b j − 1 , 1 b_{j,1},b_{j-1,1} bj,1,bj−1,1
b j , 1 ( t ) = t − t j t j + 1 − t j b j , 0 ( t ) + t j + 2 − t t j + 2 − t j + 1 b j + 1 , 0 ( t ) = t − t j t j + 1 − t j \begin{aligned} b_{j,1}(t) & = \frac{t-t_j}{t_{j+1}-t_j}\ b_{j,0}(t)+\frac{t_{j+2}-t}{t_{j+2}-t_{j+1}}\ b_{j+1,0}(t) \\ & = \frac{t-t_j}{t_{j+1}-t_j} \end{aligned} bj,1(t)=tj+1−tjt−tj bj,0(t)+tj+2−tj+1tj+2−t bj+1,0(t)=tj+1−tjt−tj
b j − 1 , 1 ( t ) = t − t j − 1 t j − t j − 1 b j − 1 , 0 ( t ) + t j + 1 − t t j + 1 − t j b j , 0 ( t ) = t j + 1 − t t j + 1 − t j \begin{aligned} b_{j-1,1}(t) & = \frac{t-t_{j-1}}{t_{j}-t_{j-1}}\ b_{j-1,0}(t)+\frac{t_{j+1}-t}{t_{j+1}-t_{j}}\ b_{j,0}(t) \\ & = \frac{t_{j+1}-t}{t_{j+1}-t_{j}} \end{aligned} bj−1,1(t)=tj−tj−1t−tj−1 bj−1,0(t)+tj+1−tjtj+1−t bj,0(t)=tj+1−tjtj+1−t
2 次 基函数有三个非零 b j , 2 , b j − 1 , 2 , b j − 2 , 2 b_{j,2},b_{j-1,2},b_{j-2,2} bj,2,bj−1,2,bj−2,2
b j , 2 ( t ) = t − t j t j + 2 − t j b j , 1 ( t ) + t j + 3 − t t j + 3 − t j + 1 b j + 1 , 1 ( t ) = t − t j t j + 2 − t j ⋅ t − t j t j + 1 − t j = ( t − t j ) 2 ( t j + 2 − t j ) ( t j + 1 − t j ) \begin{aligned} b_{j,2}(t) & = \frac{t-t_j}{t_{j+2}-t_j}\ b_{j,1}(t)+\frac{t_{j+3}-t}{t_{j+3}-t_{j+1}}\ b_{j+1,1}(t) \\ & = \frac{t-t_j}{t_{j+2}-t_j} \cdot \frac{t-t_j}{t_{j+1}-t_j} \\ & = \frac{(t-t_j)^2}{(t_{j+2}-t_j)(t_{j+1}-t_j)} \end{aligned} bj,2(t)=tj+2−tjt−tj bj,1(t)+tj+3−tj+1tj+3−t bj+1,1(t)=tj+2−tjt−tj⋅tj+1−tjt−tj=(tj+2−tj)(tj+1−tj)(t−tj)2
b j − 1 , 2 ( t ) = t − t j − 1 t j + 1 − t j − 1 b j − 1 , 1 ( t ) + t j + 2 − t t j + 2 − t j b j , 1 ( t ) = t − t j − 1 t j + 1 − t j − 1 ⋅ t j + 1 − t t j + 1 − t j + t j + 2 − t t j + 2 − t j ⋅ t − t j t j + 1 − t j = ( t − t j − 1 ) ( t j + 1 − t ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) + ( t j + 2 − t ) ( t − t j ) ( t j + 2 − t j ) ( t j + 1 − t j ) \begin{aligned} b_{j-1,2}(t) & = \frac{t-t_{j-1}}{t_{j+1}-t_{j-1}}\ b_{j-1,1}(t)+\frac{t_{j+2}-t}{t_{j+2}-t_{j}}\ b_{j,1}(t) \\ & = \frac{t-t_{j-1}}{t_{j+1}-t_{j-1}}\cdot \frac{t_{j+1}-t}{t_{j+1}-t_{j}} +\frac{t_{j+2}-t}{t_{j+2}-t_{j}}\cdot \frac{t-t_j}{t_{j+1}-t_j} \\ & = \frac{(t-t_{j-1})(t_{j+1}-t)}{(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} + \frac{(t_{j+2}-t)(t-t_j)}{(t_{j+2}-t_{j})(t_{j+1}-t_j)} \end{aligned} bj−1,2(t)=tj+1−tj−1t−tj−1 bj−1,1(t)+tj+2−tjtj+2−t bj,1(t)=tj+1−tj−1t−tj−1⋅tj+1−tjtj+1−t+tj+2−tjtj+2−t⋅tj+1−tjt−tj=(tj+1−tj−1)(tj+1−tj)(t−tj−1)(tj+1−t)+(tj+2−tj)(tj+1−tj)(tj+2−t)(t−tj)
b j − 2 , 2 ( t ) = t − t j − 2 t j − t j − 2 b j − 2 , 1 ( t ) + t j + 1 − t t j + 1 − t j − 1 b j − 1 , 1 ( t ) = t j + 1 − t t j + 1 − t j − 1 ⋅ t j + 1 − t t j + 1 − t j = ( t j + 1 − t ) 2 ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) \begin{aligned} b_{j-2,2}(t) & = \frac{t-t_{j-2}}{t_{j}-t_{j-2}}\ b_{j-2,1}(t)+\frac{t_{j+1}-t}{t_{j+1}-t_{j-1}}\ b_{j-1,1}(t) \\ & = \frac{t_{j+1}-t}{t_{j+1}-t_{j-1}}\cdot \frac{t_{j+1}-t}{t_{j+1}-t_{j}} \\ & = \frac{(t_{j+1}-t)^2}{(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} \end{aligned} bj−2,2(t)=tj−tj−2t−tj−2 bj−2,1(t)+tj+1−tj−1tj+1−t bj−1,1(t)=tj+1−tj−1tj+1−t⋅tj+1−tjtj+1−t=(tj+1−tj−1)(tj+1−tj)(tj+1−t)2
3 次 基函数有四个非零 b j , 3 , b j − 1 , 3 , b j − 2 , 3 , b j − 3 , 3 b_{j,3},b_{j-1,3},b_{j-2,3},b_{j-3,3} bj,3,bj−1,3,bj−2,3,bj−3,3
b j , 3 ( t ) = t − t j t j + 3 − t j b j , 2 ( t ) + t j + 4 − t t j + 4 − t j + 1 b j + 1 , 2 ( t ) = t − t j t j + 3 − t j ⋅ ( t − t j ) 2 ( t j + 2 − t j ) ( t j + 1 − t j ) = ( t − t j ) 3 ( t j + 3 − t j ) ( t j + 2 − t j ) ( t j + 1 − t j ) \begin{aligned} b_{j,3}(t) &= \frac{t-t_j}{t_{j+3}-t_j}\ b_{j,2}(t)+\frac{t_{j+4}-t}{t_{j+4}-t_{j+1}}\ b_{j+1,2}(t) \\ & = \frac{t-t_j}{t_{j+3}-t_j}\cdot \frac{(t-t_j)^2}{(t_{j+2}-t_j)(t_{j+1}-t_j)} \\ & = \frac{(t-t_j)^3}{(t_{j+3}-t_j)(t_{j+2}-t_j)(t_{j+1}-t_j)} \end{aligned} bj,3(t)=tj+3−tjt−tj bj,2(t)+tj+4−tj+1tj+4−t bj+1,2(t)=tj+3−tjt−tj⋅(tj+2−tj)(tj+1−tj)(t−tj)2=(tj+3−tj)(tj+2−tj)(tj+1−tj)(t−tj)3
b j − 1 , 3 ( t ) = t − t j − 1 t j + 2 − t j − 1 b j − 1 , 2 ( t ) + t j + 3 − t t j + 3 − t j b j , 2 ( t ) = t − t j − 1 t j + 2 − t j − 1 ⋅ [ ( t − t j − 1 ) ( t j + 1 − t ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) + ( t j + 2 − t ) ( t − t j ) ( t j + 2 − t j ) ( t j + 1 − t j ) ] + t j + 3 − t t j + 3 − t j ⋅ ( t − t j ) 2 ( t j + 2 − t j ) ( t j + 1 − t j ) = ( t − t j − 1 ) 2 ( t j + 1 − t ) ( t j + 2 − t j − 1 ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) + ( t − t j − 1 ) ( t j + 2 − t ) ( t − t j ) ( t j + 2 − t j − 1 ) ( t j + 2 − t j ) ( t j + 1 − t j ) + ( t j + 3 − t ) ( t − t j ) 2 ( t j + 3 − t j ) ( t j + 2 − t j ) ( t j + 1 − t j ) \begin{aligned} b_{j-1,3}(t) &= \frac{t-t_{j-1}}{t_{j+2}-t_{j-1}}\ b_{j-1,2}(t)+\frac{t_{j+3}-t}{t_{j+3}-t_{j}}\ b_{j,2}(t) \\ & = \frac{t-t_{j-1}}{t_{j+2}-t_{j-1}}\cdot [\frac{(t-t_{j-1})(t_{j+1}-t)}{(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} + \frac{(t_{j+2}-t)(t-t_j)}{(t_{j+2}-t_{j})(t_{j+1}-t_j)}] + \frac{t_{j+3}-t}{t_{j+3}-t_{j}}\cdot \frac{(t-t_j)^2}{(t_{j+2}-t_j)(t_{j+1}-t_j)} \\ & = \frac{(t-t_{j-1})^2(t_{j+1}-t)}{(t_{j+2}-t_{j-1})(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} + \frac{(t-t_{j-1})(t_{j+2}-t)(t-t_j)}{(t_{j+2}-t_{j-1})(t_{j+2}-t_{j})(t_{j+1}-t_j)} + \frac{(t_{j+3}-t)(t-t_j)^2}{(t_{j+3}-t_j)(t_{j+2}-t_j)(t_{j+1}-t_j)} \end{aligned} bj−1,3(t)=tj+2−tj−1t−tj−1 bj−1,2(t)+tj+3−tjtj+3−t bj,2(t)=tj+2−tj−1t−tj−1⋅[(tj+1−tj−1)(tj+1−tj)(t−tj−1)(tj+1−t)+(tj+2−tj)(tj+1−tj)(tj+2−t)(t−tj)]+tj+3−tjtj+3−t⋅(tj+2−tj)(tj+1−tj)(t−tj)2=(tj+2−tj−1)(tj+1−tj−1)(tj+1−tj)(t−tj−1)2(tj+1−t)+(tj+2−tj−1)(tj+2−tj)(tj+1−tj)(t−tj−1)(tj+2−t)(t−tj)+(tj+3−tj)(tj+2−tj)(tj+1−tj)(tj+3−t)(t−tj)2
b j − 2 , 3 ( t ) = t − t j − 2 t j + 1 − t j − 2 b j − 2 , 2 ( t ) + t j + 2 − t t j + 2 − t j − 1 b j − 1 , 2 ( t ) = t − t j − 2 t j + 1 − t j − 2 ⋅ ( t j + 1 − t ) ( t j + 1 − t ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) + t j + 2 − t t j + 2 − t j − 1 ⋅ [ ( t − t j − 1 ) ( t j + 1 − t ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) + ( t j + 2 − t ) ( t − t j ) ( t j + 2 − t j ) ( t j + 1 − t j ) ] = ( t − t j − 2 ) ( t j + 1 − t ) 2 ( t j + 1 − t j − 2 ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) + ( t j + 2 − t ) ( t − t j − 1 ) ( t j + 1 − t ) ( t j + 2 − t j − 1 ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) + ( t j + 2 − t ) 2 ( t − t j ) ( t j + 2 − t j − 1 ) ( t j + 2 − t j ) ( t j + 1 − t j ) \begin{aligned} b_{j-2,3}(t) &= \frac{t-t_{j-2}}{t_{j+1}-t_{j-2}}\ b_{j-2,2}(t)+\frac{t_{j+2}-t}{t_{j+2}-t_{j-1}}\ b_{j-1,2}(t) \\ & = \frac{t-t_{j-2}}{t_{j+1}-t_{j-2}}\cdot \frac{(t_{j+1}-t)(t_{j+1}-t)}{(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} + \frac{t_{j+2}-t}{t_{j+2}-t_{j-1}}\cdot [\frac{(t-t_{j-1})(t_{j+1}-t)}{(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} + \frac{(t_{j+2}-t)(t-t_j)}{(t_{j+2}-t_{j})(t_{j+1}-t_j)}] \\ & = \frac{(t-t_{j-2})(t_{j+1}-t)^2}{(t_{j+1}-t_{j-2})(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} + \frac{(t_{j+2}-t)(t-t_{j-1})(t_{j+1}-t)}{(t_{j+2}-t_{j-1})(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} + \frac{(t_{j+2}-t)^2(t-t_j)}{(t_{j+2}-t_{j-1})(t_{j+2}-t_{j})(t_{j+1}-t_j)} \end{aligned} bj−2,3(t)=tj+1−tj−2t−tj−2 bj−2,2(t)+tj+2−tj−1tj+2−t bj−1,2(t)=tj+1−tj−2t−tj−2⋅(tj+1−tj−1)(tj+1−tj)(tj+1−t)(tj+1−t)+tj+2−tj−1tj+2−t⋅[(tj+1−tj−1)(tj+1−tj)(t−tj−1)(tj+1−t)+(tj+2−tj)(tj+1−tj)(tj+2−t)(t−tj)]=(tj+1−tj−2)(tj+1−tj−1)(tj+1−tj)(t−tj−2)(tj+1−t)2+(tj+2−tj−1)(tj+1−tj−1)(tj+1−tj)(tj+2−t)(t−tj−1)(tj+1−t)+(tj+2−tj−1)(tj+2−tj)(tj+1−tj)(tj+2−t)2(t−tj)
b j − 3 , 3 ( t ) = t − t j − 3 t j − t j − 3 b j − 3 , 2 ( t ) + t j + 1 − t t j + 1 − t j − 2 b j − 2 , 2 ( t ) = t j + 1 − t t j + 1 − t j − 2 ⋅ ( t j + 1 − t ) 2 ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) = ( t j + 1 − t ) 3 ( t j + 1 − t j − 2 ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) \begin{aligned} b_{j-3,3}(t) &= \frac{t-t_{j-3}}{t_{j}-t_{j-3}}\ b_{j-3,2}(t)+\frac{t_{j+1}-t}{t_{j+1}-t_{j-2}}\ b_{j-2,2}(t) \\ &= \frac{t_{j+1}-t}{t_{j+1}-t_{j-2}}\cdot \frac{(t_{j+1}-t)^2}{(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} \\ &= \frac{(t_{j+1}-t)^3}{(t_{j+1}-t_{j-2})(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} \end{aligned} bj−3,3(t)=tj−tj−3t−tj−3 bj−3,2(t)+tj+1−tj−2tj+1−t bj−2,2(t)=tj+1−tj−2tj+1−t⋅(tj+1−tj−1)(tj+1−tj)(tj+1−t)2=(tj+1−tj−2)(tj+1−tj−1)(tj+1−tj)(tj+1−t)3
也即
B j , 3 ( t ) = ( t − t j ) 3 ( t j + 3 − t j ) ( t j + 2 − t j ) ( t j + 1 − t j ) B j − 1 , 3 ( t ) = ( t − t j − 1 ) 2 ( t j + 1 − t ) ( t j + 2 − t j − 1 ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) + ( t − t j − 1 ) ( t j + 2 − t ) ( t − t j ) ( t j + 2 − t j − 1 ) ( t j + 2 − t j ) ( t j + 1 − t j ) + ( t j + 3 − t ) ( t − t j ) 2 ( t j + 3 − t j ) ( t j + 2 − t j ) ( t j + 1 − t j ) B j − 2 , 3 ( t ) = ( t − t j − 2 ) ( t j + 1 − t ) 2 ( t j + 1 − t j − 2 ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) + ( t j + 2 − t ) ( t − t j − 1 ) ( t j + 1 − t ) ( t j + 2 − t j − 1 ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) + ( t j + 2 − t ) 2 ( t − t j ) ( t j + 2 − t j − 1 ) ( t j + 2 − t j ) ( t j + 1 − t j ) B j − 3 , 3 ( t ) = ( t j + 1 − t ) 3 ( t j + 1 − t j − 2 ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) (*) \begin{aligned} &B_{j,3}(t) = \frac{(t-t_j)^3}{(t_{j+3}-t_j)(t_{j+2}-t_j)(t_{j+1}-t_j)} \\ &B_{j-1,3}(t) = \frac{(t-t_{j-1})^2(t_{j+1}-t)}{(t_{j+2}-t_{j-1})(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} + \frac{(t-t_{j-1})(t_{j+2}-t)(t-t_j)}{(t_{j+2}-t_{j-1})(t_{j+2}-t_{j})(t_{j+1}-t_j)} + \frac{(t_{j+3}-t)(t-t_j)^2}{(t_{j+3}-t_j)(t_{j+2}-t_j)(t_{j+1}-t_j)} \\ &B_{j-2,3}(t) = \frac{(t-t_{j-2})(t_{j+1}-t)^2}{(t_{j+1}-t_{j-2})(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} + \frac{(t_{j+2}-t)(t-t_{j-1})(t_{j+1}-t)}{(t_{j+2}-t_{j-1})(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} + \frac{(t_{j+2}-t)^2(t-t_j)}{(t_{j+2}-t_{j-1})(t_{j+2}-t_{j})(t_{j+1}-t_j)} \\ &B_{j-3,3}(t) = \frac{(t_{j+1}-t)^3}{(t_{j+1}-t_{j-2})(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} \end{aligned} \tag{*} Bj,3(t)=(tj+3−tj)(tj+2−tj)(tj+1−tj)(t−tj)3Bj−1,3(t)=(tj+2−tj−1)(tj+1−tj−1)(tj+1−tj)(t−tj−1)2(tj+1−t)+(tj+2−tj−1)(tj+2−tj)(tj+1−tj)(t−tj−1)(tj+2−t)(t−tj)+(tj+3−tj)(tj+2−tj)(tj+1−tj)(tj+3−t)(t−tj)2Bj−2,3(t)=(tj+1−tj−2)(tj+1−tj−1)(tj+1−tj)(t−tj−2)(tj+1−t)2+(tj+2−tj−1)(tj+1−tj−1)(tj+1−tj)(tj+2−t)(t−tj−1)(tj+1−t)+(tj+2−tj−1)(tj+2−tj)(tj+1−tj)(tj+2−t)2(t−tj)Bj−3,3(t)=(tj+1−tj−2)(tj+1−tj−1)(tj+1−tj)(tj+1−t)3(*)
由此,得到该区间的曲线表达式为
B ( t ) = B 0 , 3 P 0 + B 1 , 3 P 1 + ⋯ + B n , 3 P n = B j − 3 , 3 ( t ) P j − 3 + B j − 2 , 3 ( t ) P j − 2 + B j − 1 , 3 ( t ) P j − 1 + B j , 3 ( t ) P j \begin{aligned} B(t) & = B_{0,3}\ P_0 + B_{1,3}\ P_1 + \cdots + B_{n,3}\ P_n \\ & = B_{j-3,3}(t)\ P_{j-3} + B_{j-2,3}(t)\ P_{j-2} + B_{j-1,3}(t)\ P_{j-1} + B_{j,3}(t)\ P_j \end{aligned} B(t)=B0,3 P0+B1,3 P1+⋯+Bn,3 Pn=Bj−3,3(t) Pj−3+Bj−2,3(t) Pj−2+Bj−1,3(t) Pj−1+Bj,3(t) Pj
根据公式可知,当节点 t 0 , t 1 , ⋯ , t n t_0,t_1,\cdots,t_n t0,t1,⋯,tn 确定后, B j , 3 , B j − 1 , 3 , B j − 2 , 3 , B j − 3 , 3 B_{j,3},B_{j-1,3},B_{j-2,3},B_{j-3,3} Bj,3,Bj−1,3,Bj−2,3,Bj−3,3 都是关于 t 的三次函数。 B ( t ) B(t) B(t) 也随着 t ( ∈ [ 0 , 1 ] ) (\in[0,1]) (∈[0,1]) 的取值而确定,也即确定了曲线上的一系列点 B(t),正是这些点组成了样条曲线。
clamped -B样条本身跟贝塞尔曲线很接近,当然可以考虑使用类似于上节贝塞尔曲线插值那样,在两点内依次插入 B 样条,通过某些设定确保曲线光滑。但这种方法会同上面一样很粗糙。
对于 B 样条,不同与贝塞尔曲线的一点就是,B 样条曲线有节点,而且节点可以映射到最终曲线上,节点对应坐标为 B ( t j ) B(t_j) B(tj),依据以上公式计算。而且B样条本身就是一条光滑曲线,取代于上面贝塞尔曲线的两点间逐个插值,考虑使用B样条一次性生成所需曲线,且曲线通过原始点(型值点)。
而要满足生成的 B 样条直接穿过型值点,恰好可以利用上述节点性质(即节点在曲线上的有对应点 B ( t j ) B(t_j) B(tj))。因此只需要考虑让 型值点等值于 节点对应点即可。即便这样,我们仍然有很大的参数设定自由度。
如,假设有一系列型值点中考虑其中一点 P’,我们使用三次B样条对所有型值点进行插值,让 P’ 等值于第 i 个节点对应点 B ( t j ) B(t_j) B(tj) ,即
P ‘ = B ( t i ) = B j − 3 , 3 ( t j ) P j − 3 + B j − 2 , 3 ( t j ) P j − 2 + B j − 1 , 3 ( t j ) P j − 1 + B j , 3 ( t j ) P j P‘ = B(t_i) = B_{j-3,3}(t_j)\ P_{j-3} + B_{j-2,3}(t_j)\ P_{j-2} + B_{j-1,3}(t_j)\ P_{j-1} + B_{j,3}(t_j)\ P_j P‘=B(ti)=Bj−3,3(tj) Pj−3+Bj−2,3(tj) Pj−2+Bj−1,3(tj) Pj−1+Bj,3(tj) Pj
该式中,P‘ 已知,控制点 P j − 3 , P j − 2 , P j − 1 , P j P_{j-3},P_{j-2},P{j-1},P{j} Pj−3,Pj−2,Pj−1,Pj 都未知,第 j 个节点值 t j t_j tj 也未知,而且这些值都可以一定程度地"随意设置。也就是说,我们有很大的自由度来通过手动设定控制点、节点分布等来满足上式。而只要满足上式,就会有生成的B样条曲线经过型值点 P’。
当然这是对一个型值点而言,考虑所有型值点的情况下,每个公式中的控制点会有重复,手动设定的自由度可能会下降,但大致感觉最终应该还是会有很多自由度。当然,可以用数学公式具体来计算说明,在此不赘述,仅为了定性说明问题。下面有详细分析求解过程。
同样以 三次B样条为例,假设已知有 l+1 个型值点为 z 0 , z 1 , ⋯ , z l z_0,z_1,\cdots,z_l z0,z1,⋯,zl ;我们要插值生成的三次B样条参数有: n + 1 n+1 n+1 个控制点 P 0 , P 1 , ⋯ , P n P_0,P_1,\cdots,P_n P0,P1,⋯,Pn 和 m + 1 m+1 m+1 个节点 t 0 , t 1 , ⋯ , t m t_0,t_1,\cdots,t_m t0,t1,⋯,tm 。
首先需要明确的一点是,就目前来说,目标三次样条曲线中控制点个数没限制,节点数目没限制,仅有的一个限制是
m = n + k + 1 = n + 4 (1) m = n + k + 1 = n + 4 \tag{1} m=n+k+1=n+4(1)
对于每个没有限制的点(控制点、节点)都意味着一个个的自由度。下面开始施加限制
先考虑最重要的一点,即,使型值点与节点(确切说是,其在目标曲线上的点)对应,也即 z i = B ( t i ) z_i = B(t_i) zi=B(ti)。可以用如下图表示
上图中表示了, z 0 = B ( t 0 ) , z 1 = B ( t 1 ) , ⋯ , z n = B ( t m ) z_0 = B(t_0), z_1=B(t_1), \cdots, z_n = B(t_m) z0=B(t0),z1=B(t1),⋯,zn=B(tm),此时是最简单的对应关系,此时有 m = l m=l m=l。但此时会有个问题,因为有一个不可忽视的一点,样条曲线是有定义域的,对于三次样条,定义域为 [ t 3 , t n + 1 ] [t_3,t_{n+1}] [t3,tn+1],因此上述对应关系是有问题的,至少 z 0 z_0 z0 应该与定义域内第一个值 B ( t 3 ) B(t_3) B(t3) 对应。同样,最后一个 z l z_l zl 与 定义域内最后一个值 B ( t n + 1 ) B(t_{n+1}) B(tn+1) 对应。
上面提到了定义域的问题,一个极好的解决方案是使用 clamped B-spline
对于三次的 clamped B-样条,有
t 0 = t 1 = t 2 = t 3 = 0 t 4 , t 5 , ⋯ , t n ∈ [ 0 , 1 ] t n + 1 = t n + 2 = t n + 3 = t n + 4 = 1 t_0 = t_1 = t_2 = t_3 = 0 \\ t_4,t_5,\cdots,t_{n} \in[0,1] \\ t_{n+1} = t_{n+2} = t_{n+3} = t_{n+4} = 1 t0=t1=t2=t3=0t4,t5,⋯,tn∈[0,1]tn+1=tn+2=tn+3=tn+4=1
而定义域为 [ t 3 , t n + 1 ] [t_3,t_{n+1}] [t3,tn+1] ,因此我们采用的对应关系为
t 3 ⇔ z 0 t 5 ⇔ z 1 ⋮ t n + 1 ⇔ z l t_3 \Leftrightarrow z_0 \\ t_5 \Leftrightarrow z_1 \\ \vdots \\ t_{n+1} \Leftrightarrow z_l t3⇔z0t5⇔z1⋮tn+1⇔zl
也即有
z 0 = B ( t 3 ) = B ( 0 ) ⋮ z j = B ( t j + 3 ) ⋮ z l = B ( t n + 1 ) = B ( 1 ) (2) z_0 = B(t_3) = B(0) \\ \vdots \\ z_j = B(t_{j+3}) \\ \vdots \\ z_l = B(t_{n+1})=B(1) \tag{2} z0=B(t3)=B(0)⋮zj=B(tj+3)⋮zl=B(tn+1)=B(1)(2)
此时, n + 1 = l + 3 n+1 = l+3 n+1=l+3 即满足 n = l + 2 n = l+2 n=l+2。
综上所述,根据限制,我们需要满足的关系有:
需要设定样条的控制点的数目比型值点多2个,即
n = l + 2 n = l + 2 n=l+2
需要设定的节点数目比型值点多6个,即
m = n + k + 1 = l + 2 + 3 + 1 = l + 6 m = n + k + 1 = l+2+3+1=l+6 m=n+k+1=l+2+3+1=l+6
满足一系列关系式(共 l + 1 l+1 l+1 个)
z j − 3 = B ( t j ) = B j − 3 , 3 ( t j ) P j − 3 + B j − 2 , 3 ( t j ) P j − 2 + B j − 1 , 3 ( t j ) P j − 1 + B j , 3 ( t j ) P j , j = 3 , 4 , ⋯ , l + 3 z_{j-3} = B(t_j) =B_{j-3,3}(t_j)\ P_{j-3} + B_{j-2,3}(t_j)\ P_{j-2} + B_{j-1,3}(t_j)\ P_{j-1} + B_{j,3}(t_j)\ P_j\ ,\ \ \ j = 3,4,\cdots,l+3 zj−3=B(tj)=Bj−3,3(tj) Pj−3+Bj−2,3(tj) Pj−2+Bj−1,3(tj) Pj−1+Bj,3(tj) Pj , j=3,4,⋯,l+3
且对于 B j , 3 , B j − 1 , 3 , B j − 2 , 3 , B j − 3 , 3 B_{j,3},B_{j-1,3},B_{j-2,3},B_{j-3,3} Bj,3,Bj−1,3,Bj−2,3,Bj−3,3 ,带入(*)公式得
B j − 3 , 3 ( t j ) = ( t j + 1 − t j ) 2 ( t j + 1 − t j − 2 ) ( t j + 1 − t j − 1 ) B j − 2 , 3 ( t j ) = ( t j − t j − 2 ) ( t j + 1 − t j ) 2 ( t j + 1 − t j − 2 ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) + ( t j + 2 − t j ) ( t j − t j − 1 ) ( t j + 2 − t j − 1 ) ( t j + 1 − t j − 1 ) B j − 1 , 3 ( t j ) = ( t j − t j − 1 ) 2 ( t j + 1 − t j ) ( t j + 2 − t j − 1 ) ( t j + 1 − t j − 1 ) ( t j + 1 − t j ) B j , 3 ( t j ) = ( t − t j ) 3 ( t j + 3 − t j ) ( t j + 2 − t j ) ( t j + 1 − t j ) = 0 \begin{aligned} &B_{j-3,3}(t_j) = \frac{(t_{j+1}-t_j)^2}{(t_{j+1}-t_{j-2})(t_{j+1}-t_{j-1})} \\ &B_{j-2,3}(t_j) = \frac{(t_j-t_{j-2})(t_{j+1}-t_j)^2}{(t_{j+1}-t_{j-2})(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} + \frac{(t_{j+2}-t_j)(t_j-t_{j-1})}{(t_{j+2}-t_{j-1})(t_{j+1}-t_{j-1})} \\ &B_{j-1,3}(t_j) = \frac{(t_j-t_{j-1})^2(t_{j+1}-t_j)}{(t_{j+2}-t_{j-1})(t_{j+1}-t_{j-1})(t_{j+1}-t_{j})} \\ &B_{j,3}(t_j) = \frac{(t-t_j)^3}{(t_{j+3}-t_j)(t_{j+2}-t_j)(t_{j+1}-t_j)} = 0\\ \end{aligned} Bj−3,3(tj)=(tj+1−tj−2)(tj+1−tj−1)(tj+1−tj)2Bj−2,3(tj)=(tj+1−tj−2)(tj+1−tj−1)(tj+1−tj)(tj−tj−2)(tj+1−tj)2+(tj+2−tj−1)(tj+1−tj−1)(tj+2−tj)(tj−tj−1)Bj−1,3(tj)=(tj+2