在OpenSceneGraph中绘制OpenCascade的曲面

在OpenSceneGraph中绘制OpenCascade的曲面

Draw OpenCascade Geometry Surfaces in OpenSceneGraph

[email protected]

摘要Abstract:本文对OpenCascade中的几何曲面数据进行简要说明,并结合OpenSceneGraph将这些曲面显示。

关键字Key Words:OpenCascade、OpenSceneGraph、Geometry Surface、NURBS

一、引言 Introduction

《BRep Format Description White Paper》中对OpenCascade的几何数据结构进行了详细说明。BRep文件中用到的曲面总共有11种:

1.Plane 平面;

2.Cylinder 圆柱面;

3.Cone 圆锥面;

4.Sphere 球面;

5.Torus 圆环面;

6.Linear Extrusion 线性拉伸面;

7.Revolution Surface 旋转曲面;

8.Bezier Surface 贝塞尔面;

9.B-Spline Surface B样条曲面;

10.Rectangle Trim Surface 矩形裁剪曲面;

11.Offset Surface 偏移曲面;

曲面的几何数据类都有一个共同的基类Geom_Surface,类图如下所示:

在OpenSceneGraph中绘制OpenCascade的曲面_第1张图片

Figure 1.1 Geometry Surface class diagram

抽象基类Geom_Surface有几个纯虚函数Bounds()、Value()等,可用来计算曲面上的点。类图如下所示:

在OpenSceneGraph中绘制OpenCascade的曲面_第2张图片

Figure 1.2 Geom_Surface class diagram

与另一几何内核sgCore中的几何的概念一致,几何(geometry)是用参数方程对曲线曲面精确表示的。

每种曲面都对纯虚函数进行实现,使计算曲面上点的方式统一。

曲线C(u)是单参数的矢值函数,它是由直线段到三维欧几里得空间的映射。曲面是关于两个参数u和v的矢值函数,它表示由uv平面上的二维区域R到三维欧几里得空间的映射。把曲面表示成双参数的形式为:

wps_clip_image-16905

它的参数方程为:

在OpenSceneGraph中绘制OpenCascade的曲面_第3张图片

u,v参数形成了一个参数平面,参数的变化区间在参数平面上构成一个矩形区域。正常情况下,参数域内的点(u,v)与曲面上的点r(u,v)是一一对应的映射关系。

给定一个具体的曲面方程,称之为给定了一个曲面的参数化。它既决定了所表示的曲面的形状,也决定了该曲面上的点与其参数域内的点的一种对应关系。同样地,曲面的参数化不是唯一的。

曲面双参数u,v的变化范围往往取为单位正方形,即u∈[0,1],v∈[0,1]。这样讨论曲面方程时,即简单、方便,又不失一般性。

二、程序示例 Code Example

