亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Polynomial Library in OpenCascade

系統(tǒng) 2230 0

Polynomial Library in OpenCascade

eryar@163.com

摘要Abstract:分析冪基曲線即多項(xiàng)式曲線在OpenCascade中的計(jì)算方法,以及利用OpenSceneGraph來(lái)顯示OpenCascade的計(jì)算結(jié)果,加深對(duì)多項(xiàng)式曲線的理解。?

關(guān)鍵字Key Words:OpenCascade、PLib、OpenSceneGraph、Polynomial Library?

??

一、 概述 Overview

CAGD(Computer Aided Geometry Design)中,基表示的參數(shù)矢函數(shù)形式已經(jīng)成為形狀數(shù)學(xué)描述的標(biāo)準(zhǔn)形式。人們首先注意到在各類函數(shù)中,多項(xiàng)式函數(shù)(Polynomial Function)能較好地滿足要求。它表示形式簡(jiǎn)單,又無(wú)窮次可微,且容易計(jì)算函數(shù)值及各階導(dǎo)數(shù)值。采用多項(xiàng)式函數(shù)作為基函數(shù)即多項(xiàng)式基,相應(yīng)可以得到參數(shù)多項(xiàng)式曲線曲面。?

人們很早就注意到這樣一個(gè)問(wèn)題:設(shè)f(x)∈C[a,b],對(duì)于任意給的ε>0,是否存在這樣的多項(xiàng)式p(x),使得?

wps_clip_image-32310

對(duì)一切a≤x≤b一致成立??

1885年,Weierstrass證明了p(x)的存在性;?

1912年,Bernstein將滿足條件的多項(xiàng)式構(gòu)造出來(lái)。?

Weierstrass定理:設(shè)f(x)∈C[a,b],那么對(duì)于任意給的ε>0,都存在這樣的多項(xiàng)式p(x),使得?

wps_clip_image-7708

Weierstrass定理說(shuō)明,[a,b]上的任何連續(xù)函數(shù)都可以用多項(xiàng)式來(lái)一致逼近。該定理實(shí)際上正好解決了利用多項(xiàng)式組成的函數(shù)來(lái)表示連續(xù)函數(shù)的問(wèn)題。?

冪(又稱單項(xiàng)式monomial)基uj(j=0,1,,,n)是最簡(jiǎn)單的多項(xiàng)式基。相應(yīng)多項(xiàng)式的全體構(gòu)成n次多項(xiàng)式空間。n次多項(xiàng)式空間中任一組n+1個(gè)線性無(wú)關(guān)的多項(xiàng)式都可以作為一組基,因此就有無(wú)窮多組基。不同組基之間僅僅相差一個(gè)線性變換。?

如果允許坐標(biāo)函數(shù)x(u),y(u),z(u)是任意的,則可以得到范圍很廣的曲線。但是在實(shí)際開發(fā)一個(gè)幾何造型系統(tǒng)時(shí),我們需要一些折中,理想的情況是將坐標(biāo)函數(shù)限制在滿足下述條件的一類函數(shù)中:?

l 能夠精確地表示用戶需要的所有曲線;?

l 在計(jì)算機(jī)中能夠被方便、高效、精確地處理,特別是可以高效地計(jì)算曲線上的點(diǎn)及各階導(dǎo)矢;函數(shù)的數(shù)值計(jì)算對(duì)浮點(diǎn)數(shù)舍入誤差不敏感;函數(shù)所需要的存儲(chǔ)量較小;?

l 比較簡(jiǎn)單,在數(shù)學(xué)上易于理解。?

一類被廣泛使用的函數(shù)就是多項(xiàng)式。盡管它們滿足上標(biāo)準(zhǔn)中的后兩項(xiàng),但有很多類型的重要曲線(及曲面)不能用多項(xiàng)式精確表示,在系統(tǒng)中,這些曲線只能用多項(xiàng)式逼近。同一參數(shù)多項(xiàng)式曲線可以采用不同的基表示,如冪基表示和Bezier表示,由些決定了它們具有不同的性質(zhì),因而就有不同的優(yōu)點(diǎn)。?

?

二、 冪基曲線的計(jì)算 Calculate Polynomial Function

一條n次曲線的冪基表示形式是:?

wps_clip_image-11805 ,其中 wps_clip_image-19121 是矢量。?

