B-Spline Curve Library in Open Cascade

简介: B-Spline Curve Library in Open Cascade Open Cascade中的B样条曲线库 eryar@163.com 摘要Abstract:简要介绍Open Cascade中的B样条曲线库BSplCLib的使用方法,并且结合源程序来对Open Cascade中的B样条曲线的组成部分如节点矢量、重复度等概念进行介绍,以及通过对计算B样条基函数的算法进行分析,加深对B样条曲线概念的理解。

B-Spline Curve Library in Open Cascade

Open Cascade中的B样条曲线库

eryar@163.com

摘要Abstract:简要介绍Open Cascade中的B样条曲线库BSplCLib的使用方法,并且结合源程序来对Open Cascade中的B样条曲线的组成部分如节点矢量、重复度等概念进行介绍,以及通过对计算B样条基函数的算法进行分析,加深对B样条曲线概念的理解。

关键字Key Word:B Spline Curve、Open Cascade、Knot Vector、Multiplicity

 

一、 概述 Overview

1946年由Schoenberg提出了B样条理论,给出了B样条的差分表达式;1972年de Boor和Cox分别独立给出了关于B样条的标准算法。Gordon和Riesenfeld又把B样条理论用于形状描述,最终提出了B样条方法。用B样条基替代了Bernstein基,构造出B样条曲线,这种方法继承了Bezier方法的一切优点,克服了Bezier方法存在的缺点,较成功地解决了局部控制问题,又轻而易举地在参数连续性基础上解决了连接问题,从而使自由曲线曲面形状的描述问题得到较好解决。

p次B样条曲线的定义为:

wps_clip_image-15140

其中:

l Pi是控制顶点(control point);

l Ni,p(u)是定义在非周期节点矢量上的p次B样条基函数;

有很多方法可以用来定义B样条基函数以及证明它的一些重要性质。例如,可以采用截尾幂函数的差商定义,开花定义,以及由de Boor和Cox等人提出的递推公式等来定义。我们这里采用的是递推定义方法,因为这种方法在计算机实现中是最有效的。

令U={u0,u1,…,um}是一个单调不减的实数序列,即ui<=ui+1,i=0,1,…,m-1。其中,ui称为节点,U称为节点矢量,用Ni,p(u)表示第i个p次B样条基函数,其定义为:

wps_clip_image-10013

B样条基有如下性质:

a) 递推性;

b) 局部支承性;

c) 规范性;

d) 可微性;

根据B样条曲线定义可知,给定控制顶点Pi(control points),曲线次数p(degree)及节点矢量U(knot vectors),B样曲线也就确定。对于有理B样条曲线,还需要参数权重(weights)。

二、 OCC中的B样条曲线库 BSplCLib in OCC

在Open Cascade中的工具箱(Toolkit)TKMath中的包(package)BSplCLib是B样条曲线库,为B样条曲线曲面的计算提供了支持。它提供了三方面的功能:

l 对节点矢量(knot vectors)及重复度(multiplicities)的管理;

l 对多维样条的支持,即B样条方法中控制顶点的维数可以是任意维数(dimension);

l 二维和三维样条曲线的方法;

Open Cascade中的B样条曲线由下列数据项定义:

定义

变量类型

变量名称

控制顶点control points

TColgp_Array1OfPnt

Poles

权重weights

TColStd_Array1OfReal

Weights

节点knots

TColStd_Array1OfReal

Knots

重数multiplicities

TColStd_Array1OfInteger

Mults

次数degree

Standard_Integer

Degree

周期性periodicity

Standard_Boolean

Periodic


B样条曲线库BSplCLib提供了一些基本几何算法:

l B样条基函数及其导数的计算BSplCLib::EvalBsplineBasis();

l 节点插入BSplCLib::InsertKnot();

l 节点去除BSplCLib::RemoveKnot();

l 升阶BSplCLib::IncreaseDegree();

l 降阶;

结合《The NURBS Book》和Open Cascade中的BSplCLib的源程序,可以高效的学习NURBS。《The NURBS Book》中有详细的理论推导及算法描述,而Open Cascade中有可以用来实际使用的程序。理论联系实际,有助于快速理解NURBS的有关概念及其应用。

三、 OCC中B样条曲线库的节点和重数Knots and Multiplicity in BSplCLib

由B样条曲线的可微性可知,节点的重数与B样条曲线的连续性相关。在节点区间内部,Ni,p(u)是无限次可微的,因在每个节点区间内部,它是一个多项式。在节点处Ni,p(u)是p-k次连续的,其中k是节点的重复度(multiplicity,有时也称为重数)。因此,增加次数p将提高曲线的连续性,而增加节点的重复度则使连续性降低。

