B-Spline Curve Library in Open Cascade
Posted on 2013-03-12 20:48 eryar 閱讀(9636) 評(píng)論(1) 編輯 收藏 引用 所屬分類: 2.OpenCASCADEB-Spline Curve Library in Open Cascade
Open Cascade中的B樣條曲線庫(kù)
摘要Abstract:簡(jiǎn)要介紹Open Cascade中的B樣條曲線庫(kù)BSplCLib的使用方法,并且結(jié)合源程序來對(duì)Open Cascade中的B樣條曲線的組成部分如節(jié)點(diǎn)矢量、重復(fù)度等概念進(jìn)行介紹,以及通過對(duì)計(jì)算B樣條基函數(shù)的算法進(jìn)行分析,加深對(duì)B樣條曲線概念的理解。
關(guān)鍵字Key Word:B Spline Curve、Open Cascade、Knot Vector、Multiplicity
一、 概述 Overview
1946年由Schoenberg提出了B樣條理論,給出了B樣條的差分表達(dá)式;1972年de Boor和Cox分別獨(dú)立給出了關(guān)于B樣條的標(biāo)準(zhǔn)算法。Gordon和Riesenfeld又把B樣條理論用于形狀描述,最終提出了B樣條方法。用B樣條基替代了Bernstein基,構(gòu)造出B樣條曲線,這種方法繼承了Bezier方法的一切優(yōu)點(diǎn),克服了Bezier方法存在的缺點(diǎn),較成功地解決了局部控制問題,又輕而易舉地在參數(shù)連續(xù)性基礎(chǔ)上解決了連接問題,從而使自由曲線曲面形狀的描述問題得到較好解決。
p次B樣條曲線的定義為:
其中:
l Pi是控制頂點(diǎn)(control point);
l Ni,p(u)是定義在非周期節(jié)點(diǎn)矢量上的p次B樣條基函數(shù);
有很多方法可以用來定義B樣條基函數(shù)以及證明它的一些重要性質(zhì)。例如,可以采用截尾冪函數(shù)的差商定義,開花定義,以及由de Boor和Cox等人提出的遞推公式等來定義。我們這里采用的是遞推定義方法,因?yàn)檫@種方法在計(jì)算機(jī)實(shí)現(xiàn)中是最有效的。
令U={u0,u1,…,um}是一個(gè)單調(diào)不減的實(shí)數(shù)序列,即ui<=ui+1,i=0,1,…,m-1。其中,ui稱為節(jié)點(diǎn),U稱為節(jié)點(diǎn)矢量,用Ni,p(u)表示第i個(gè)p次B樣條基函數(shù),其定義為:
B樣條基有如下性質(zhì):
a) 遞推性;
b) 局部支承性;
c) 規(guī)范性;
d) 可微性;
根據(jù)B樣條曲線定義可知,給定控制頂點(diǎn)Pi(control points),曲線次數(shù)p(degree)及節(jié)點(diǎn)矢量U(knot vectors),B樣曲線也就確定。對(duì)于有理B樣條曲線,還需要參數(shù)權(quán)重(weights)。
二、 OCC中的B樣條曲線庫(kù) BSplCLib in OCC
在Open Cascade中的工具箱(Toolkit)TKMath中的包(package)BSplCLib是B樣條曲線庫(kù),為B樣條曲線曲面的計(jì)算提供了支持。它提供了三方面的功能:
l 對(duì)節(jié)點(diǎn)矢量(knot vectors)及重復(fù)度(multiplicities)的管理;
l 對(duì)多維樣條的支持,即B樣條方法中控制頂點(diǎn)的維數(shù)可以是任意維數(shù)(dimension);
l 二維和三維樣條曲線的方法;
Open Cascade中的B樣條曲線由下列數(shù)據(jù)項(xiàng)定義:
定義 |
變量類型 |
變量名稱 |
控制頂點(diǎn)control points |
TColgp_Array1OfPnt |
Poles |
權(quán)重weights |
TColStd_Array1OfReal |
Weights |
節(jié)點(diǎn)knots |
TColStd_Array1OfReal |
Knots |
重?cái)?shù)multiplicities |
TColStd_Array1OfInteger |
Mults |
次數(shù)degree |
Standard_Integer |
Degree |
周期性periodicity |
Standard_Boolean |
Periodic |
B樣條曲線庫(kù)BSplCLib提供了一些基本幾何算法:
l B樣條基函數(shù)及其導(dǎo)數(shù)的計(jì)算BSplCLib::EvalBsplineBasis();
l 節(jié)點(diǎn)插入BSplCLib::InsertKnot();
l 節(jié)點(diǎn)去除BSplCLib::RemoveKnot();
l 升階BSplCLib::IncreaseDegree();
l 降階;
結(jié)合《The NURBS Book》和Open Cascade中的BSplCLib的源程序,可以高效的學(xué)習(xí)NURBS。《The NURBS Book》中有詳細(xì)的理論推導(dǎo)及算法描述,而Open Cascade中有可以用來實(shí)際使用的程序。理論聯(lián)系實(shí)際,有助于快速理解NURBS的有關(guān)概念及其應(yīng)用。
三、 OCC中B樣條曲線庫(kù)的節(jié)點(diǎn)和重?cái)?shù)Knots and Multiplicity in BSplCLib
由B樣條曲線的可微性可知,節(jié)點(diǎn)的重?cái)?shù)與B樣條曲線的連續(xù)性相關(guān)。在節(jié)點(diǎn)區(qū)間內(nèi)部,Ni,p(u)是無限次可微的,因在每個(gè)節(jié)點(diǎn)區(qū)間內(nèi)部,它是一個(gè)多項(xiàng)式。在節(jié)點(diǎn)處Ni,p(u)是p-k次連續(xù)的,其中k是節(jié)點(diǎn)的重復(fù)度(multiplicity,有時(shí)也稱為重?cái)?shù))。因此,增加次數(shù)p將提高曲線的連續(xù)性,而增加節(jié)點(diǎn)的重復(fù)度則使連續(xù)性降低。
重復(fù)度(multiplicity,有時(shí)也稱為重?cái)?shù))有兩種不同的理解方式:
l 節(jié)點(diǎn)在節(jié)點(diǎn)矢量中的重復(fù)度;
l 節(jié)點(diǎn)相對(duì)于一個(gè)特定的基函數(shù)的重復(fù)度;
在Open Cascade中對(duì)重復(fù)度的理解是前者,即節(jié)點(diǎn)在節(jié)點(diǎn)矢量中的重復(fù)度。下面結(jié)合源程序來進(jìn)行說明。
函數(shù)BSplCLib::Knots()用來將給定的節(jié)點(diǎn)矢量(節(jié)點(diǎn)序列knot sequence)轉(zhuǎn)換為節(jié)點(diǎn)的重復(fù)度不大于1的Knots數(shù)組和每個(gè)節(jié)點(diǎn)對(duì)應(yīng)的重復(fù)度Mults數(shù)組,且數(shù)據(jù)Knots和Mults的長(zhǎng)度必由函數(shù)BSplCLib::KnotsLength()得到。Knots()函數(shù)的源程序如下所示:

































