給定u0,計(jì)算冪基曲線上的點(diǎn)C(u0)的最有效算法是英國(guó)數(shù)學(xué)家W.G.Horner提出的Horner方法。Horner算法是遞歸概念的一個(gè)典型實(shí)例,它采用最少的乘法來(lái)進(jìn)行多項(xiàng)式求值,使計(jì)算由X^n問(wèn)題轉(zhuǎn)化為O(n)的問(wèn)題。?

l 當(dāng)次數(shù)=1時(shí): wps_clip_image-31777

l 當(dāng)次數(shù)=2時(shí): wps_clip_image-19321

l ……?

l 當(dāng)次數(shù)=n時(shí): wps_clip_image-1762

用數(shù)組來(lái)直接計(jì)算:

      
        void
      
      
         Horner1(a, n, u0, C)

{

    C 
      
      =
      
         a[n];

    
      
      
        for
      
       (
      
        int
      
       i = n-
      
        1
      
      ; i >= 
      
        0
      
      ; i--
      
        )

    {

        C 
      
      = C * u0 +
      
         a[i];

    }

}
      
    

?在OpenSceneGraph中來(lái)計(jì)算:??

      
        void
      
       Horner(osg::Vec3Array* a, 
      
        double
      
       u, osg::Vec3&
      
         p)

{

    
      
      
        int
      
       n = a->size() - 
      
        1
      
      
        ;

    p 
      
      = a->
      
        at(n);



    
      
      
        for
      
       (
      
        int
      
       i = n-
      
        1
      
      ; i >= 
      
        0
      
      ; i--
      
        )

    {

        p 
      
      = p * u + a->
      
        at(i);

    }

}
      
    

?

三、 冪基曲線的顯示 Render Power Basis Curve

利用Horner方法可以計(jì)算[0,1]區(qū)間上相應(yīng)曲線上的點(diǎn),將這些點(diǎn)連成線就構(gòu)成了冪基曲線的近似表示。在OpenSceneGraph中顯示冪基曲線程序如下所示:?

      #include <osg/Vec3>
      
        

#include 
      
      <osg/Array>
      
        

#include 
      
      <osg/Geode>
      
        

#include 
      
      <osg/Group>
      
        

#include 
      
      <osgGA/StateSetManipulator>
      
        

#include 
      
      <osgViewer/Viewer>
      
        

#include 
      
      <osgViewer/ViewerEventHandlers>




      
        #pragma
      
       comment(lib, "osgd.lib")


      
        #pragma
      
       comment(lib, "osgGAd.lib")


      
        #pragma
      
       comment(lib, "osgViewerd.lib")




      
        /*
      
      
        

* @breif Compute point on power basis curve.

* @param [in] a: 

* @param [in] x: 

* @return: Point on power basis curve.


      
      
        */
      
      
        void
      
       Horner(osg::Vec3Array* a, 
      
        double
      
       u, osg::Vec3&
      
         p)

{

    
      
      
        int
      
       n = a->size() - 
      
        1
      
      
        ;



    
      
      
        if
      
       (-
      
        1
      
       ==
      
         n)

    {

        
      
      
        return
      
      
         ;

    }

    

    p 
      
      = a->
      
        at(n);



    
      
      
        for
      
       (
      
        int
      
       i = n-
      
        1
      
      ; i >= 
      
        0
      
      ; i--
      
        )

    {

        p 
      
      = p * u + a->
      
        at(i);

    }

}



osg::Node
      
      *
      
         RenderPowerBasisCurve()

