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

/*
* Copyright (c) 2013 eryar All Rights Reserved.
*
* File : Main.cpp
* Author : eryar@163.com
* Date : 2013-08-11 10:36
* Version : V1.0
*
* Description : Draw OpenCascade Geometry Surfaces in OpenSceneGraph.
*
*/ // OpenSceneGraph
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osgGA/StateSetManipulator>
#include <osgViewer/ViewerEventHandlers> #pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib") // OpenCascade
#define WNT
#include <TColgp_Array2OfPnt.hxx>
#include <TColStd_HArray1OfInteger.hxx>
#include <TColGeom_Array2OfBezierSurface.hxx>
#include <GeomConvert_CompBezierSurfacesToBSplineSurface.hxx> #include <Geom_Surface.hxx>
#include <Geom_BezierSurface.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Geom_ConicalSurface.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom_Plane.hxx>
#include <Geom_ToroidalSurface.hxx>
#include <Geom_SphericalSurface.hxx> #pragma comment(lib, "TKernel.lib")
#pragma comment(lib, "TKMath.lib")
#pragma comment(lib, "TKG3d.lib")
#pragma comment(lib, "TKGeomBase.lib") // Approximation Delta.
const double APPROXIMATION_DELTA = 0.1; /**
* @breif Build geometry surface.
*/
osg::Node* buildSurface(const Geom_Surface& surface)
{
osg::ref_ptr<osg::Geode> geode = new osg::Geode(); gp_Pnt point;
Standard_Real uFirst = 0.0;
Standard_Real vFirst = 0.0;
Standard_Real uLast = 0.0;
Standard_Real vLast = 0.0; surface.Bounds(uFirst, uLast, vFirst, vLast); Precision::IsNegativeInfinite(uFirst) ? uFirst = -1.0 : uFirst;
Precision::IsInfinite(uLast) ? uLast = 1.0 : uLast; Precision::IsNegativeInfinite(vFirst) ? vFirst = -1.0 : vFirst;
Precision::IsInfinite(vLast) ? vLast = 1.0 : vLast; // Approximation in v direction.
for (Standard_Real u = uFirst; u <= uLast; u += APPROXIMATION_DELTA)
{
osg::ref_ptr<osg::Geometry> linesGeom = new osg::Geometry();
osg::ref_ptr<osg::Vec3Array> pointsVec = new osg::Vec3Array(); for (Standard_Real v = vFirst; v <= vLast; v += APPROXIMATION_DELTA)
{
point = surface.Value(u, v); pointsVec->push_back(osg::Vec3(point.X(), point.Y(), point.Z()));
} // Set the colors.
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f, 1.0f, 0.0f, 0.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.0f, 0.0f));
linesGeom->setNormalArray(normals.get());
linesGeom->setNormalBinding(osg::Geometry::BIND_OVERALL); // Set vertex array.
linesGeom->setVertexArray(pointsVec);
linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, , pointsVec->size())); geode->addDrawable(linesGeom.get());
} // Approximation in u direction.
for (Standard_Real v = vFirst; v <= vLast; v += APPROXIMATION_DELTA)
{
osg::ref_ptr<osg::Geometry> linesGeom = new osg::Geometry();
osg::ref_ptr<osg::Vec3Array> pointsVec = new osg::Vec3Array(); for (Standard_Real u = vFirst; u <= uLast; u += APPROXIMATION_DELTA)
{
point = surface.Value(u, v); pointsVec->push_back(osg::Vec3(point.X(), point.Y(), point.Z()));
} // Set the colors.
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f, 1.0f, 0.0f, 0.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.0f, 0.0f));
linesGeom->setNormalArray(normals.get());
linesGeom->setNormalBinding(osg::Geometry::BIND_OVERALL); // Set vertex array.
linesGeom->setVertexArray(pointsVec);
linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, , pointsVec->size())); geode->addDrawable(linesGeom.get());
} return geode.release();
} /**
* @breif Test geometry surfaces of OpenCascade.
*/
osg::Node* buildScene(void)
{
osg::ref_ptr<osg::Group> root = new osg::Group(); // Test Plane.
Geom_Plane plane(gp::XOY());
root->addChild(buildSurface(plane)); // Test Bezier Surface and B-Spline Surface.
TColgp_Array2OfPnt array1(,,,);
TColgp_Array2OfPnt array2(,,,);
TColgp_Array2OfPnt array3(,,,);
TColgp_Array2OfPnt array4(,,,); array1.SetValue(,,gp_Pnt(,,));
array1.SetValue(,,gp_Pnt(,,));
array1.SetValue(,,gp_Pnt(,,));
array1.SetValue(,,gp_Pnt(,,));
array1.SetValue(,,gp_Pnt(,,));
array1.SetValue(,,gp_Pnt(,,));
array1.SetValue(,,gp_Pnt(,,));
array1.SetValue(,,gp_Pnt(,,));
array1.SetValue(,,gp_Pnt(,,)); array2.SetValue(,,gp_Pnt(,,));
array2.SetValue(,,gp_Pnt(,,));
array2.SetValue(,,gp_Pnt(,,));
array2.SetValue(,,gp_Pnt(,,));
array2.SetValue(,,gp_Pnt(,,));
array2.SetValue(,,gp_Pnt(,,));
array2.SetValue(,,gp_Pnt(,,));
array2.SetValue(,,gp_Pnt(,,));
array2.SetValue(,,gp_Pnt(,,)); array3.SetValue(,,gp_Pnt(,,));
array3.SetValue(,,gp_Pnt(,,));
array3.SetValue(,,gp_Pnt(,,));
array3.SetValue(,,gp_Pnt(,,));
array3.SetValue(,,gp_Pnt(,,));
array3.SetValue(,,gp_Pnt(,,));
array3.SetValue(,,gp_Pnt(,,));
array3.SetValue(,,gp_Pnt(,,));
array3.SetValue(,,gp_Pnt(,,)); array4.SetValue(,,gp_Pnt(,,));
array4.SetValue(,,gp_Pnt(,,));
array4.SetValue(,,gp_Pnt(,,));
array4.SetValue(,,gp_Pnt(,,));
array4.SetValue(,,gp_Pnt(,,));
array4.SetValue(,,gp_Pnt(,,));
array4.SetValue(,,gp_Pnt(,,));
array4.SetValue(,,gp_Pnt(,,));
array4.SetValue(,,gp_Pnt(,,)); Geom_BezierSurface BZ1(array1);
Geom_BezierSurface BZ2(array2);
Geom_BezierSurface BZ3(array3);
Geom_BezierSurface BZ4(array4);
root->addChild(buildSurface(BZ1));
root->addChild(buildSurface(BZ2));
root->addChild(buildSurface(BZ3));
root->addChild(buildSurface(BZ4)); Handle_Geom_BezierSurface BS1 = new Geom_BezierSurface(array1);
Handle_Geom_BezierSurface BS2 = new Geom_BezierSurface(array2);
Handle_Geom_BezierSurface BS3 = new Geom_BezierSurface(array3);
Handle_Geom_BezierSurface BS4 = new Geom_BezierSurface(array4);
TColGeom_Array2OfBezierSurface bezierarray(,,,);
bezierarray.SetValue(,,BS1);
bezierarray.SetValue(,,BS2);
bezierarray.SetValue(,,BS3);
bezierarray.SetValue(,,BS4); GeomConvert_CompBezierSurfacesToBSplineSurface BB (bezierarray); if (BB.IsDone())
{
Geom_BSplineSurface BSPLSURF(
BB.Poles()->Array2(),
BB.UKnots()->Array1(),
BB.VKnots()->Array1(),
BB.UMultiplicities()->Array1(),
BB.VMultiplicities()->Array1(),
BB.UDegree(),
BB.VDegree() ); BSPLSURF.Translate(gp_Vec(,,)); root->addChild(buildSurface(BSPLSURF));
} // Test Spherical Surface.
Geom_SphericalSurface sphericalSurface(gp::XOY(), 1.0);
sphericalSurface.Translate(gp_Vec(2.5, 0.0, 0.0));
root->addChild(buildSurface(sphericalSurface)); // Test Conical Surface.
Geom_ConicalSurface conicalSurface(gp::XOY(), M_PI/, 1.0);
conicalSurface.Translate(gp_Vec(5.0, 0.0, 0.0));
root->addChild(buildSurface(conicalSurface)); // Test Cylindrical Surface.
Geom_CylindricalSurface cylindricalSurface(gp::XOY(), 1.0);
cylindricalSurface.Translate(gp_Vec(8.0, 0.0, 0.0));
root->addChild(buildSurface(cylindricalSurface)); // Test Toroidal Surface.
Geom_ToroidalSurface toroidalSurface(gp::XOY(), 1.0, 0.2);
toroidalSurface.Translate(gp_Vec(11.0, 0.0, 0.0));
root->addChild(buildSurface(toroidalSurface)); return root.release();
} int main(int argc, char* argv[])
{
osgViewer::Viewer myViewer; myViewer.setSceneData(buildScene()); myViewer.addEventHandler(new osgGA::StateSetManipulator(myViewer.getCamera()->getOrCreateStateSet()));
myViewer.addEventHandler(new osgViewer::StatsHandler);
myViewer.addEventHandler(new osgViewer::WindowSizeHandler); return myViewer.run();
}

