数值计算 --- B样条函数(B-spline)

发布于:2022-08-03 ⋅ 阅读:(526) ⋅ 点赞:(0)

B-spline就是Basis Spline的简称:

        术语B-spline一词,是由Isaac Jacob Schoenberg创造的。一个n阶的B-spline函数,是一个变量为x的n-1次分段多项式函数f(x)。分段函数之间,段与段之间的断点被称为knots

B-spline的定义:

        B-spline,可以看成是一系列控制点(Control points)权重函数N_{i,D}(Weight function)的线性组合,简而言之,就是每个控制点乘以自己对应的权重系数然后再求和,就能得到B-spline曲线在对应位置的值。控制点是我们后期指定的,而权重函数是我们预先定义好的,不会因为q的改变而改变。

 


权重函数(注意:以下只讨论权重函数N,不涉及控制点CP)

权重函数N_{i,D}的定义: 

        函数N_{i,D}的定义,可以参考Cox–de Boor的递归公式。对于给定的knots,当D=1时,一阶权重函数N可以定义为:

        一阶权重函数的图像:

           有了一阶B函数以后,其他所有D>1的高阶权重函数都是基于这一函数生成的递归表达式:

 

 

其中权重函数N_{i,D}有如下特征:

        1,N_{i,D}是一个分段函数,其中,i表示第几段函数,D表示阶数

        2,如果N_{i,D}函数的阶数为D,则每段函数都是一个D-1次多项式。

        3,每段函数之间的断点,被称为knots,用非递减序列t0,t1,...tn表示,被称为knot vector

        4,一但knots确定了以后,那么每段函数之间的连续性等于D-2。

        5,对每一段权重函数而言,他只在固定的一个区间内有值,其他地方都为0。这个区间就是u的定义域,他等于[t_{i}~t_{i+D}),有些地方叫knot span,是一个半开半闭区间。(此处,对knot span的定义不一定严谨)

        

        比如说,对于上述的一阶权重函数N_{i,1}(u)而言,阶数D=1,每段函数都是一个D-1=0阶多项式。对于第i段函数而言,u的定义区间为[t_{i}~t_{i+1})对于第0段函数N_{0,1}(u)而言,他的knot span为[0,1),在[0,1)之间的函数值等于1,在这之外函数值都等于0。

 

        为了简化上面所提到的这个高阶权重函数的定义,也为了简化计算,一般情况下,会把knot vector也就是函数之间的断点t0,t1,...tn,简化成一组非常递减的正整数。简而言之,就是把原来的t0,t1,...tn换成了0,1,...n。

 

        为了更好的理解当D>1时的递归公式,我这里借用了一组别人的插图(见参考文献1)。

        首先,让我们把目光放在图中三角形的最左上角的一个小三角形,N_{0,1},N_{1,1}N_{0,2},其中还有两条红线把N_{0,1}N_{0,2}和 ​​​​​​​N_{1,1}N_{0,2} 分别连接了起来。他所要表达的是,要想求出二阶函数​​​​​​​N_{0,2},我们需要先知道一阶函数​​​​​​​N_{0,1}和​​​​​​​N_{1,1}。也就是说,要想知道上图大三角形中左起第二列的所有二阶函数N_{0,2}N_{1,2},。。。N_{4,2},必须先知道左起第一列的一阶函数N_{0,1}N_{1,1}。。。N_{5,1}。依此类推,当我们要计算六阶函数N_{0,6}时,首先需要先知道五阶函数N_{0,5}N_{1,5},其次我们需要相应的所有四阶函数,三阶函数。。。直到一阶函数。

 

        从公式的角度看也一样,根据简化后的公式,我们发现要想得到阶数为D的第i条曲线,比如说N_{0,1},需要先知道阶数为D-1的第i条曲线N_{0,0}和阶数为D-1的第i+1条曲线N_{1,0}。比D低一阶的两条基础曲线前面大括号内的值,实际上就是这两条曲线的权重。

        下面我们逐一探讨一下,几个不同阶数的权重函数N_{i,D}我这里再次强调,我们到目前为止都没有讨论过控制点CP,而只讨论权重函数,目的是为了避免让大家混淆权重函数和控制点,这两个B-spline中最重要的概念。因为,B-spline可以说就是这两个概念的线性组合,因为,只有分别理解他们的各自的作用,才能更好的理解B-spline。