{

    
      
      
        const
      
      
        int
      
       nStep = 
      
        100
      
      
        ;

    osg::Geode
      
      * curveNode = 
      
        new
      
      
         osg::Geode();

    osg::ref_ptr
      
      <osg::Geometry> curveGeom = 
      
        new
      
      
         osg::Geometry();

    osg::ref_ptr
      
      <osg::Vec3Array> curvePnts = 
      
        new
      
      
         osg::Vec3Array();



    
      
      
        //
      
      
         Test to compuate point on power basis curve.
      
      

    osg::ref_ptr<osg::Vec3Array> ctrlPnts = 
      
        new
      
      
         osg::Vec3Array;

    ctrlPnts
      
      ->push_back(osg::Vec3(
      
        0
      
      , 
      
        0
      
      , 
      
        6
      
      
        ));

    ctrlPnts
      
      ->push_back(osg::Vec3(
      
        3
      
      , 
      
        0
      
      , 
      
        6
      
      
        ));

    ctrlPnts
      
      ->push_back(osg::Vec3(
      
        6
      
      , 
      
        0
      
      , 
      
        3
      
      
        ));

    ctrlPnts
      
      ->push_back(osg::Vec3(
      
        6
      
      , 
      
        0
      
      , 
      
        0
      
      
        ));



    
      
      
        for
      
       (
      
        int
      
       i = 
      
        0
      
      ; i < nStep; i++
      
        )

    {

        osg::Vec3 pnt;

        Horner(ctrlPnts, i 
      
      * 
      
        1.0
      
       /
      
         nStep, pnt);



        curvePnts
      
      ->
      
        push_back(pnt);

    }



    curveGeom
      
      ->
      
        setVertexArray(curvePnts);

    curveGeom
      
      ->addPrimitiveSet(
      
        new
      
       osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 
      
        0
      
      , curvePnts->
      
        size()));



    curveNode
      
      ->
      
        addDrawable(curveGeom);



    
      
      
        return
      
      
         curveNode;

}




      
      
        int
      
       main(
      
        int
      
       argc, 
      
        char
      
      *
      
         argv[])

{

    osgViewer::Viewer myViewer;

    osg::ref_ptr
      
      <osg::Group> root = 
      
        new
      
      
         osg::Group();



    root
      
      ->
      
        addChild(RenderPowerBasisCurve());



    myViewer.setSceneData(root);



    myViewer.addEventHandler(
      
      
        new
      
       osgGA::StateSetManipulator(myViewer.getCamera()->
      
        getOrCreateStateSet()));

    myViewer.addEventHandler(
      
      
        new
      
      
         osgViewer::StatsHandler);

    myViewer.addEventHandler(
      
      
        new
      
      
         osgViewer::WindowSizeHandler);



    
      
      
        return
      
      
         myViewer.run();

}
      
    

設(shè)置不同的控制點(diǎn)ctrlPnts,就得到不同的曲線。?

當(dāng)n=1時(shí),有兩個(gè)控制點(diǎn)a0, a1,表示由a0到a0+a1的直線段,如圖3.1所示:?

wps_clip_image-6916

Figure 3.1 連接兩點(diǎn)(0,0,6)到(3,0,6)的直線?

當(dāng)n=2時(shí),曲線是一段由a0到a0+a1+a2的拋物線弧,如圖3.2所示:?

wps_clip_image-887

Figure 3.2 拋物線弧(0,0,6)(3,0,6)(6,0,3)?

??

四、 occ中的多項(xiàng)式計(jì)算庫(kù)The PLib in OCC

在OpenCascade中的基礎(chǔ)模塊(FoundationClasses)的數(shù)學(xué)計(jì)算工具箱(TKMath Toolkit)中有個(gè)PLib包,用以對(duì)多項(xiàng)式進(jìn)行基本的計(jì)算。PLib庫(kù)中的函數(shù)都是靜態(tài)函數(shù),所以都是類函數(shù),可以用類名加函數(shù)名直接調(diào)用。?

PLib可對(duì)多項(xiàng)式進(jìn)行如下計(jì)算:?

l 計(jì)算多項(xiàng)式的值:EvalPolynomial;?

l 計(jì)算Lagrange插值:EvalLagrange;?

l 計(jì)算Hermite插值:EvalCubicHermite;?

其中計(jì)算多項(xiàng)式值的方法也是用的Horner方法。?

包PLib中提供了計(jì)算幾何的數(shù)學(xué)基礎(chǔ)中多項(xiàng)式插值中大部分插值計(jì)算。結(jié)合書籍《計(jì)算幾何教程》科學(xué)出版社中第一章的理論內(nèi)容及OpenCascade的源程序,可以方便計(jì)算幾何的數(shù)學(xué)基礎(chǔ)知識(shí)的學(xué)習(xí)。?

??

五、 使用PLib Apply PLib Class

