【B样条曲线:计算系数】

对这篇文章的翻译,仅学习。

B样条曲线:计算系数

尽管de Boor的算法是计算b样条曲线上对应于给定u的点的标准方法,但我们在许多情况下确实需要这些系数(例如,曲线插值和逼近)。我们将举例说明一种简单的方法。

给定一条由n+1个控制点P0, P1,…, Pn,和 m+1节 u0=u1=…=up=0, up+1, up+2,…, um-p-1, um-p=um-p+1=…= um=1,我们想计算系数N0,p(u), N1,p(u),…, Nn,p(u)对于任意给定在[0,1]内的u。一种简单的方法是使用下面的递归关系:
【B样条曲线:计算系数】_第1张图片
然而,这是一个非常耗时的过程。要计算Ni,p(u),我们需要计算Ni,p-1(u)和Ni+1,p-1(u)。为了计算Ni,p-1(u),我们需要计算Ni,p-2(u)和Ni+1,p-2(u)。为了计算Ni+1,p-1(u),我们需要Ni+1,p-2(u)和Ni+2,p-2(u)。正如你所看到的,Ni+1,p-2(u)出现了两次,因此,它的递归计算也将被重复。随着递归的深入,将会发生更多的重复计算。这与前面一页讨论的de Casteljau算法的递归版本非常相似。因此,计算速度非常慢。

有一个简单的方法。假设u在结跨度[uk,uk+1)中。b样条基函数的一个重要性质是,在[uk,uk+1)上p次基函数最多有p+1个非零,即:Nk-p,p(u), Nk-p+1,p(u), Nk-p+2,p(u),…, Nk-1,p(u), Nk,p(u)。根据定义,在[uk,uk+1)上0次的唯一非零基函数是Nk,0(u)。因此,系数可以从Nk,0(u)以“扇出”三角形形式计算,如下所示:
【B样条曲线:计算系数】_第2张图片
由于Nk,0(u)在结跨度[uk,uk+1)上= 1,其他0次b样条基函数在[uk,uk+1)上为0,我们可以从Nk,0(u)开始,计算1次Nk-1,1(u)和Nk,1(u)的基函数。从这两个值,我们可以计算出2次的基函数Nk-2,2(u), Nk-1,2(u)和Nk,2(u)。这个过程重复进行,直到计算出所有p+1个非零系数。

在这个计算中,像Nk-1,2(u)这样的“内部”值有一个左上前驱(即Nk-1,1(u))和一个左下前驱(即Nk,1(u));在上述三角形的右上方向边界上的值,如Nk-1,1(u),只有左下方向的前驱(即Nk,0(u));在这个三角形的右下方向边界上的值,如Nk,2(u),只有一个左上方向的前驱(即Nk,1(u))。因此,在右上(右下)方向边界上的值使用定义中的递归关系的第二(一)项。只有内部值同时使用这两项。基于上述观察,我们得到以下算法:

算法


上面的算法不是很高效。它的目的是用一种直观和易于理解的方式来说明这个想法。数组 N[] 保存了所有中间结果和最终结果。对于d阶,N[i]存储变量Ni,d(u)的值,最后N[k-d], N[k-d+1],…, N[k]包含非零系数。计算从d=1开始,因为我们知道唯一的非零基函数是Nk,0(u),如果u在节跨度[uk,uk+1)中。外层循环让度d从1到p。begin后面的第一个赋值语句只用一项计算Nk-d,d(u)(即它在三角形中的左下项,Nk-d+1,d-1(u)),内层for循环只用一项计算“内部”项,外层循环的最后一个语句只用一项计算Nk,d(u)(即它的左上项,在三角形中的Nk,d-1(u))。

你能让这个算法更高效吗?

你可能感兴趣的:(图形学,笔记,算法,学习)