重复度(multiplicity,有时也称为重数)有两种不同的理解方式:

l 节点在节点矢量中的重复度;

l 节点相对于一个特定的基函数的重复度;

在Open Cascade中对重复度的理解是前者,即节点在节点矢量中的重复度。下面结合源程序来进行说明。

函数BSplCLib::Knots()用来将给定的节点矢量(节点序列knot sequence)转换为节点的重复度不大于1的Knots数组和每个节点对应的重复度Mults数组,且数据Knots和Mults的长度必由函数BSplCLib::KnotsLength()得到。Knots()函数的源程序如下所示:

 

// ======================================================================= 

// function : Knots 

// purpose  : Computes  the  sequence   of knots Knots  without repetition   

//            of the  knots  of multiplicity  greater than 1. 

//            Length  of <Knots> and  <Mults> must be KnotsLength(KnotSequence,Periodic). 

// ======================================================================= 

void  BSplCLib::Knots( const  TColStd_Array1OfReal &  SeqKnots,  

          TColStd_Array1OfReal 
& knots, 

          TColStd_Array1OfInteger 
& mult, 

//          const Standard_Boolean Periodic) 

const  Standard_Boolean ) 

img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif


   Standard_Real val 
= SeqKnots(1); 

   Standard_Integer kk
=1

   knots(kk) 
= val; 

   mult(kk)  
= 1

for (Standard_Integer jj=2;jj<=SeqKnots.Length();jj++

img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif     


// test on strict equality on nodes 

if (SeqKnots(jj)!=val) 

img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif         


           val 
= SeqKnots(jj); 

           kk
++

           knots(kk) 
= val; 

           mult(kk)  
= 1

         }
 

else 

img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif         


           mult(kk)
++

         }
 

     }
 

}
 


从上述代码可知,直接使用了不等于来判断两个节点的值是否相同,而没有采用误差处理,即严格的相等比较。程序将节点重复度不大于1的节点及其相应的重复度分别保存到knots和mult中。

四、 B样条曲线的分类 B Spline Curve Type

B样条曲线一般按定义基函数的节点序列是否等距(均匀)分为均匀B样条曲线(Uniform B-Spline Curve)和非均匀B样条曲线(Non Uniform B-Spline Curve)。

B样条曲线按节点序列中节点分布情况不同,又分为四种类型:均匀B样条曲线、准均匀B样条曲线、分段Bezier曲线、一般非均匀B样条曲线。设给定特征多边形顶点Vi,i=0,1,…,n,曲线次数k,则有:

l 均匀B样条曲线(uniform B-Spline curve):节点序列中节点沿参数轴均匀或等距分布,即所有节点区间长度为大于零的常数(constant):

wps_clip_image-14311

l 准均匀B样曲线(quasi-uniform B-Spline curve):其节点序列中两端节点具有重复度k+1,而所有内节点均匀分布,具有重复度1。

l 分段Bezier曲线(piecewise Bezier curve):其节点序列中两端节点重复度与准均匀B样条曲线的相同,所不同的是所有内节点重复度为k。

l 非均匀B样条曲线(general non-uniform B-Spline curve):这是对任意分布的节点序列,只要在数学上成立,即节点序列非递减,都可取。

在基础类模块(Module FoundationClasses)的工具箱(Toolkit TKMath)中的包(GeomAbs)中有对B样样条曲线类型的定义,源程序如下所示:

 

// !  This enumeration is used to note specific curve form. <br> 

enum  GeomAbs_BSplKnotDistribution { 

GeomAbs_NonUniform, 

GeomAbs_Uniform, 

GeomAbs_QuasiUniform, 

GeomAbs_PiecewiseBezier 

}; 

 

而类BSplCLib主要是用来管理节点和重复度的,所有将节点和重复度也进行了分类。根据节点矢量是否均匀分布,将节点分配方式(Knot Distribution)分为:均匀(BSplCLib_Uniform)和非均匀(BSplCLib_NonUniform)。源程序如下所示:

 

enum  BSplCLib_KnotDistribution { 

BSplCLib_NonUniform, 

BSplCLib_Uniform 

}; 

 

根据重复度数组将重复度的分配方式分为如下三种类型:

n BSplCLib_Constant:重复度都相同;

n BSplCLib_QuasiConstant:首、尾节点的重复度与内部节点的重复度不同;

n BSplClib_NonConstant:其它情况;