因?yàn)榘黀Lib中的類PLib都是靜態(tài)函數(shù),所以函數(shù)傳入的參數(shù)比較多,若要使用這些計(jì)算函數(shù),需要對(duì)其函數(shù)參數(shù)進(jìn)行了解。為了對(duì)不同維數(shù)多項(xiàng)式進(jìn)行計(jì)算,類PLib中把空間點(diǎn)轉(zhuǎn)換成了實(shí)數(shù)數(shù)組,并提供了相互轉(zhuǎn)換的函數(shù)。以計(jì)算多項(xiàng)式值為例,來(lái)說(shuō)明使用PLib的方法。程序代碼如下所示:?

      osg::Node* TestPLib(
      
        void
      
      
        )

{

    
      
      
        const
      
      
        int
      
       nStep = 
      
        100
      
      
        ;

    osg::Geode
      
      * curveNode = 
      
        new
      
      
         osg::Geode();

    osg::ref_ptr
      
      <osg::Geometry> curveGeom = 
      
        new
      
      
         osg::Geometry();

    osg::ref_ptr
      
      <osg::Vec3Array> curvePnts = 
      
        new
      
      
         osg::Vec3Array();



    TColgp_Array1OfPnt poles(
      
      
        1
      
      , 
      
        3
      
      
        );

    TColStd_Array1OfReal fp(
      
      
        1
      
      , poles.Length() * 
      
        3
      
      
        );

    TColStd_Array1OfReal points(
      
      
        0
      
      , 
      
        1
      
      , 
      
        3
      
      
        );



    Standard_Real
      
      * polynomialCoeff = (Standard_Real*) &
      
        (fp(fp.Lower()));

    Standard_Real
      
      * result = (Standard_Real*)&
      
        (points(points.Lower()));



    poles.SetValue(
      
      
        1
      
      , gp_Pnt(
      
        0
      
      , 
      
        0
      
      , 
      
        6
      
      
        ));

    poles.SetValue(
      
      
        2
      
      , gp_Pnt(
      
        3
      
      , 
      
        0
      
      , 
      
        6
      
      
        ));

    poles.SetValue(
      
      
        3
      
      , gp_Pnt(
      
        6
      
      , 
      
        0
      
      , 
      
        3
      
      
        ));



    
      
      
        //
      
      
         Change poles to flat array.
      
      
            PLib::SetPoles(poles, fp);



    
      
      
        //
      
      
         Three control point, so degree is 3-1=2.
      
      

    Standard_Integer nDegree = 
      
        3
      
       - 
      
        1
      
      
        ;



    
      
      
        //
      
      
         Because point are 3 Dimension.
      
      

    Standard_Integer nDimension = 
      
        3
      
      
        ;



    
      
      
        for
      
       (
      
        int
      
       i = 
      
        0
      
      ; i < nStep; i++
      
        )

    {

        PLib::NoDerivativeEvalPolynomial(

        i 
      
      * 
      
        1.0
      
       /
      
         nStep, 

        nDegree, 

        nDimension,

        nDegree 
      
      *
      
         nDimension,

        polynomialCoeff[
      
      
        0
      
      
        ], 

        result[
      
      
        0
      
      
        ]);



        
      
      
        //
      
       

        curvePnts->push_back(osg::Vec3(result[
      
        0
      
      ], result[
      
        1
      
      ], result[
      
        2
      
      
        ]));

    }



    curveGeom
      
      ->
      
        setVertexArray(curvePnts);

    curveGeom
      
      ->addPrimitiveSet(
      
        new
      
       osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 
      
        0
      
      , curvePnts->
      
        size()));



    curveNode
      
      ->
      
        addDrawable(curveGeom);



    
      
      
        return
      
      
         curveNode;

}
      
    

函數(shù)PLib::SetPoles可以將空間坐標(biāo)點(diǎn)轉(zhuǎn)換為實(shí)數(shù)數(shù)組。在調(diào)用無(wú)微分計(jì)算多項(xiàng)式的函數(shù)時(shí),將坐標(biāo)點(diǎn)的實(shí)數(shù)數(shù)組的首地址作為參數(shù)之一傳入。?

為了與前面的Horner方法計(jì)算多項(xiàng)式的結(jié)果進(jìn)行對(duì)比,將OpenCascade對(duì)相同點(diǎn)計(jì)算的結(jié)果也顯示出來(lái)。如下圖5.1所示:?

wps_clip_image-13254

Figure 5.1 PLib compute result VS. Previous Horner method?