從上述代碼可知,直接使用了不等于來判斷兩個(gè)節(jié)點(diǎn)的值是否相同,而沒有采用誤差處理,即嚴(yán)格的相等比較。程序?qū)⒐?jié)點(diǎn)重復(fù)度不大于1的節(jié)點(diǎn)及其相應(yīng)的重復(fù)度分別保存到knots和mult中。
四、 B樣條曲線的分類 B Spline Curve Type
B樣條曲線一般按定義基函數(shù)的節(jié)點(diǎn)序列是否等距(均勻)分為均勻B樣條曲線(Uniform B-Spline Curve)和非均勻B樣條曲線(Non Uniform B-Spline Curve)。
B樣條曲線按節(jié)點(diǎn)序列中節(jié)點(diǎn)分布情況不同,又分為四種類型:均勻B樣條曲線、準(zhǔn)均勻B樣條曲線、分段Bezier曲線、一般非均勻B樣條曲線。設(shè)給定特征多邊形頂點(diǎn)Vi,i=0,1,…,n,曲線次數(shù)k,則有:
l 均勻B樣條曲線(uniform B-Spline curve):節(jié)點(diǎn)序列中節(jié)點(diǎn)沿參數(shù)軸均勻或等距分布,即所有節(jié)點(diǎn)區(qū)間長(zhǎng)度為大于零的常數(shù)(constant):
l 準(zhǔn)均勻B樣曲線(quasi-uniform B-Spline curve):其節(jié)點(diǎn)序列中兩端節(jié)點(diǎn)具有重復(fù)度k+1,而所有內(nèi)節(jié)點(diǎn)均勻分布,具有重復(fù)度1。
l 分段Bezier曲線(piecewise Bezier curve):其節(jié)點(diǎn)序列中兩端節(jié)點(diǎn)重復(fù)度與準(zhǔn)均勻B樣條曲線的相同,所不同的是所有內(nèi)節(jié)點(diǎn)重復(fù)度為k。
l 非均勻B樣條曲線(general non-uniform B-Spline curve):這是對(duì)任意分布的節(jié)點(diǎn)序列,只要在數(shù)學(xué)上成立,即節(jié)點(diǎn)序列非遞減,都可取。
在基礎(chǔ)類模塊(Module FoundationClasses)的工具箱(Toolkit TKMath)中的包(GeomAbs)中有對(duì)B樣樣條曲線類型的定義,源程序如下所示:
enum GeomAbs_BSplKnotDistribution {
GeomAbs_NonUniform,
GeomAbs_Uniform,
GeomAbs_QuasiUniform,
GeomAbs_PiecewiseBezier
};
而類BSplCLib主要是用來管理節(jié)點(diǎn)和重復(fù)度的,所有將節(jié)點(diǎn)和重復(fù)度也進(jìn)行了分類。根據(jù)節(jié)點(diǎn)矢量是否均勻分布,將節(jié)點(diǎn)分配方式(Knot Distribution)分為:均勻(BSplCLib_Uniform)和非均勻(BSplCLib_NonUniform)。源程序如下所示:
BSplCLib_NonUniform,
BSplCLib_Uniform
};
根據(jù)重復(fù)度數(shù)組將重復(fù)度的分配方式分為如下三種類型:
n BSplCLib_Constant:重復(fù)度都相同;
n BSplCLib_QuasiConstant:首、尾節(jié)點(diǎn)的重復(fù)度與內(nèi)部節(jié)點(diǎn)的重復(fù)度不同;
n BSplClib_NonConstant:其它情況;
源程序如下所示:
BSplCLib_NonConstant,
BSplCLib_Constant,
BSplCLib_QuasiConstant
};
判斷節(jié)點(diǎn)矢量和重復(fù)度矢量類型分別由下列函數(shù)實(shí)現(xiàn):
l BSplCLib::KnotForm();
l BSplCLib::MultForm();
具體的判斷方法可以查看源程序。
將節(jié)點(diǎn)分布方式與重復(fù)度的分布方式進(jìn)行組合,可以得出B樣條曲線的那幾種類型。
五、 B樣條基函數(shù)的計(jì)算 Evaluate the B-Spline Basis
B樣條基函數(shù)的計(jì)算主要使用了B樣條基了函數(shù)的遞推公式(Cox-deBoor公式)的局部支撐性質(zhì),如下所示:
直接由定義可知:
l Ni,0(u)是一個(gè)階梯函數(shù),它在半開區(qū)間u∈[ui, ui+1)外都為零;
l 當(dāng)次數(shù)p>0時(shí),Ni,p(u)是兩個(gè)p-1次基函數(shù)的線性組合;
l 計(jì)算一組基函數(shù)需要事先指定節(jié)點(diǎn)矢量U和次數(shù)p;
l 半開區(qū)間[ui,ui+1)稱為第i個(gè)節(jié)點(diǎn)區(qū)間(knot span),它的長(zhǎng)度可以為零,因?yàn)橄噜徆?jié)點(diǎn)可以是相同的;
l 計(jì)算p次基函數(shù)的過程可以生成一個(gè)如下形式的三角形陳列:
B樣條有局部支撐性,即若u不在區(qū)間[ui, ui+p+1),則Ni,p(u)=0。可從下面的三角形中看出N1,3是N1,0、N2,0、N3,0和N4,0的線性組合,而N1,0在區(qū)間[u1, u2)上非零,N2,0在區(qū)間[u2,u3)上非零,N3,0在區(qū)間[u3,u4)上非零,N4,0在區(qū)間[u4,u5)上非零,所以N1,3僅在區(qū)間[u1,u5)上非零。
在任意給定的節(jié)點(diǎn)區(qū)間[uj,uj+1)內(nèi),最多有p+1個(gè)是非零的,它們是Nj-p,p、Nj-p+1、…、Nj,p。例如,在[u3,u4)上,零次基函數(shù)中只有N3,0是非零的,一次基函數(shù)只有N2,1和N3,1是非零的,非零的三次基函數(shù)只有N0,3、N1,3、N2,3、N3,3。這個(gè)性質(zhì)如下圖所示:
上面兩幅圖中右邊的圖中所示的推算過程表明,給定節(jié)點(diǎn)序列U及B樣條曲線的次數(shù)p,給出任意一個(gè)u值,找出其所在的節(jié)點(diǎn)區(qū)間[ui,ui+1)上,最多有Ni-p,p,Ni-p+1,p,…,Ni,p個(gè)非零的基函數(shù)。
例如我們根據(jù)遞推公式寫出二次基函數(shù)的一般形式,如下所示:
當(dāng)給定的u值在區(qū)間[u3,u4)上即(i=3)時(shí),根據(jù)上面的三角形,得出下列重要結(jié)論:
即這兩項(xiàng)不需要計(jì)算。另外一個(gè)重要結(jié)論就是圖中用相同顏色框中的部分是相同的,也就是下面程序中的變量temp表示的內(nèi)容。
我們引入下面符號(hào):
由二次基函數(shù)推出的三個(gè)公式可寫為:
上述推導(dǎo)過程為《The NURBS Book》中的算法,算法代碼如下所示:
理解了變量temp的意義之后,整個(gè)程序就很好理解了。
將Open Cascade中計(jì)算基函數(shù)的算法是不同的,將其源程序摘抄如下所示:
//function : Build BSpline Matrix
//purpose : Builds the Bspline Matrix
//=======================================================================
Standard_Integer
BSplCLib::EvalBsplineBasis
//(const Standard_Integer Side, // = 1 rigth side, -1 left side
(const Standard_Integer , // = 1 rigth side, -1 left side
const Standard_Integer DerivativeRequest,
const Standard_Integer Order,
const TColStd_Array1OfReal& FlatKnots,
const Standard_Real Parameter,
Standard_Integer& FirstNonZeroBsplineIndex,
math_Matrix& BsplineBasis)
{
// the matrix must have at least DerivativeRequest + 1
// row and Order columns
// the result are stored in the following way in
// the Bspline matrix
// Let i be the FirstNonZeroBsplineIndex and
// t be the parameter value, k the order of the
// knot vector, r the DerivativeRequest :
//
// B (t) B (t) B (t)
// i i+1 i+k-1
//
// (1) (1) (1)
// B (t) B (t) B (t)
// i i+1 i+k-1
//
//
//
//
// (r) (r) (r)
// B (t) B (t) B (t)
// i i+1 i+k-1
//
Standard_Integer
ReturnCode,
ii,
pp,
qq,
ss,
NumPoles,
LocalRequest ;
// ,Index ;
Standard_Real NewParameter,
Inverse,
Factor,
LocalInverse,
Saved ;
// , *FlatKnotsArray ;
ReturnCode = 0 ;
FirstNonZeroBsplineIndex = 0 ;
LocalRequest = DerivativeRequest ;
if (DerivativeRequest >= Order) {
LocalRequest = Order - 1 ;
}
if (BsplineBasis.LowerCol() != 1 ||
BsplineBasis.UpperCol() < Order ||
BsplineBasis.LowerRow() != 1 ||
BsplineBasis.UpperRow() <= LocalRequest) {
ReturnCode = 1;
goto FINISH ;
}
NumPoles = FlatKnots.Upper() - FlatKnots.Lower() + 1 - Order ;
BSplCLib::LocateParameter(Order - 1,
FlatKnots,
Parameter,
Standard_False,
Order,
NumPoles+1,
ii,
NewParameter) ;
FirstNonZeroBsplineIndex = ii - Order + 1 ;
BsplineBasis(1,1) = 1.0e0 ;
LocalRequest = DerivativeRequest ;
if (DerivativeRequest >= Order) {
LocalRequest = Order - 1 ;
}
for (qq = 2 ; qq <= Order - LocalRequest ; qq++) {
BsplineBasis(1,qq) = 0.0e0 ;
for (pp = 1 ; pp <= qq - 1 ; pp++) {
//
// this should be always invertible if ii is correctly computed
//
Factor = (Parameter - FlatKnots(ii - qq + pp + 1))
/ (FlatKnots(ii + pp) - FlatKnots(ii - qq + pp + 1)) ;
Saved = Factor * BsplineBasis(1,pp) ;
BsplineBasis(1,pp) *= (1.0e0 - Factor) ;
BsplineBasis(1,pp) += BsplineBasis(1,qq) ;
BsplineBasis(1,qq) = Saved ;
}
}
for (qq = Order - LocalRequest + 1 ; qq <= Order ; qq++) {
for (pp = 1 ; pp <= qq - 1 ; pp++) {
BsplineBasis(Order - qq + 2,pp) = BsplineBasis(1,pp) ;
}
BsplineBasis(1,qq) = 0.0e0 ;
for (ss = Order - LocalRequest + 1 ; ss <= qq ; ss++) {
BsplineBasis(Order - ss + 2,qq) = 0.0e0 ;
}
for (pp = 1 ; pp <= qq - 1 ; pp++) {
Inverse = 1.0e0 / (FlatKnots(ii + pp) - FlatKnots(ii - qq + pp + 1)) ;
Factor = (Parameter - FlatKnots(ii - qq + pp + 1)) * Inverse ;
Saved = Factor * BsplineBasis(1,pp) ;
BsplineBasis(1,pp) *= (1.0e0 - Factor) ;
BsplineBasis(1,pp) += BsplineBasis(1,qq) ;
BsplineBasis(1,qq) = Saved ;
LocalInverse = (Standard_Real) (qq - 1) * Inverse ;
for (ss = Order - LocalRequest + 1 ; ss <= qq ; ss++) {
Saved = LocalInverse * BsplineBasis(Order - ss + 2, pp) ;
BsplineBasis(Order - ss + 2, pp) *= - LocalInverse ;
BsplineBasis(Order - ss + 2, pp) += BsplineBasis(Order - ss + 2,qq) ;
BsplineBasis(Order - ss + 2,qq) = Saved ;
}
}
}
FINISH :
return (ReturnCode) ;
}
函數(shù)的作用是用來計(jì)算所有的基函數(shù)及其導(dǎo)數(shù),并將結(jié)果以矩陣(數(shù)組)的形式保存。結(jié)合二次基函數(shù)的推導(dǎo)方法,將述代碼寫成公式的形式。函數(shù)的參數(shù)及其描述如下表所示:
變量 |
描述 |
DerivativeRequest |
導(dǎo)數(shù)的次數(shù) |
Order |
B樣條基函數(shù)的階數(shù)(次數(shù)+1) |
FlatKnots |
節(jié)點(diǎn)矢量 |
Parameter |
參數(shù) |
FirstNonZeroBspline |
第一個(gè)非零基函數(shù)的索引值 |
BsplineBasis |
基函數(shù)值矩陣 |
當(dāng)導(dǎo)數(shù)次數(shù)DerivativeRequest大于B樣條基的階數(shù)Order時(shí),將計(jì)算導(dǎo)數(shù)的次數(shù)設(shè)置為B樣條基的次數(shù)(Order-1)。程序代碼如下所示:
if (DerivativeRequest >= Order) {
LocalRequest = Order - 1 ;
}
對(duì)B樣條基數(shù)計(jì)算結(jié)果矩陣BsplineBasis存儲(chǔ)空間進(jìn)行檢查。若存儲(chǔ)空間不足,則會(huì)退出,程序代碼如下所示:
BsplineBasis.UpperCol() < Order ||
BsplineBasis.LowerRow() != 1 ||
BsplineBasis.UpperRow() <= LocalRequest) {
ReturnCode = 1;
goto FINISH ;
}
確定參數(shù)Parameter所在的節(jié)點(diǎn)區(qū)間的下標(biāo)(索引值),程序代碼如下所示:
BSplCLib::LocateParameter(Order - 1,
FlatKnots,
Parameter,
Standard_False,
Order,
NumPoles+1,
ii,
NewParameter) ;
確定參數(shù)Parameter所在區(qū)間的算法是用二分法搜索得到。程序代碼如下所示:
//function : Hunt
//purpose :
//=======================================================================
void BSplCLib::Hunt (const Array1OfReal& XX,
const Standard_Real X,
Standard_Integer& Ilc)
{
// replaced by simple dichotomy (RLE)
Ilc = XX.Lower();
const Standard_Real *px = &XX(Ilc);
px -= Ilc;
if (X < px[Ilc]) {
Ilc--;
return;
}
Standard_Integer Ihi = XX.Upper();
if (X > px[Ihi]) {
Ilc = Ihi + 1;
return;
}
Standard_Integer Im;
while (Ihi - Ilc != 1) {
Im = (Ihi + Ilc) >> 1;
if (X > px[Im]) Ilc = Im;
else Ihi = Im;
}
}
確定參數(shù)所在區(qū)間[ui,ui+1)后,可得到第一個(gè)非零基函數(shù)的索引值為i-p;
FirstNonZeroBsplineIndex = ii - Order + 1 ;
基函數(shù)計(jì)算的主要算法代碼如下所示:
for (qq = 2 ; qq <= Order - LocalRequest ; qq++) {
BsplineBasis(1,qq) = 0.0e0 ;
for (pp = 1 ; pp <= qq - 1 ; pp++) {
//
// this should be always invertible if ii is correctly computed
//
Factor = (Parameter - FlatKnots(ii - qq + pp + 1))
/ (FlatKnots(ii + pp) - FlatKnots(ii - qq + pp + 1)) ;
Saved = Factor * BsplineBasis(1,pp) ;
BsplineBasis(1,pp) *= (1.0e0 - Factor) ;
BsplineBasis(1,pp) += BsplineBasis(1,qq) ;
BsplineBasis(1,qq) = Saved ;
}
}
其中:
為節(jié)點(diǎn)區(qū)間[ui,ui+1)上的基函數(shù)左邊部分的系數(shù);
為節(jié)點(diǎn)區(qū)間[ui-1,ui)上的基函數(shù)右邊部分的系數(shù);
六、 程序示例 Sample Codes
將上述內(nèi)容以一個(gè)簡(jiǎn)單示例程序來驗(yàn)證,程序代碼如下所示:
* Copyright (c) 2013 eryar All Rights Reserved.
*
* File : Main.cpp
* Author : eryar@163.com
* Date : 2013-03-09
* Version :
*
* Description : Learn the B-Spline Curve library in the Open Cascade.
*
*/
#include <BSplCLib.hxx>
#include <math_Matrix.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <Geom2d_BSplineCurve.hxx>
#pragma comment(lib, "TKernel.lib")
#pragma comment(lib, "TKMath.lib")
#pragma comment(lib, "TKG2d.lib")
int main(int argc, char* argv[])
{
// Knot vector: [0,0,0,1,2,3,4,4,5,5,5]
TColStd_Array1OfReal knotSeq(1, 11);
knotSeq.Init(0);
knotSeq.SetValue(1, 0);
knotSeq.SetValue(2, 0);
knotSeq.SetValue(3, 0);
knotSeq.SetValue(4, 1);
knotSeq.SetValue(5, 2);
knotSeq.SetValue(6, 3);
knotSeq.SetValue(7, 4);
knotSeq.SetValue(8, 4);
knotSeq.SetValue(9, 5);
knotSeq.SetValue(10, 5);
knotSeq.SetValue(11, 5);
cout<<"Knot Sequence: [ ";
for (Standard_Integer i = 1; i <= knotSeq.Length(); i++)
{
cout<<knotSeq.Value(i)<<" ";
}
cout<<"]"<<endl;
Standard_Integer knotsLen = BSplCLib::KnotsLength(knotSeq);
TColStd_Array1OfReal knots(1, knotsLen);
TColStd_Array1OfInteger mults(1, knotsLen);
// Test Knots, Mults and Knot sequence of BSplCLib.
BSplCLib::Knots(knotSeq, knots, mults);
cout<<"Knots: [ ";
for (Standard_Integer i = 1; i <= knots.Length(); i++)
{
cout<<knots.Value(i)<<" ";
}
cout<<"]"<<endl;
cout<<"Multiplicity: [ ";
for (Standard_Integer i = 1; i <= mults.Length(); i++)
{
cout<<mults.Value(i)<<" ";
}
cout<<"]"<<endl;
if (BSplCLib::KnotForm(knots, 1, knotsLen) == BSplCLib_Uniform)
{
cout<<"Knots is uniform."<<endl;
}
else
{
cout<<"Knots is non-uniform."<<endl;
}
Standard_Real rValue = 2.5;
Standard_Integer iOrder = 2+1;
Standard_Integer iFirstNonZeroIndex = 0;
math_Matrix bSplineBasis(1, 1, 1, iOrder, 0);
BSplCLib::EvalBsplineBasis(1, 0, iOrder, knotSeq, rValue, iFirstNonZeroIndex, bSplineBasis);
cout<<"First Non-Zero Basis index: "<<iFirstNonZeroIndex<<endl;
cout<<bSplineBasis<<endl;
return 0;
}
上述代碼對(duì)節(jié)點(diǎn)矢量、重復(fù)度的概念的驗(yàn)證,并以一個(gè)實(shí)例計(jì)算所有非零基函數(shù)的值。程序輸出為:
Knot Sequence: [ 0 0 0 1 2 3 4 4 5 5 5 ]
Knots: [ 0 1 2 3 4 5 ]
Multiplicity: [ 3 1 1 1 2 3 ]
Knots is uniform.
First Non-Zero Basis index: 3
math_Matrix of RowNumber = 1 and ColNumber = 3
math_Matrix ( 1, 1 ) = 0.125
math_Matrix ( 1, 2 ) = 0.75
math_Matrix ( 1, 3 ) = 0.125
Press any key to continue . . .
七、 結(jié)論 Conclusion
通過學(xué)習(xí)《The NURBS Book》并給合Open Cascade的源程序,理論聯(lián)系實(shí)際,使對(duì)NURBS的學(xué)習(xí)更輕松。
根據(jù)B樣條基的遞推公式,B樣條曲線的局部性是通過節(jié)點(diǎn)來具體實(shí)現(xiàn)的。與Bezier曲線不同的就是增加了節(jié)點(diǎn)這個(gè)參數(shù)。根據(jù)Cox-deBoor遞推公式親自推導(dǎo)出一次、二次、三次B樣條基函數(shù),可以加深對(duì)B樣條曲線的理解。
計(jì)算給定節(jié)點(diǎn)矢量、次數(shù)及參數(shù),計(jì)算參數(shù)所在區(qū)間上所有非零基函數(shù)算法的步驟為:
l 通過二分法查找出參數(shù)所在的節(jié)點(diǎn)區(qū)間;
l 根據(jù)B樣條基的局部支撐性,計(jì)算出所在節(jié)點(diǎn)區(qū)間上所有非零基函數(shù);
八、 致謝 Acknowledgments
感謝曉天的支持與鼓勵(lì)。
九、 參考文獻(xiàn) Bibliography
1. 趙罡,穆國(guó)旺,王拉柱譯Les Piegl,Wayne Tiller The NURBS Book(Second Edition) 2010 清華大學(xué)出版社
2. 莫容,常智勇 計(jì)算機(jī)輔助幾何造型技術(shù) 2009 科學(xué)出版社
3. 王仁宏,李崇君,朱春鋼 計(jì)算幾何教程 2008 科學(xué)出版社