源程序如下所示:

 

enum  BSplCLib_MultDistribution { 

BSplCLib_NonConstant, 

BSplCLib_Constant, 

BSplCLib_QuasiConstant 

}; 

 

判断节点矢量和重复度矢量类型分别由下列函数实现:

l BSplCLib::KnotForm();

l BSplCLib::MultForm();

具体的判断方法可以查看源程序。

将节点分布方式与重复度的分布方式进行组合,可以得出B样条曲线的那几种类型。

五、 B样条基函数的计算 Evaluate the B-Spline Basis

B样条基函数的计算主要使用了B样条基了函数的递推公式(Cox-deBoor公式)的局部支撑性质,如下所示:

wps_clip_image-21079

直接由定义可知:

l Ni,0(u)是一个阶梯函数,它在半开区间u∈[ui, ui+1)外都为零;

l 当次数p>0时,Ni,p(u)是两个p-1次基函数的线性组合;

l 计算一组基函数需要事先指定节点矢量U和次数p;

l 半开区间[ui,ui+1)称为第i个节点区间(knot span),它的长度可以为零,因为相邻节点可以是相同的;

l 计算p次基函数的过程可以生成一个如下形式的三角形陈列:

wps_clip_image-31692

B样条有局部支撑性,即若u不在区间[ui, ui+p+1),则Ni,p(u)=0。可从下面的三角形中看出N1,3是N1,0、N2,0、N3,0和N4,0的线性组合,而N1,0在区间[u1, u2)上非零,N2,0在区间[u2,u3)上非零,N3,0在区间[u3,u4)上非零,N4,0在区间[u4,u5)上非零,所以N1,3仅在区间[u1,u5)上非零。

在任意给定的节点区间[uj,uj+1)内,最多有p+1个是非零的,它们是Nj-p,p、Nj-p+1、…、Nj,p。例如,在[u3,u4)上,零次基函数中只有N3,0是非零的,一次基函数只有N2,1和N3,1是非零的,非零的三次基函数只有N0,3、N1,3、N2,3、N3,3。这个性质如下图所示:

wps_clip_image-14220 wps_clip_image-13472

上面两幅图中右边的图中所示的推算过程表明,给定节点序列U及B样条曲线的次数p,给出任意一个u值,找出其所在的节点区间[ui,ui+1)上,最多有Ni-p,p,Ni-p+1,p,…,Ni,p个非零的基函数。

例如我们根据递推公式写出二次基函数的一般形式,如下所示:

wps_clip_image-25174

当给定的u值在区间[u3,u4)上即(i=3)时,根据上面的三角形,得出下列重要结论:

wps_clip_image-2192

即这两项不需要计算。另外一个重要结论就是图中用相同颜色框中的部分是相同的,也就是下面程序中的变量temp表示的内容。

我们引入下面符号:

wps_clip_image-27970

由二次基函数推出的三个公式可写为:

wps_clip_image-18620

上述推导过程为《The NURBS Book》中的算法,算法代码如下所示:

wps_clip_image-10895

理解了变量temp的意义之后,整个程序就很好理解了。

将Open Cascade中计算基函数的算法是不同的,将其源程序摘抄如下所示:

 

// ======================================================================= 

// 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) ; 




函数的作用是用来计算所有的基函数及其导数,并将结果以矩阵(数组)的形式保存。结合二次基函数的推导方法,将述代码写成公式的形式。函数的参数及其描述如下表所示:

变量

描述

DerivativeRequest

导数的次数

Order

B样条基函数的阶数(次数+1)

FlatKnots

节点矢量

Parameter

参数

FirstNonZeroBspline

第一个非零基函数的索引值

BsplineBasis

基函数值矩阵


当导数次数DerivativeRequest大于B样条基的阶数Order时,将计算导数的次数设置为B样条基的次数(Order-1)。程序代码如下所示:

 

  LocalRequest  =  DerivativeRequest ; 