使用函数Value(u, v)根据参数计算出曲面上的点,将点分u,v方向连成线,可以绘制出曲面的线框模型。程序如下所示:

 

  1  /*
  2  *    Copyright (c) 2013 eryar All Rights Reserved.
  3  *
  4  *        File    : Main.cpp
  5  *        Author  : [email protected]
  6  *        Date    : 2013-08-11 10:36
  7  *        Version : V1.0
  8  *
  9  *    Description : Draw OpenCascade Geometry Surfaces in OpenSceneGraph.
 10  *
 11  */
 12 
 13  //  OpenSceneGraph
 14  #include  < osgDB / ReadFile >
 15  #include  < osgViewer / Viewer >
 16  #include  < osgGA / StateSetManipulator >
 17  #include  < osgViewer / ViewerEventHandlers >
 18 
 19  #pragma comment(lib,  " osgd.lib " )
 20  #pragma comment(lib,  " osgDBd.lib " )
 21  #pragma comment(lib,  " osgGAd.lib " )
 22  #pragma comment(lib,  " osgViewerd.lib " )
 23 
 24  //  OpenCascade
 25  #define  WNT
 26  #include  < TColgp_Array2OfPnt.hxx >
 27  #include  < TColStd_HArray1OfInteger.hxx >
 28  #include  < TColGeom_Array2OfBezierSurface.hxx >
 29  #include  < GeomConvert_CompBezierSurfacesToBSplineSurface.hxx >
 30 
 31  #include  < Geom_Surface.hxx >
 32  #include  < Geom_BezierSurface.hxx >
 33  #include  < Geom_BSplineSurface.hxx >
 34  #include  < Geom_ConicalSurface.hxx >
 35  #include  < Geom_CylindricalSurface.hxx >
 36  #include  < Geom_Plane.hxx >
 37  #include  < Geom_ToroidalSurface.hxx >
 38  #include  < Geom_SphericalSurface.hxx >
 39 
 40  #pragma comment(lib,  " TKernel.lib " )
 41  #pragma comment(lib,  " TKMath.lib " )
 42  #pragma comment(lib,  " TKG3d.lib " )
 43  #pragma comment(lib,  " TKGeomBase.lib " )
 44 
 45  //  Approximation Delta.
 46  const   double  APPROXIMATION_DELTA  =   0.1 ;
 47 
 48  /* *
 49  * @breif Build geometry surface.
 50  */
 51  osg::Node *  buildSurface( const  Geom_Surface &  surface)
 52  {
 53      osg::ref_ptr < osg::Geode >  geode  =   new  osg::Geode();
 54 
 55      gp_Pnt point;
 56      Standard_Real uFirst  =   0.0 ;
 57      Standard_Real vFirst  =   0.0 ;
 58      Standard_Real uLast  =   0.0 ;
 59      Standard_Real vLast  =   0.0 ;
 60 
 61      surface.Bounds(uFirst, uLast, vFirst, vLast);
 62 
 63      Precision::IsNegativeInfinite(uFirst)  ?  uFirst  =   - 1.0  : uFirst;
 64      Precision::IsInfinite(uLast)  ?  uLast  =   1.0  : uLast;
 65 
 66      Precision::IsNegativeInfinite(vFirst)  ?  vFirst  =   - 1.0  : vFirst;
 67      Precision::IsInfinite(vLast)  ?  vLast  =   1.0  : vLast;
 68 
 69       //  Approximation in v direction.
 70       for  (Standard_Real u  =  uFirst; u  <=  uLast; u  +=  APPROXIMATION_DELTA)
 71      {
 72          osg::ref_ptr < osg::Geometry >  linesGeom  =   new  osg::Geometry();
 73          osg::ref_ptr < osg::Vec3Array >  pointsVec  =   new  osg::Vec3Array();
 74 
 75           for  (Standard_Real v  =  vFirst; v  <=  vLast; v  +=  APPROXIMATION_DELTA)
 76          {
 77              point  =  surface.Value(u, v);
 78 
 79              pointsVec -> push_back(osg::Vec3(point.X(), point.Y(), point.Z()));
 80          }
 81 
 82           //  Set the colors.
 83          osg::ref_ptr < osg::Vec4Array >  colors  =   new  osg::Vec4Array;
 84          colors -> push_back(osg::Vec4( 1.0f 1.0f 0.0f 0.0f ));
 85          linesGeom -> setColorArray(colors. get ());
 86          linesGeom -> setColorBinding(osg::Geometry::BIND_OVERALL);
 87 
 88           //  Set the normal in the same way of color.
 89          osg::ref_ptr < osg::Vec3Array >  normals  =   new  osg::Vec3Array;
 90          normals -> push_back(osg::Vec3( 0.0f - 1.0f 0.0f ));
 91          linesGeom -> setNormalArray(normals. get ());
 92          linesGeom -> setNormalBinding(osg::Geometry::BIND_OVERALL);
 93 
 94           //  Set vertex array.
 95          linesGeom -> setVertexArray(pointsVec);
 96          linesGeom -> addPrimitiveSet( new  osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP,  0 , pointsVec -> size()));
 97          
 98          geode -> addDrawable(linesGeom. get ());
 99      }
