OpenCASCADE Linear Extrusion Surface

系统 1850 0

OpenCASCADE Linear Extrusion Surface

eryar@163.com

Abstract. OpenCASCADE linear extrusion surface is a generalized cylinder. Such a surface is obtained by sweeping a curve (called the “extruded curve” or “basis”) in a given direction (referred to as the direction of extrusion and defined by a unit vector). The u parameter is along the extruded curve. The v parameter is along the direction of extrusion. The form of a surface of linear extrusion is generally a ruled surface. It can be a cylindrical surface, or a planar surface.

Key Words. OpenCASCADE, Extrusion Surface, Sweeping

1. Introduction

一般柱面(The General Cylinder)可以由一段或整个圆弧沿一个方向偏移一定的距离得到。如下图所示:

wps_clip_image-3336

Figure 1.1 Extrusion Shapes

当将顶点拉伸时,会生成一条边;当将边拉伸时,会生成面;当将Wire拉伸时,会生成Shell,当将面拉伸时,会生成体。当将曲线沿一个方向拉伸时,会形成一个曲面,如果此方向为直线,则会生成一般柱面。如果此方向是曲线时,会生成如下图所示曲面:

wps_clip_image-9181

Figure 1.2 Swept surface/ loft surface

本文主要介绍将曲线沿直线方向拉伸的算法,即一般柱面生成算法。并将生成的曲面在OpenSceneGraph中进行显示。

2. Cylinder Surface Definition

设 W是一个单位向量,C(u)是定义在节点矢量U上,权值为wi的p次NURBS曲线。我们要得到一般柱面S(u,v)的表达式,S(u,v)是通过将 C(u)沿方向W平行扫描(sweep)距离d得到的。记扫描方向的参数为v, 0<v<1,显然,S(u,v)必须满足以下两个条件:

v 对于固定的u0, S(u0, v)为由C(u0)到C(u0)+dW的直线段;

v 对于固定的v0:

wps_clip_image-23488

所要求的柱面的表达式为:

wps_clip_image-17503

S(u,v)定义在节点矢量U和V上,这里V={0,0,1,1},U为C(u)的节点矢量。控制顶点由Pi,0=Pi和Pi,1=Pi+dW给出,权值wi,0=wi,1=wi。如下图所示为一般柱面:

wps_clip_image-2395

Figure 2.1 A general cylinder obtained by translating C(u) a distance d along W.

其中OpenCASCADE中一般柱面的表达式如下所示:

wps_clip_image-28368

其取值范围的代码如下所示:

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


        
        
          //
        
        
          function : Bounds


        
        
          //
        
        
          purpose  : 


        
        
          //
        
        
          =======================================================================
        
        
          void
        
         Geom_SurfaceOfLinearExtrusion::Bounds ( Standard_Real&
        
           U1, 

                         Standard_Real
        
        &
        
           U2,

                         Standard_Real
        
        &
        
           V1, 

                         Standard_Real
        
        & V2 ) 
        
          const
        
        
           {



  V1 
        
        = -Precision::Infinite();  V2 =
        
           Precision::Infinite();

  U1 
        
        = basisCurve->FirstParameter();  U2 = basisCurve->
        
          LastParameter();

}
        
      

由上代码可知,参数在v方向上是趋于无穷的;在u方向上参数的范围为曲线的范围。计算柱面上点的方法代码如下所示:

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


        
        
          //
        
        
          function : D0


        
        
          //
        
        
          purpose  : 


        
        
          //
        
        
          =======================================================================
        
        
          void
        
         Geom_SurfaceOfLinearExtrusion::D0 (
        
          const
        
        
           Standard_Real U, 

                                        
        
        
          const
        
        
           Standard_Real V, 

                                        Pnt
        
        & P)  
        
          const
        
        
           {

  

  XYZ Pxyz 
        
        =
        
           direction.XYZ();

  Pxyz.Multiply (V);

  Pxyz.Add (basisCurve
        
        ->
        
          Value (U).XYZ());

  P.SetXYZ(Pxyz);      

}
        
      

即将柱面上点先按V方向来计算,再按U方向来计算,最后将两个方向的值相加即得到柱面上的点。

由上述代码可知,OpenCASCADE中一般柱面没有使用NURBS曲面来表示。根据这个方法,可以将任意曲线沿给定的方向来得到一个柱面,这个曲线可以是直线、圆弧、圆、椭圆等。关于柱面上更多算法,如求微分等,可以参考源程序。

3. Display the Surface

