在OpenSceneGraph中绘制OpenCascade的曲面
Draw OpenCascade Geometry Surfaces in OpenSceneGraph
摘要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,类图如下所示:
Figure 1.1 Geometry Surface class diagram
抽象基类Geom_Surface有几个纯虚函数Bounds()、Value()等,可用来计算曲面上的点。类图如下所示:
Figure 1.2 Geom_Surface class diagram
与另一几何内核sgCore中的几何的概念一致,几何(geometry)是用参数方程对曲线曲面精确表示的。
每种曲面都对纯虚函数进行实现,使计算曲面上点的方式统一。
曲线C(u)是单参数的矢值函数,它是由直线段到三维欧几里得空间的映射。曲面是关于两个参数u和v的矢值函数,它表示由uv平面上的二维区域R到三维欧几里得空间的映射。把曲面表示成双参数的形式为:
它的参数方程为:
u,v参数形成了一个参数平面,参数的变化区间在参数平面上构成一个矩形区域。正常情况下,参数域内的点(u,v)与曲面上的点r(u,v)是一一对应的映射关系。
给定一个具体的曲面方程,称之为给定了一个曲面的参数化。它既决定了所表示的曲面的形状,也决定了该曲面上的点与其参数域内的点的一种对应关系。同样地,曲面的参数化不是唯一的。
曲面双参数u,v的变化范围往往取为单位正方形,即u∈[0,1],v∈[0,1]。这样讨论曲面方程时,即简单、方便,又不失一般性。
二、程序示例 Code Example
使用函数Value(u, v)根据参数计算出曲面上的点,将点分u,v方向连成线,可以绘制出曲面的线框模型。程序如下所示:
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 }
程序效果如下图所示:
Figure 2.1 OpenCascade Geometry Surfaces in OpenSceneGraph
三、结论 Conclusion
根据OpenCascade中的几何曲面的函数Value(u, v)可以计算出曲面上的点。分u方向和v方向分别绘制曲面上的点,并将之连接成线,即可以表示出曲面的线框模型。因为这样的模型没有面的信息,所以不能有光照效果、材质效果等。要有光照、材质的信息,必须将曲面进行三角剖分。相关的剖分算法有Delaunay三角剖分等。
PDF Version: Draw OpenCascade Geometry Surfaces in OpenSceneGraph