程序效果如下图所示:

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. 无法导入以下密钥文件: xxxx.pfx,该密钥文件可能受密码保护 的解决方案

    无法导入以下密钥文件: xxxx.pfx,该密钥文件可能受密码保护.若要更正此问题,请尝试再次导入证书,或手动将证书安装到具有以下密钥容器名称的强名称 CSP: VS_KEY_A5A29909FF6D ...

  2. [Java基础]字符串

    1.字符串特点 字符串是常量,创建之后不能修改: 字符串的内容一旦修改,就会马上创建一个新的对象: 字符串实际为一个char value[]={'a','a'};数组: 2.==与equal判断字符串 ...

  3. CA Loves GCD (BC#78 1002) (hdu 5656)

    CA Loves GCD  Accepts: 135  Submissions: 586  Time Limit: 6000/3000 MS (Java/Others)  Memory Limit: ...

  4. 多语言配置--LogisticsPlatform物流平台系统

    先看:LanguageProvider.cs   中几个主要方法 1.读取默认语言 附user.ini文件: 2.获取语言类型 附LanguageType.xml 3.读取语言资源 附:   看ILa ...

  5. UIWebView和Js交互

    在日常的ios项目开发中,我们经常会在原生应用中嵌入web页面,通常我们只是进行一个展示,没有其它的一些功能.但是也有一些项目中需要web页面中的html和native进行交互.但是ios sdk 并 ...

  6. (转)Silverlight控件关系理解

    原文地址http://www.cnblogs.com/Joetao/articles/1899664.html 本篇学习了Silverlight中的控件继承关系,了解控件的继承关系对应我们操作控件,使 ...

  7. Django的virtualenv环境搭建

    安装virtualenv好处多多,可以让当前的项目使用单独的类库,实现系统类库的隔离,所以能够自由地控制当前项目类库的版本,不受系统类库的影响:还有其他N多好处. 下面是安装说明和使用示例: 首先安装 ...

  8. UILabel实现自适应高宽

    UILabel是iOS开发常用的控件.UILabel的属性需要了解,UILabel的特殊显示效果也需要我们掌握.UILabel自适应高宽度是很多初学者遇到的技术性难题.比如段文字,要让他完全地分行显示 ...

  9. Mac环境下svn的使用

    在Windows环境中,我们一般使用TortoiseSVN来搭建svn环境.在Mac环境下,由于Mac自带了svn的服务器端和客户端功能,所以我们可以在不装任何第三方软件的前提下使用svn功能,不过还 ...

  10. 蛙蛙推荐:WEB安全入门

    信息安全基础 信息安全目标 真实性:对信息的来源进行判断,能对伪造来源的信息予以鉴别, 就是身份认证. 保密性:保证机密信息不被窃听,盗取,或窃听者不能了解信息的真实含义. 完整性:保证数据的一致性, ...