100 
101       //  Approximation in u direction.
102       for  (Standard_Real v  =  vFirst; v  <=  vLast; v  +=  APPROXIMATION_DELTA)
103      {
104          osg::ref_ptr < osg::Geometry >  linesGeom  =   new  osg::Geometry();
105          osg::ref_ptr < osg::Vec3Array >  pointsVec  =   new  osg::Vec3Array();
106 
107           for  (Standard_Real u  =  vFirst; u  <=  uLast; u  +=  APPROXIMATION_DELTA)
108          {
109              point  =  surface.Value(u, v);
110 
111              pointsVec -> push_back(osg::Vec3(point.X(), point.Y(), point.Z()));
112          }
113 
114           //  Set the colors.
115          osg::ref_ptr < osg::Vec4Array >  colors  =   new  osg::Vec4Array;
116          colors -> push_back(osg::Vec4( 1.0f 1.0f 0.0f 0.0f ));
117          linesGeom -> setColorArray(colors. get ());
118          linesGeom -> setColorBinding(osg::Geometry::BIND_OVERALL);
119 
120           //  Set the normal in the same way of color.
121          osg::ref_ptr < osg::Vec3Array >  normals  =   new  osg::Vec3Array;
122          normals -> push_back(osg::Vec3( 0.0f - 1.0f 0.0f ));
123          linesGeom -> setNormalArray(normals. get ());
124          linesGeom -> setNormalBinding(osg::Geometry::BIND_OVERALL);
125 
126           //  Set vertex array.
127          linesGeom -> setVertexArray(pointsVec);
128          linesGeom -> addPrimitiveSet( new  osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP,  0 , pointsVec -> size()));
129          
130          geode -> addDrawable(linesGeom. get ());
131      }
132 
133       return  geode.release();
134  }
135 
136  /* *
137  * @breif Test geometry surfaces of OpenCascade.
138  */
139  osg::Node *  buildScene( void )
140  {
141      osg::ref_ptr < osg::Group >  root  =   new  osg::Group();
142 
143       //  Test Plane.
144      Geom_Plane plane(gp::XOY());
145      root -> addChild(buildSurface(plane));
146 
147       //  Test Bezier Surface and B-Spline Surface.
148      TColgp_Array2OfPnt array1( 1 , 3 , 1 , 3 );
149      TColgp_Array2OfPnt array2( 1 , 3 , 1 , 3 );
150      TColgp_Array2OfPnt array3( 1 , 3 , 1 , 3 );
151      TColgp_Array2OfPnt array4( 1 , 3 , 1 , 3 );
152 
153      array1.SetValue( 1 , 1 ,gp_Pnt( 1 , 1 , 1 ));
154      array1.SetValue( 1 , 2 ,gp_Pnt( 2 , 1 , 2 ));
155      array1.SetValue( 1 , 3 ,gp_Pnt( 3 , 1 , 1 ));
156      array1.SetValue( 2 , 1 ,gp_Pnt( 1 , 2 , 1 ));
157      array1.SetValue( 2 , 2 ,gp_Pnt( 2 , 2 , 2 ));
158      array1.SetValue( 2 , 3 ,gp_Pnt( 3 , 2 , 0 ));
159      array1.SetValue( 3 , 1 ,gp_Pnt( 1 , 3 , 2 ));
160      array1.SetValue( 3 , 2 ,gp_Pnt( 2 , 3 , 1 ));
161      array1.SetValue( 3 , 3 ,gp_Pnt( 3 , 3 , 0 ));
162 
163      array2.SetValue( 1 , 1 ,gp_Pnt( 3 , 1 , 1 ));
164      array2.SetValue( 1 , 2 ,gp_Pnt( 4 , 1 , 1 ));
165      array2.SetValue( 1 , 3 ,gp_Pnt( 5 , 1 , 2 ));
166      array2.SetValue( 2 , 1 ,gp_Pnt( 3 , 2 , 0 ));
167      array2.SetValue( 2 , 2 ,gp_Pnt( 4 , 2 , 1 ));
168      array2.SetValue( 2 , 3 ,gp_Pnt( 5 , 2 , 2 ));
169      array2.SetValue( 3 , 1 ,gp_Pnt( 3 , 3 , 0 ));
170      array2.SetValue( 3 , 2 ,gp_Pnt( 4 , 3 , 0 ));
171      array2.SetValue( 3 , 3 ,gp_Pnt( 5 , 3 , 1 ));
172 
173      array3.SetValue( 1 , 1 ,gp_Pnt( 1 , 3 , 2 ));
174      array3.SetValue( 1 , 2 ,gp_Pnt( 2 , 3 , 1 ));
175      array3.SetValue( 1 , 3 ,gp_Pnt( 3 , 3 , 0 ));
176      array3.SetValue( 2 , 1 ,gp_Pnt( 1 , 4 , 1 ));
177      array3.SetValue( 2 , 2 ,gp_Pnt( 2 , 4 , 0 ));
178      array3.SetValue( 2 , 3 ,gp_Pnt( 3 , 4 , 1 ));
179      array3.SetValue( 3 , 1 ,gp_Pnt( 1 , 5 , 1 ));
180      array3.SetValue( 3 , 2 ,gp_Pnt( 2 , 5 , 1 ));
181      array3.SetValue( 3 , 3 ,gp_Pnt( 3 , 5 , 2 ));
182 
183      array4.SetValue( 1 , 1 ,gp_Pnt( 3 , 3 , 0 ));
184      array4.SetValue( 1 , 2 ,gp_Pnt( 4 , 3 , 0 ));
185      array4.SetValue( 1 , 3 ,gp_Pnt( 5 , 3 , 1 ));
186      array4.SetValue( 2 , 1 ,gp_Pnt( 3 , 4 , 1 ));
187      array4.SetValue( 2 , 2 ,gp_Pnt( 4 , 4 , 1 ));
188      array4.SetValue( 2 , 3 ,gp_Pnt( 5 , 4 , 1 ));
189      array4.SetValue( 3 , 1 ,gp_Pnt( 3 , 5 , 2 ));
190      array4.SetValue( 3 , 2 ,gp_Pnt( 4 , 5 , 2 ));
191      array4.SetValue( 3 , 3 ,gp_Pnt( 5 , 5 , 1 ));
192 
193      Geom_BezierSurface BZ1(array1);
194      Geom_BezierSurface BZ2(array2);
195      Geom_BezierSurface BZ3(array3);
196      Geom_BezierSurface BZ4(array4);
197      root -> addChild(buildSurface(BZ1));
198      root -> addChild(buildSurface(BZ2));
199      root -> addChild(buildSurface(BZ3));
200      root -> addChild(buildSurface(BZ4));
201 
202      Handle_Geom_BezierSurface BS1  =   new  Geom_BezierSurface(array1);
203      Handle_Geom_BezierSurface BS2  =   new  Geom_BezierSurface(array2);
204      Handle_Geom_BezierSurface BS3  =   new  Geom_BezierSurface(array3);
205      Handle_Geom_BezierSurface BS4  =   new  Geom_BezierSurface(array4);
206      TColGeom_Array2OfBezierSurface bezierarray( 1 , 2 , 1 , 2 );
207      bezierarray.SetValue( 1 , 1 ,BS1);
208      bezierarray.SetValue( 1 , 2 ,BS2);
209      bezierarray.SetValue( 2 , 1 ,BS3);
210      bezierarray.SetValue( 2 , 2 ,BS4);
211 
212      GeomConvert_CompBezierSurfacesToBSplineSurface BB (bezierarray);
213 
214       if  (BB.IsDone())
215      {
216          Geom_BSplineSurface BSPLSURF(
217              BB.Poles() -> Array2(),
218              BB.UKnots() -> Array1(),
219              BB.VKnots() -> Array1(),
220              BB.UMultiplicities() -> Array1(),
221              BB.VMultiplicities() -> Array1(),
222              BB.UDegree(),
223              BB.VDegree() );
224 
225          BSPLSURF.Translate(gp_Vec( 0 , 0 , 2 ));
226 
227          root -> addChild(buildSurface(BSPLSURF));
228      }
229 
230       //  Test Spherical Surface.
231      Geom_SphericalSurface sphericalSurface(gp::XOY(),  1.0 );
232      sphericalSurface.Translate(gp_Vec( 2.5 0.0 0.0 ));
233      root -> addChild(buildSurface(sphericalSurface));
234 
235       //  Test Conical Surface.
236      Geom_ConicalSurface conicalSurface(gp::XOY(), M_PI / 8 1.0 );
237      conicalSurface.Translate(gp_Vec( 5.0 0.0 0.0 ));
238      root -> addChild(buildSurface(conicalSurface));
239 
240       //  Test Cylindrical Surface.
241      Geom_CylindricalSurface cylindricalSurface(gp::XOY(),  1.0 );
242      cylindricalSurface.Translate(gp_Vec( 8.0 0.0 0.0 ));
243      root -> addChild(buildSurface(cylindricalSurface));
244 
245       //  Test Toroidal Surface.
246      Geom_ToroidalSurface toroidalSurface(gp::XOY(),  1.0 0.2 );
247      toroidalSurface.Translate(gp_Vec( 11.0 0.0 0.0 ));
248      root -> addChild(buildSurface(toroidalSurface));
249 
250       return  root.release();
251  }
252 
253  int  main( int  argc,  char *  argv[])
254  {
255      osgViewer::Viewer myViewer;
256      
257      myViewer.setSceneData(buildScene());
258 
259      myViewer.addEventHandler( new  osgGA::StateSetManipulator(myViewer.getCamera() -> getOrCreateStateSet()));
260      myViewer.addEventHandler( new  osgViewer::StatsHandler);
261      myViewer.addEventHandler( new  osgViewer::WindowSizeHandler);
262 
263       return  myViewer.run();
264  }

程序效果如下图所示:

在OpenSceneGraph中绘制OpenCascade的曲面_第4张图片

Figure 2.1 OpenCascade Geometry Surfaces in OpenSceneGraph

三、结论 Conclusion

根据OpenCascade中的几何曲面的函数Value(u, v)可以计算出曲面上的点。分u方向和v方向分别绘制曲面上的点,并将之连接成线,即可以表示出曲面的线框模型。因为这样的模型没有面的信息,所以不能有光照效果、材质效果等。要有光照、材质的信息,必须将曲面进行三角剖分。相关的剖分算法有Delaunay三角剖分等。

 

PDF Version: Draw OpenCascade Geometry Surfaces in OpenSceneGraph

你可能感兴趣的:(在OpenSceneGraph中绘制OpenCascade的曲面)