还是在OpenSceneGraph中来对一般柱面进行可视化,来验证结果。因为OpenSceneGraph的简单易用,显示曲面的程序代码如下所示:

        
          /*
        
        
          

*    Copyright (c) 2013 to current year. All Rights Reserved.

*

*           File : Main.cpp

*         Author : eryar@163.com

*           Date : 2014-11-23 10:18

*        Version : OpenCASCADE6.8.0

*

*    Description : Test the Linear Extrusion Surface of OpenCASCADE.

*

*      Key Words : OpenCascade, Linear Extrusion Surface, General Cylinder

*                  


        
        
          */
        
        
          //
        
        
           OpenCASCADE.
        
        
          #define
        
         WNT
        
          

#include 
        
        <Precision.hxx>
        
          



#include 
        
        <gp_Circ.hxx>
        
          



#include 
        
        <Geom_SurfaceOfLinearExtrusion.hxx>
        
          



#include 
        
        <GC_MakeCircle.hxx>
        
          

#include 
        
        <GC_MakeSegment.hxx>
        
          

#include 
        
        <GC_MakeArcOfCircle.hxx>




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


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


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


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






        
          //
        
        
           OpenSceneGraph.
        
        

#include <osgViewer/Viewer>
        
          

#include 
        
        <osgViewer/ViewerEventHandlers>
        
          



#include 
        
        <osgGA/StateSetManipulator>




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


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


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




        
          const
        
        
          double
        
         TOLERANCE_EDGE = 1e-
        
          6
        
        
          ;


        
        
          const
        
        
          double
        
         APPROXIMATION_DELTA = 
        
          0.05
        
        
          ;




        
        
          /*
        
        
          *

* @brief Render 3D geometry surface.


        
        
          */
        
        
          

osg::Node
        
        * BuildSurface(
        
          const
        
         Handle_Geom_Surface&
        
           theSurface)

{

    osg::ref_ptr
        
        <osg::Geode> aGeode = 
        
          new
        
        
           osg::Geode();



    Standard_Real aU1 
        
        = 
        
          0.0
        
        
          ;

    Standard_Real aV1 
        
        = 
        
          0.0
        
        
          ;

    Standard_Real aU2 
        
        = 
        
          0.0
        
        
          ;

    Standard_Real aV2 
        
        = 
        
          0.0
        
        
          ;

    Standard_Real aDeltaU 
        
        = 
        
          0.0
        
        
          ;

    Standard_Real aDeltaV 
        
        = 
        
          0.0
        
        
          ;



    theSurface
        
        ->
        
          Bounds(aU1, aU2, aV1, aV2);



    
        
        
          //
        
        
           trim the parametrical space to avoid infinite space.
        
        

    Precision::IsNegativeInfinite(aU1) ? aU1 = -
        
          1.0
        
        
           : aU1;

    Precision::IsInfinite(aU2) 
        
        ? aU2 = 
        
          1.0
        
        
           : aU2;



    Precision::IsNegativeInfinite(aV1) 
        
        ? aV1 = -
        
          1.0
        
        
           : aV1;

    Precision::IsInfinite(aV2) 
        
        ? aV2 = 
        
          1.0
        
        
           : aV2;



    
        
        
          //
        
        
           Approximation in v direction.
        
        

    aDeltaU = (aU2 - aU1) *
        
           APPROXIMATION_DELTA;

    aDeltaV 
        
        = (aV2 - aV1) *
        
           APPROXIMATION_DELTA;



    
        
        
          for
        
         (Standard_Real u = aU1; (u - aU2) <= TOLERANCE_EDGE; u +=
        
           aDeltaU)

    {

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

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



        
        
        
          for
        
         (Standard_Real v = aV1; (v - aV2) <= TOLERANCE_EDGE; v +=
        
           aDeltaV)

        {

            gp_Pnt aPoint 
        
        = theSurface->
        
          Value(u, v);



            aPoints
        
        ->
        
          push_back(osg::Vec3(aPoint.X(), aPoint.Y(), aPoint.Z()));

        }



        
        
        
          //
        
        
           Set vertex array.
        
        

        aLine->
        
          setVertexArray(aPoints);

        aLine
        
        ->addPrimitiveSet(
        
          new
        
         osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 
        
          0
        
        , aPoints->
        
          size()));

        

        aGeode
        
        ->addDrawable(aLine.
        
          get
        
        
          ());

    }



    
        
        
          //
        
        
           Approximation in u direction.
        
        
          for
        
         (Standard_Real v = aV1; (v - aV2) <= TOLERANCE_EDGE; v +=
        
           aDeltaV)

    {

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

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



        
        
        
          for
        
         (Standard_Real u = aU1; (u - aU2) <= TOLERANCE_EDGE; u +=
        
           aDeltaU)

        {

            gp_Pnt aPoint 
        
        = theSurface->
        
          Value(u, v);



            aPoints
        
        ->
        
          push_back(osg::Vec3(aPoint.X(), aPoint.Y(), aPoint.Z()));

        }



        
        
        
          //
        
        
           Set vertex array.
        
        

        aLine->
        
          setVertexArray(aPoints);

        aLine
        
        ->addPrimitiveSet(
        
          new
        
         osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 
        
          0
        
        , aPoints->
        
          size()));

        

        aGeode
        
        ->addDrawable(aLine.
        
          get
        
        
          ());

    }



    
        
        
          return
        
        
           aGeode.release();

}




        
        
          /*
        
        
          *

* @brief Build the test scene.


        
        
          */
        
        
          