一阶权重函数N_{i,1}(u)

         首先,我们知道权重函数都有一个有效区间,也就是u的定义域,函数在定义域之外的值都是0。一阶函数N_{i,1}(u),D=1,u=[i,i+1),有效区间为i+1。

         这里我们统一以7个knots为例,knot vector list t_{i}={0,1,2,3,4,5,6},每段函数的knot span为1。对于第0段函数,也就是当i=0时,u的定义域为[0,1),函数N_{0,1}(u)的断点knot为0,1。对于最后一段函数,也就是第5段函数,此时,i=5,u=[5,6),函数两端的端点knot为,5,6。注意,此时还没有用到递归函数。

 

 一阶权重函数N_{i,1}(u)的图像: 

 Matlab code:

 


 二阶权重函数N_{i,2}(u)

         二阶函数​​​​​​​N_{i,2}(u),D=2,u=[i,i+2),第i段函数的有效区间为i+2。 同样是7个knots,knot vector list t_{i}={0,1,2,3,4,5,6},每段函数的knot span=D=2。

        对于二阶权重函数的计算,此时我们需要用到递归函数(下图中的公式2)。

 

        首先,我们把重点放在公式中的阶数D,当我们要计算N_{i,D}(u),我们预先要知道N_{i,D-1}(u)N_{i+1,D-1}(u)。用文字来描述就是, 要想得到阶数为D的第i条曲线,需要预先知道阶数为D-1的第i条曲线和阶数同为为D-1的第i+1条曲线 。

        同样,现在我们分别把i=0,1,5和D=2代入简化后的公式2,看一下二阶权重函数。

         当i=0时,对于第0段函数N_{0,2}(u)而言,定义域u=[0,2)。但是,用于合成他的两个(2-1)一阶函数N_{0,1}(u)N_{1,1}(u)的定义域分别是[0,1)和[1,2)。这一点可以借助之前的递归图更好的看明白:

        因此,当u=[0,1)时,仅仅只有函数N_{0,1}(u)对函数N_{0,2}(u)起作用,也就是上式中的前半部分uN_{0,1}(u)。此时,N_{1,1}(u)等于0,N_{0,1}(u)等于1,N_{0,2}(u)=u。同理, 当u=[1,2)时,仅仅只有函数​​​​​​​N_{1,1}(u)对函数N_{0,2}(u)起作用,也就是上式中的后半部分(2-u)N_{1,1}(u)。 此时,​​​​​​​N_{0,1}(u)等于0,N_{1,1}(u)等于1,N_{0,2}(u)=2-u。如下图所示: 

 

        当i=1时,u=[1,3):

 

         当i=4时,u=[4,6):

 

  二阶权重函数N_{i,2}(u)的图像: 

 

        这里我对上图进行一个简单的说明,我们看上图中的第一幅图,也就是N_{0,2}(u)的函数图像,他的第一段函数在0~1之间,此时y(u)=u,这是一个标准的y=x的函数图像,此时斜率为45°。现在我们把目光移到他的右半边,也就是第一段函数在1~2之间的图像,此时y(u)=2-u。熟悉函数图像的同学马上就会发现,他其实就是把y=-x的图像向上移动了2位得到的。

 Matlab code:


 

三阶权重函数N_{i,3}(u) 

        三阶函数N_{i,3}(u),D=3,u=[i,i+3),第i段函数的有效区间为i+3。 总共7个knots,knot vector list t_{i}={0,1,2,3,4,5,6},每段函数的knot span=D=3。

         按照Cox–de Boor递归公式,要求三阶的权重函数,首先我们要先知道二阶的权重函数,而这些函数都已经在前面求出来了。

        和前面一样,我们把i=0,1,4和D=3逐一代入简化后的公式2,逐一看一下三阶权重函数。首先我们来看一下三阶权重函数的第0段函数,也就是当i=0时,u=[0,3)时的函数N_{0,3}(u): 

化简后得: 

         我们可以看到,和前面一样,为了求出N_{0,3}(u),我们需要先知道N_{0,2}(u)N_{1,2}(u)(前面已经算好了)。此时,我们要特别注意函数N_{0,3}(u)的定义域u=[0,3),用于合成他的子函数之一N_{0,2}(u)的定义域是[0,2),继而我们还会发现,对于N_{0,2}(u)而言,用于合成他的子函数之一N_{0,1}(u)的定义域是[0,1),在这以外都是0。也就是说,对于这个递归分段函数,我们要特别注意他的有效区间,或者说是每一小段子函数的有效定义域。(这在递归图中会更加直观)

 1,当u=[0,1)时:

        此时,只有N_{0,2}(u)在此处有定义,其他都为0。因此,这时只有N_{0,2}(u)对函数N_{0,3}(u)起作用, 此时,​​​​​​​N_{0,2}(u)等于u,​​​​​​​N_{1,2}(u)等于0,​​​​​​​N_{0,3}(u)=u^2/2。

 

2,   当u=[1,2)时:

          此时,N_{0,2}(u)N_{1,2}(u)都有定义,他们同时对函数N_{0,3}(u)起作用, 此时,N_{0,2}(u)在[1,2)上等于2-u,​​​​​​​N_{1,2}(u)在[1,2)上等于u-1,​​​​​​​N_{0,3}(u)=(-2u^2+6u-3)/2。

 

3,   当u=[2,3)时:

     

   此时,只有​​​​​​​N_{1,2}(u)在此处有定义,其他都为0。因此,这时只有​​​​​​​N_{1,2}(u)对函数N_{0,3}(u)起作用。此时,​​​​​​​N_{1,2}(u)等于3-u,​​​​​​​​​​​​​​N_{0,2}(u)等于0,​​​​​​​N_{0,3}(u)=(3-u)^2/2。

 

当i=1时,u=[1,4): 

 

当i=3时,u=[3,6):  

 

 

  三阶B-spline的函数图像: 

 

 Matlab code:

 


补充:

(全文完)

作者 --- 松下J27

谢谢收看!

参考文献:

1,B-spline Basis Functions: Definition

2,

诗词赏析:

遣悲怀三首·其二》--- 元稹

昔日戏言身后意,今朝都到眼前来。(身后意 一作:身后事)
衣裳已施行看尽,针线犹存未忍开。
尚想旧情怜婢仆,也曾因梦送钱财。
诚知此恨人人有,贫贱夫妻百事哀。

 (配图与本文无关)  

版权声明:所有的笔记,可能来自很多不同的网站和说明,在此没法一一列出,如有侵权,请告知,立即删除。欢迎大家转载,但是,如果有人引用或者COPY我的文章,必须在你的文章中注明你所使用的图片或者文字来自于我的文章,否则,侵权必究。 ----松下J27

本文含有隐藏内容,请 开通VIP 后查看

微信公众号

今日签到

点亮在社区的每一天
去签到