• <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樣條基函數——B-Spline Basis Functions

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

            B-Spline Basis Functions

            eryar@163.com

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

               關鍵字Key Words:B Spline Basis Functions、OpenSceneGraph

            一、概述Overview

            有很多方法可以用來定義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-29792

            B樣條基有如下性質:

            a) 遞推性;

            b) 局部支承性;

            c) 規范性;

            d) 可微性;

            二、程序 Codes

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

            頭文件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_



            實現文件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);
            }


            主函數:

             

            /*
            *    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();
            }

             

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

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

            wps_clip_image-3302

            圖1. 一次B樣條基函數

            wps_clip_image-6258

            圖2. 二次B樣條基函數

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

            三、結論 Conclusion

            程序計算結果與書中吻合,效果還不錯。

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

             

            PDF Version and Codes: B-Spline Basis Functions

            亚洲人成无码网站久久99热国产| 久久久久国产一区二区| Xx性欧美肥妇精品久久久久久 | 狠狠色婷婷久久综合频道日韩| Xx性欧美肥妇精品久久久久久| 国内精品久久久久久久涩爱| 久久国产成人午夜aⅴ影院| 欧美与黑人午夜性猛交久久久| 久久无码专区国产精品发布| 精品免费久久久久久久| 久久综合丁香激情久久| 久久精品国产亚洲AV蜜臀色欲| 久久婷婷久久一区二区三区| 国产成人精品久久亚洲| 无码日韩人妻精品久久蜜桃 | 国产精品美女久久久m| 欧美与黑人午夜性猛交久久久| 久久久久人妻一区二区三区vr| 香蕉久久一区二区不卡无毒影院| 亚洲欧美久久久久9999| 国产麻豆精品久久一二三| 欧洲性大片xxxxx久久久| 久久这里只精品国产99热| 精品国产乱码久久久久软件| 久久人妻少妇嫩草AV无码蜜桃| 国产AV影片久久久久久| 国产精品久久久久久久久鸭| 亚洲国产精品无码久久久秋霞2| 精品久久久久久无码人妻蜜桃| 久久久久无码精品国产不卡| 精品伊人久久久| 一本久道久久综合狠狠躁AV| 久久久不卡国产精品一区二区| 丁香狠狠色婷婷久久综合| 久久夜色精品国产噜噜亚洲AV| 一本色综合久久| 亚洲国产成人乱码精品女人久久久不卡| 99久久人妻无码精品系列| 奇米影视7777久久精品| 久久久久人妻一区精品性色av| 看久久久久久a级毛片|