osg::Node
        
        * BuildScene(
        
          void
        
        
          )

{

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



    
        
        
          //
        
        
           test the linear extrusion surface.

    
        
        
          //
        
        
           test linear extrusion surface of a line.
        
        

    Handle_Geom_Curve aSegment = GC_MakeSegment(gp_Pnt(
        
          3.0
        
        , 
        
          0.0
        
        , 
        
          0.0
        
        ), gp_Pnt(
        
          6.0
        
        , 
        
          0.0
        
        , 
        
          0.0
        
        
          ));

    Handle_Geom_Surface aPlane 
        
        = 
        
          new
        
        
           Geom_SurfaceOfLinearExtrusion(aSegment, gp::DZ());



    aRoot
        
        ->
        
          addChild(BuildSurface(aPlane));



    
        
        
          //
        
        
           test linear extrusion surface of a arc.
        
        

    Handle_Geom_Curve aArc = GC_MakeArcOfCircle(gp_Circ(gp::ZOX(), 
        
          2.0
        
        ), 
        
          0.0
        
        , M_PI, 
        
          true
        
        
          );

    Handle_Geom_Surface aSurface 
        
        = 
        
          new
        
        
           Geom_SurfaceOfLinearExtrusion(aArc, gp::DY());

    

    aRoot
        
        ->
        
          addChild(BuildSurface(aSurface));



    
        
        
          //
        
        
           test linear extrusion surface of a circle.
        
        

    Handle_Geom_Curve aCircle = GC_MakeCircle(gp::XOY(), 
        
          1.0
        
        
          );

    Handle_Geom_Surface aCylinder 
        
        = 
        
          new
        
        
           Geom_SurfaceOfLinearExtrusion(aCircle, gp::DZ());

    

    aRoot
        
        ->
        
          addChild(BuildSurface(aCylinder));



    
        
        
          return
        
        
           aRoot.release();

}




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

{

    osgViewer::Viewer aViewer;



    aViewer.setSceneData(BuildScene());



    aViewer.addEventHandler(
        
        
          new
        
        
           osgGA::StateSetManipulator(

        aViewer.getCamera()
        
        ->
        
          getOrCreateStateSet()));

    aViewer.addEventHandler(
        
        
          new
        
        
           osgViewer::StatsHandler);

    aViewer.addEventHandler(
        
        
          new
        
        
           osgViewer::WindowSizeHandler);



    
        
        
          return
        
        
           aViewer.run();



    
        
        
          return
        
        
          0
        
        
          ;

}
        
      

上述显示方法只是显示线框的最简单的算法,只为验证一般柱面结果,不是高效算法。显示结果如下图所示:

wps_clip_image-20068

Figure 3.1 General Cylinder for: Circle, Arc, Line

如上图所示分别为对圆、圆弧和直线进行拉伸得到的一般柱面。根据这个原理可以将任意曲线沿给定方向进行拉伸得到一个柱面。

4. Conclusion

通 过对OpenCASCADE中一般柱面的类中代码进行分析可知,OpenCASCADE的这个线性拉伸柱面 Geom_SurfaceOfLinearExtrusion是根据一般柱面的定义实现的,并不是使用NURBS曲面来表示的。当需要用NURBS曲面来 表示一般柱面时,需要注意控制顶点及权值的计算取值。

5. References

1. 赵罡,穆国旺,王拉柱译. 非均匀有理B样条. 清华大学出版社. 2010

2. Les Piegl, Wayne Tiller. The NURBS Book. Springer-Verlag. 1997

3. OpenCASCADE Team, OpenCASCADE BRep Format. 2014

4. Donald Hearn, M. Pauline Baker. Computer Graphics with OpenGL. Prentice Hall. 2009

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

PDF Version and Source Code: OpenCASCADE Linear Extrusion Surface

OpenCASCADE Linear Extrusion Surface


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论