• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            eryar

            PipeCAD - Plant Piping Design Software.
            RvmTranslator - Translate AVEVA RVM to OBJ, glTF, etc.
            posts - 603, comments - 590, trackbacks - 0, articles - 0

            B樣條基函數(shù)——B-Spline Basis Functions

            Posted on 2013-03-27 10:27 eryar 閱讀(16674) 評論(0)  編輯 收藏 引用 所屬分類: 2.OpenCASCADE

            B-Spline Basis Functions

            eryar@163.com

                摘要Abstract:直接根據(jù)B樣條的Cox-deBoor遞推定義寫出計(jì)算B樣條基函數(shù)的程序,并將計(jì)算結(jié)果在OpenSceneGraph中顯示。

               關(guān)鍵字Key Words:B Spline Basis Functions、OpenSceneGraph

            一、概述Overview

            有很多方法可以用來定義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ù),其定義為:

            wps_clip_image-29792

            B樣條基有如下性質(zhì):

            a) 遞推性;

            b) 局部支承性;

            c) 規(guī)范性;

            d) 可微性;

            二、程序 Codes

            直接根據(jù)B樣條基函數(shù)的Cox-deBoor遞推定義,寫出計(jì)算B樣條基函數(shù)的程序如下:

            頭文件BSplineBasisFunction.h:

             

            /*
            *    Copyright (c) 2013 eryar All Rights Reserved.
            *
            *        File    : BSplineBasisFunction.h
            *        Author  : eryar@163.com
            *        Date    : 2013-03-23 22:13
            *        Version : V1.0
            *
            *    Description : Use Cox-deBoor formula to implemente the 
            *                  B-Spline Basis functions.
            *
            */

            #ifndef _BSPLINEBASISFUNCTION_H_
            #define _BSPLINEBASISFUNCTION_H_

            #include 
            <vector>

            class BSplineBasisFunction
            {
            public:
                BSplineBasisFunction(
            const std::vector<double>& U);
                
            ~BSplineBasisFunction(void);

            public:
                
            /*
                * @brief Binary search of the knot vector.
                
            */

                
            int FindSpan(double u);

                
            /*
                * @brief 
                * @param [in] i: span of the parameter u;
                *        [in] p: degree;
                *        [in] u: parameter;
                
            */

                
            double EvalBasis(int i, int p, double u);

                
            /*
                * @breif Get knot vector size.
                
            */

                
            int GetKnotVectorSize(voidconst;

                
            /*
                * @breif Get the knot value of the given index.
                
            */

                
            double GetKnot(int i) const;

            private:
                std::vector
            <double> mKnotVector;
            }
            ;

            #endif // _BSPLINEBASISFUNCTION_H_



            實(shí)現(xiàn)文件BSplineBasisFunction.cpp:

             

            /*
            *    Copyright (c) 2013 eryar All Rights Reserved.
            *
            *        File    : BSplineBasisFunction.cpp
            *        Author  : eryar@163.com
            *        Date    : 2013-03-23 22:14
            *        Version : V1.0
            *
            *    Description : Use Cox-deBoor formula to implemente the 
            *                  B-Spline Basis functions.
            *
            */


            #include 
            "BSplineBasisFunction.h"

            BSplineBasisFunction::BSplineBasisFunction( 
            const std::vector<double>& U )
                :mKnotVector(U)
            {

            }



            BSplineBasisFunction::
            ~BSplineBasisFunction(void)
            {
            }


            int BSplineBasisFunction::GetKnotVectorSize( void ) const
            {
                
            return static_cast<int> (mKnotVector.size());
            }


            double BSplineBasisFunction::GetKnot( int i ) const
            {
                
            return mKnotVector[i];
            }


            /*
            * @brief Binary search of the knot vector.
            */

            int BSplineBasisFunction::FindSpan( double u )
            {
                
            int iSize = static_cast<int> (mKnotVector.size());

                
            if (u >= mKnotVector[iSize-1])
                
            {
                    
            return iSize;
                }


                
            int iLow = 0;
                
            int iHigh = iSize;
                
            int iMiddle = (iLow + iHigh) / 2;

                
            while (u < mKnotVector[iMiddle] || u > mKnotVector[iMiddle+1])
                
            {
                    
            if (u < mKnotVector[iMiddle])
                    
            {
                        iHigh 
            = iMiddle;
                    }

                    
            else
                    
            {
                        iLow 
            = iMiddle;
                    }


                    iMiddle 
            = (iLow + iHigh) / 2;
                }


                
            return iMiddle;
            }


            double BSplineBasisFunction::EvalBasis( int i, int p, double u )
            {
                
            if ((i+p+1>= GetKnotVectorSize())
                
            {
                    
            return 0;
                }


                
            if (0 == p)
                
            {
                    
            if (u >= mKnotVector[i] && u < mKnotVector[i+1])
                    
            {
                        
            return 1;
                    }
             
                    
            else
                    
            {
                        
            return 0;
                    }

                }


                
            double dLeftUpper = u - mKnotVector[i];
                
            double dLeftLower = mKnotVector[i+p] - mKnotVector[i];
                
            double dLeftValue = 0;

                
            double dRightUpper = mKnotVector[i+p+1- u;
                
            double dRightLower = mKnotVector[i+p+1- mKnotVector[i+1];
                
            double dRightValue = 0;

                
            if (dLeftUpper != 0 && dLeftLower != 0)
                
            {
                    dLeftValue 
            = (dLeftUpper / dLeftLower) * EvalBasis(i, p-1, u);
                }


                
            if (dRightUpper != 0 && dRightLower != 0)
                
            {
                    dRightValue 
            = (dRightUpper / dRightLower) * EvalBasis(i+1, p-1, u);
                }


                
            return (dLeftValue + dRightValue);
            }


            主函數(shù):

             

            /*
            *    Copyright (c) 2013 eryar All Rights Reserved.
            *
            *        File    : Main.cpp
            *        Author  : eryar@163.com
            *        Date    : 2013-03-23 22:11
            *        Version : V1.0
            *
            *    Description : Use Cox-deBoor formula to implemente the 
            *                  B-Spline Basis functions.
            *
            */


            #include 
            <osgDB/ReadFile>
            #include 
            <osgViewer/Viewer>
            #include 
            <osgGA/StateSetManipulator>
            #include 
            <osgViewer/ViewerEventHandlers>

            #include 
            "BSplineBasisFunction.h"

            #pragma comment(lib, 
            "osgd.lib")
            #pragma comment(lib, 
            "osgDBd.lib")
            #pragma comment(lib, 
            "osgGAd.lib")
            #pragma comment(lib, 
            "osgViewerd.lib")

            osg::Node
            * MakeBasisFuncLine(BSplineBasisFunction& bf, int i, int p)
            {
                
            // The property basis functions.
                int iLen = bf.GetKnotVectorSize();
                
            int iStep = 800;
                
            double dStart = bf.GetKnot(0);
                
            double dEnd = bf.GetKnot(iLen-1);
                
            double dDelta = (dEnd - dStart) / iStep;
                
            double u = 0;
                
            double v = 0;

                
            // Create the Geode (Geometry Node) to contain all our osg::Geometry objects.
                osg::Geode* geode = new osg::Geode;

                
            // Create Geometry object to store all the vertices and lines primitive.
                osg::ref_ptr<osg::Geometry> linesGeom = new osg::Geometry;

                
            // Set the vertex array to the points geometry object.
                osg::ref_ptr<osg::Vec3Array> pointsVec = new osg::Vec3Array;

                
            for (int s = 0; s <= iStep; s++)
                
            {
                    u 
            = s * dDelta;
                    v 
            = bf.EvalBasis(i, p, u);
                    
            if (v != 0)
                    
            {
                        pointsVec
            ->push_back(osg::Vec3(u, 0, v));
                    }

                }

                linesGeom
            ->setVertexArray(pointsVec);

                
            // Set the colors.
                osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
                colors
            ->push_back(osg::Vec4(1.0f1.0f0.0f0.0f));
                linesGeom
            ->setColorArray(colors.get());
                linesGeom
            ->setColorBinding(osg::Geometry::BIND_OVERALL);

                
            // Set the normal in the same way of color.
                osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
                normals
            ->push_back(osg::Vec3(0.0f-1.0f0.0f));
                linesGeom
            ->setNormalArray(normals.get());
                linesGeom
            ->setNormalBinding(osg::Geometry::BIND_OVERALL);

                
            // Add the points geometry to the geode.
                linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, pointsVec->size()));
                geode
            ->addDrawable(linesGeom.get());

                
            return geode;
            }


            osg::Node
            * CreateScene(void)
            {
                osg::Group
            * root = new osg::Group;

                
            // Knot vector: U={0,0,0,1,2,3,4,4,5,5,5}.
                std::vector<double> knotVector;
                knotVector.push_back(
            0);
                knotVector.push_back(
            0);
                knotVector.push_back(
            0);
                knotVector.push_back(
            1);
                knotVector.push_back(
            2);
                knotVector.push_back(
            3);
                knotVector.push_back(
            4);
                knotVector.push_back(
            4);
                knotVector.push_back(
            5);
                knotVector.push_back(
            5);
                knotVector.push_back(
            5);

                BSplineBasisFunction basisFunc(knotVector);
             
                
            for (int i = 0; i < basisFunc.GetKnotVectorSize(); i++)
                
            {
                    
            // 
                    
            //root->addChild(MakeBasisFuncLine(basisFunc, i, 1));

                    
            // 
                    root->addChild(MakeBasisFuncLine(basisFunc, i, 2));
                }

                
                
            return root;
            }


            int main(int argc, char* argv[])
            {
                osgViewer::Viewer viewer;
                viewer.setSceneData(CreateScene());

                viewer.addEventHandler(
            new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
                viewer.addEventHandler(
            new osgViewer::StatsHandler);
                viewer.addEventHandler(
            new osgViewer::WindowSizeHandler);

                
            return viewer.run();
            }

             

            若想顯示出所有次數(shù)的B樣條基函數(shù),只需要在CreateScene中添加就好了。

            以《The NURBS Book》中的例子2.2,節(jié)點(diǎn)矢量U={0, 0, 0, 1, 2, 3, 4, 4, 5, 5, 5},次數(shù)p=2,分別將程序計(jì)算的一次、二次B樣條基函數(shù)的結(jié)果列出,如下圖所示:

            wps_clip_image-3302

            圖1. 一次B樣條基函數(shù)

            wps_clip_image-6258

            圖2. 二次B樣條基函數(shù)

            本來還想將不同的B樣條基函數(shù)以不同的顏色顯示,試了幾次,都沒有成功。若以不同的顏色顯示,會更直觀。若你有設(shè)置顏色的方法,歡迎告訴我,eryar@163.com。

            三、結(jié)論 Conclusion

            程序計(jì)算結(jié)果與書中吻合,效果還不錯(cuò)。

            理解了B樣條的Cox-deBoor遞推定義之后,可以將程序中的遞歸代碼轉(zhuǎn)換為非遞歸實(shí)現(xiàn),這樣就可以深入理解B樣條基函數(shù)了。

             

            PDF Version and Codes: B-Spline Basis Functions

            …久久精品99久久香蕉国产 | 亚洲伊人久久成综合人影院| 国产精品熟女福利久久AV| 久久e热在这里只有国产中文精品99| 久久精品国产一区二区三区| 久久久久久综合网天天| www性久久久com| 久久久久久噜噜精品免费直播| 久久久久久午夜精品| 97久久超碰国产精品2021| 国产精品永久久久久久久久久| 久久人人爽人人澡人人高潮AV | 精品久久久久久久久久中文字幕 | 久久精品国产亚洲AV久| 久久99精品国产一区二区三区| 久久天天日天天操综合伊人av| 久久久久人妻一区二区三区vr| 久久er国产精品免费观看8| 亚洲精品午夜国产VA久久成人| 亚洲狠狠综合久久| 亚洲精品乱码久久久久久蜜桃图片| 婷婷久久综合九色综合98| 一级女性全黄久久生活片免费 | 欧美久久一级内射wwwwww.| 亚洲综合日韩久久成人AV| 久久国产成人亚洲精品影院| 久久久精品人妻一区二区三区四| 久久久久无码精品国产app| 人妻精品久久久久中文字幕69| 久久影视综合亚洲| 久久精品一区二区三区不卡| 久久人人爽人人爽人人片AV东京热 | 少妇精品久久久一区二区三区| 久久亚洲高清综合| 久久精品国产精品青草| 婷婷久久久亚洲欧洲日产国码AV | 久久精品国产99久久丝袜| 国产精品天天影视久久综合网| 伊人久久五月天| 亚洲精品乱码久久久久久蜜桃| 国产成人精品久久综合|