在OpenSceneGraph中绘制OpenCascade的曲面

Render OpenCascade Geometry Surfaces in OpenSceneGraph

eryar@163.com

摘要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方向连成线,可以绘制出曲面的线框模型。程序如下所示:

  1. /*
  2. * Copyright (c) 2013 eryar All Rights Reserved.
  3. *
  4. * File : Main.cpp
  5. * Author : eryar@163.com
  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, , 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, , 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(,,,);
  149. TColgp_Array2OfPnt array2(,,,);
  150. TColgp_Array2OfPnt array3(,,,);
  151. TColgp_Array2OfPnt array4(,,,);
  152.  
  153. array1.SetValue(,,gp_Pnt(,,));
  154. array1.SetValue(,,gp_Pnt(,,));
  155. array1.SetValue(,,gp_Pnt(,,));
  156. array1.SetValue(,,gp_Pnt(,,));
  157. array1.SetValue(,,gp_Pnt(,,));
  158. array1.SetValue(,,gp_Pnt(,,));
  159. array1.SetValue(,,gp_Pnt(,,));
  160. array1.SetValue(,,gp_Pnt(,,));
  161. array1.SetValue(,,gp_Pnt(,,));
  162.  
  163. array2.SetValue(,,gp_Pnt(,,));
  164. array2.SetValue(,,gp_Pnt(,,));
  165. array2.SetValue(,,gp_Pnt(,,));
  166. array2.SetValue(,,gp_Pnt(,,));
  167. array2.SetValue(,,gp_Pnt(,,));
  168. array2.SetValue(,,gp_Pnt(,,));
  169. array2.SetValue(,,gp_Pnt(,,));
  170. array2.SetValue(,,gp_Pnt(,,));
  171. array2.SetValue(,,gp_Pnt(,,));
  172.  
  173. array3.SetValue(,,gp_Pnt(,,));
  174. array3.SetValue(,,gp_Pnt(,,));
  175. array3.SetValue(,,gp_Pnt(,,));
  176. array3.SetValue(,,gp_Pnt(,,));
  177. array3.SetValue(,,gp_Pnt(,,));
  178. array3.SetValue(,,gp_Pnt(,,));
  179. array3.SetValue(,,gp_Pnt(,,));
  180. array3.SetValue(,,gp_Pnt(,,));
  181. array3.SetValue(,,gp_Pnt(,,));
  182.  
  183. array4.SetValue(,,gp_Pnt(,,));
  184. array4.SetValue(,,gp_Pnt(,,));
  185. array4.SetValue(,,gp_Pnt(,,));
  186. array4.SetValue(,,gp_Pnt(,,));
  187. array4.SetValue(,,gp_Pnt(,,));
  188. array4.SetValue(,,gp_Pnt(,,));
  189. array4.SetValue(,,gp_Pnt(,,));
  190. array4.SetValue(,,gp_Pnt(,,));
  191. array4.SetValue(,,gp_Pnt(,,));
  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(,,,);
  207. bezierarray.SetValue(,,BS1);
  208. bezierarray.SetValue(,,BS2);
  209. bezierarray.SetValue(,,BS3);
  210. bezierarray.SetValue(,,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(,,));
  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/, 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三角剖分等。

Render OpenCascade Geometry Surfaces in OpenSceneGraph的更多相关文章

  1. Render OpenCascade Geometry Curves in OpenSceneGraph

    在OpenSceneGraph中绘制OpenCascade的曲线 Render OpenCascade Geometry Curves in OpenSceneGraph eryar@163.com ...

  2. OpenCascade Shape Representation in OpenSceneGraph

    OpenCascade Shape Representation in OpenSceneGraph eryar@163.com 摘要Abstract:本文通过程序实例,将OpenCascade中的拓 ...

  3. Opencascade、OpenGL和OpenSceneGraph的区别与联系

    OpenGL只是三维显示 Openscenegraph基于场景图的概念,它提供一个在OpenGL之上的面向对象的框架,从而能把开发者从实现和优化底层图形的调用中解脱出来 Opencascade更适合算 ...

  4. OpenCASCADE Linear Extrusion Surface

    OpenCASCADE Linear Extrusion Surface eryar@163.com Abstract. OpenCASCADE linear extrusion surface is ...

  5. Polynomial Library in OpenCascade

    Polynomial Library in OpenCascade eryar@163.com 摘要Abstract:分析幂基曲线即多项式曲线在OpenCascade中的计算方法,以及利用OpenSc ...

  6. Representation Data in OpenCascade BRep

    Representation Data in OpenCascade BRep eryar@163.com 摘要Abstract:现在的显示器大多数是光栅显示器,即可以看做一个像素的矩阵.在光栅显示器 ...

  7. Open Cascade 转化为OpenSceneGraph中的Mesh

    #include <osgDB/ReadFile> #include <osgViewer/Viewer> #include <osgGA/StateSetManipul ...

  8. OpenCASCADE Data Exchange - 3D PDF

    OpenCASCADE Data Exchange - 3D PDF eryar@163.com Abstract. Today most 3D engineering model data are ...

  9. Visualize Surface by Delaunay Triangulator

    Visualize Surface by Delaunay Triangulator eryar@163.com Abstract. Delaunay Triangulation is the cor ...

随机推荐

  1. linux bash中too many arguments问题的解决方法

    今天在编写shell脚本时,在if条件后跟的是[ $pid ],执行脚本的时候报 然后我输入改为[[$pid]]后,再执行脚本,就成功了,代码如下: #!/bin/bash pid=`ps -ef|g ...

  2. 举例详解CSS中的cursor属性

    这篇文章主要举例介绍了CSS中的cursor属性,包括zoom-in/zoom-out和grab/grabbing等常用属性值的使用,需要的朋友可以参考下 一.开篇之言 CSS3的领域范围已经渗透到了 ...

  3. java.lang.RuntimeException: Method setUp in android.test.ApplicationTestCase not mocked. See http://g.co/androidstudio/not-mocked for details.

    解决: build.gradle里加入: android { testOptions { unitTests.returnDefaultValues = true } }

  4. 浅谈Swift集合类型

    Swift 的集合表现形式由数组和字典组成.它可以完美的存储任何呢想存储的东西. 数组是一个同类型的序列化列表集合,它用来存储相同类型的不同值.字典也是一个数组,但它的存值方式类似于Map,通过一对一 ...

  5. selenium 富文本框处理

    selenium 富文本框处理, 网上有用API的解决方法1:参见:http://blog.csdn.net/xc5683/article/details/8963621 群里1位群友的解决方法2:参 ...

  6. Entity Framework EF6使用 MySql创建数据库异常解决办法

    EF6使用MySQL数据库时,第一次创建数据库出现“Specified key was too long; max key length is 767 bytes”错误,解决办法请见以下连接. htt ...

  7. php小trick

    1.unset函数是注销变量函数2.mysql 绕过截断单引号 (1)(php单引号不解析,双引号解析)$query='select * from flag where user=\''.$user[ ...

  8. 初学python里的yield send next

    今天看书的时候突然看到这个想起来一直没有怎么使用过send和next试了一下 发现了一个诡异的问题 import math def get_primes(start): while 1 : if is ...

  9. 淘宝上倒卖新浪微盘事件来龙去脉——谈谈巧用IMEI

    这是一个老黄历的事件,曾记得淘宝上的卖家卖10元卖50g网络硬盘,并且卖的相当的火,一个月就卖了500个账号.由于我也是那个事件的亲身经历者之一,这里就看到了IMEI号在项目中防止作弊是何其的重要. ...

  10. mono的远程调试

    mono可以让.net程序运行在linux平台上.于是.net程序员有了mono之后就转身跨平台了.但开放环境往往还是在windows下,于是有了这样的需求,是否可以用windows下的源码来实机调试 ...