if  (DerivativeRequest  >=  Order) { 

    LocalRequest 
=  Order  -   1  ; 


 

对B样条基数计算结果矩阵BsplineBasis存储空间进行检查。若存储空间不足,则会退出,程序代码如下所示:

 

if  (BsplineBasis.LowerCol()  !=   1   ||  

      BsplineBasis.UpperCol() 
<  Order  ||  

      BsplineBasis.LowerRow() 
!=   1   ||  

      BsplineBasis.UpperRow() 
<=  LocalRequest) { 

    ReturnCode 
=   1

goto  FINISH ; 


 

确定参数Parameter所在的节点区间的下标(索引值),程序代码如下所示:

 

NumPoles  =  FlatKnots.Upper()  -  FlatKnots.Lower()  +   1   -  Order ; 

  BSplCLib::LocateParameter(Order 
-   1

    FlatKnots, 

    Parameter, 

    Standard_False, 

    Order, 

    NumPoles
+ 1

    ii, 

                NewParameter) ; 


确定参数Parameter所在区间的算法是用二分法搜索得到。程序代码如下所示:

 

// ======================================================================= 

// 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; 






确定参数所在区间[ui,ui+1)后,可得到第一个非零基函数的索引值为i-p;

  FirstNonZeroBsplineIndex = ii - Order + 1 ;

基函数计算的主要算法代码如下所示:

 

BsplineBasis( 1 , 1 =   1.0e0  ; 

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 ; 






其中:

wps_clip_image-13697为节点区间[ui,ui+1)上的基函数左边部分的系数;

wps_clip_image-7128为节点区间[ui-1,ui)上的基函数右边部分的系数;

 

六、 程序示例 Sample Codes

将上述内容以一个简单示例程序来验证,程序代码如下所示:

 

/*  

*    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




上述代码对节点矢量、重复度的概念的验证,并以一个实例计算所有非零基函数的值。程序输出为:

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 . . .

 

七、 结论 Conclusion

通过学习《The NURBS Book》并给合Open Cascade的源程序,理论联系实际,使对NURBS的学习更轻松。

根据B样条基的递推公式,B样条曲线的局部性是通过节点来具体实现的。与Bezier曲线不同的就是增加了节点这个参数。根据Cox-deBoor递推公式亲自推导出一次、二次、三次B样条基函数,可以加深对B样条曲线的理解。

计算给定节点矢量、次数及参数,计算参数所在区间上所有非零基函数算法的步骤为:

l 通过二分法查找出参数所在的节点区间;

l 根据B样条基的局部支撑性,计算出所在节点区间上所有非零基函数;

 

八、 致谢 Acknowledgments

感谢晓天的支持与鼓励。

 

九、 参考文献 Bibliography

1. 赵罡,穆国旺,王拉柱译Les Piegl,Wayne Tiller The NURBS Book(Second Edition) 2010 清华大学出版社

2. 莫容,常智勇 计算机辅助几何造型技术 2009 科学出版社

3. 王仁宏,李崇君,朱春钢 计算几何教程 2008 科学出版社

 

目录
相关文章
|
数据可视化 Linux Python
成功解决RuntimeError: Selected KDE bandwidth is 0. Cannot estiamte density
成功解决RuntimeError: Selected KDE bandwidth is 0. Cannot estiamte density
Open CASCADE之拟合Smooth curve
Open CASCADE之拟合Smooth curve
823 0
Open CASCADE之拟合Smooth curve
成功解决coordinate_descent.py:491: ConvergenceWarning: Objective did not converge. You might want to inc
成功解决coordinate_descent.py:491: ConvergenceWarning: Objective did not converge. You might want to inc
|
算法
Convert BSpline Curve to Arc Spline in OpenCASCADE
Convert BSpline Curve to Arc Spline in OpenCASCADE eryar@163.com Abstract. The paper based on OpenCASCADE algorithms to approximate the NURBS curve to arc spline.
1531 0
|
人工智能 图形学
OpenCASCADE Shape Location
OpenCASCADE Shape Location eryar@163.com Abstract. The TopLoc package of OpenCASCADE gives resources to handle 3D local coordinate systems called Locations.
1610 0
|
算法
OPEN CASCADE Gauss Least Square
OPEN CASCADE Gauss Least Square eryar@163.com Abstract. The least square can be used to solve a set of n linear equations of m unknowns(n >= m).
1176 0
|
图形学 UED
OPEN CASCADE Curve Continuity
OPEN CASCADE Curve Continuity eryar@163.com Abstract. 设计一条复杂曲线时,出于设计和制造上的考虑,常常通过多段曲线组合而成,这就需要解决曲线段之间如何实现光滑连接的问题。
1375 0
|
索引
OPEN CASCADE BSpline Curve Interpolation
OPEN CASCADE BSpline Curve Interpolation eryar@163.com Abstract. Global curve interpolation to point data is a way to construct curves.
1610 0
|
C++ Java Spring
Make Helix Curve in OpenCASCADE
Make Helix Curve in OpenCASCADE eryar@163.com Abstract. OpenCASCADE does not provide helix curve directly, but you can build a helix curve by the pcurve of a surface(curve on surface).
1616 0