由上圖可知,PLib的計(jì)算結(jié)果與前面的Horner方法計(jì)算結(jié)果相同。查看OpenCascade的源程序,得其多項(xiàng)式計(jì)算方法也是采用的Horner方法。?

      
        void
      
        PLib::NoDerivativeEvalPolynomial(
      
        const
      
      
         Standard_Real    Par,

                       
      
      
        const
      
      
         Standard_Integer Degree,

                       
      
      
        const
      
      
         Standard_Integer Dimension, 

                       
      
      
        const
      
      
         Standard_Integer DegreeDimension, 

                       Standard_Real
      
      &
      
                 PolynomialCoeff,

                       Standard_Real
      
      &
      
                 Results)

{

  Standard_Integer jj;

  Standard_Real 
      
      *RA = &
      
        Results ;  

  Standard_Real 
      
      *PA = &
      
        PolynomialCoeff ;

  Standard_Real 
      
      *tmpRA =
      
         RA;

  Standard_Real 
      
      *tmpPA = PA +
      
         DegreeDimension;



  
      
      
        switch
      
      
         (Dimension) {

  

  
      
      
        case
      
      
        1
      
      
         : {

    
      
      *tmpRA = *
      
        tmpPA;

    

    
      
      
        for
      
       (jj = Degree  ; jj >  
      
        0
      
       ; jj--
      
        ) {

      tmpPA
      
      --
      
        ;



      
      
      *tmpRA = Par * (*tmpRA) + (*
      
        tmpPA);

    }

    
      
      
        break
      
      
        ;

  }

}
      
    

從上述計(jì)算一維多項(xiàng)式的代碼可以看出,計(jì)算方法與前面的Horner方法相同。?

??

六、 結(jié)論?

學(xué)習(xí)使用Horner方法來(lái)計(jì)算多項(xiàng)式的值,并將計(jì)算結(jié)果在OpenSceneGraph中顯示。通過(guò)使用OpenCascade的多項(xiàng)式庫(kù)PLib來(lái)計(jì)算多項(xiàng)式的值,并結(jié)合其源程序來(lái)理解如何使用庫(kù)PLib。庫(kù)PLib為了統(tǒng)一多項(xiàng)式的計(jì)算,將空間點(diǎn)都轉(zhuǎn)換成數(shù)組后再進(jìn)行計(jì)算,在這其中大量使用了指針,代碼可讀性也不是很好,需要仔細(xì)、耐心。?

??

七、 參考資料?

1. 王仁宏、李崇君、朱春鋼 計(jì)算幾何教程 科學(xué)出版社 2008.6?

2. 趙罡、穆國(guó)旺、王拉柱 非均勻有理B樣條《The NURBS Book》 清華大學(xué)出版社 2010.12?

3.? OpenCascade source code?

?

PDF Version and Source Code: Polynomial Library in OpenCascade

Polynomial Library in OpenCascade


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 五月婷婷六月综合 | 视频二区 素人 欧美 日韩 | 99在线精品免费视频 | 欧美视频免费在线播放 | 亚欧精品一区二区三区四区 | 奇米色偷偷 | 超乳w真性中出し冲田杏梨101 | 日日干日日草 | 成熟热自由日本语亚洲人 | 九九99re在线视频精品免费 | 福利国产 | 国产99久久九九精品免费 | 久久综合一区 | 欧美特级毛片aaaa | 幸福宝色多多 | 欧美毛片基地 | 天天射日日 | 国产精品色图 | 久久精品国产99久久 | 亚洲天天做日日做天天欢毛片 | 精品国产日韩一区三区 | 91精品国产麻豆国产自产在线 | jizz免费在线观看 | 久久精品a一国产成人免费网站 | 国产午夜亚洲精品久久www | 毛片电 | 亚洲小色网 | 羞羞网站在线免费观看 | 欧美大狠狠大臿蕉香蕉大视频 | 久久精品伊人波多野结 | 国产日韩美国成人 | 爱爱网站在线观看免费 | 久久女同互慰一区二区三区 | 九九影院理论片在线观看 | 伊人色婷婷综在合线亚洲 | 尹人香蕉久久99天天拍欧美p7 | 亚洲精品综合一区二区三区 | 图片专区亚洲欧美另类 | 欧美精品香蕉在线观看网 | 四虎国产一区 | 成人影院免费在线观看 |