在 OpenSceneGraph 中绘制 OpenCascade 的曲线 Draw OpenCascade Geometry Curves in OpenSceneGraph eryar@163.com 摘要 Abstract: 本文简要说明 OpenCascade 中几何曲线的数据, 并将这些几何曲线在 OpenSceneGraph 中绘制出来 关键字 KeyWords:OpenCascade Geometry Curve OpenSceneGraph B-Spline NURBS 一 引言 Introduction 结合 BRep Format Description White Paper 对 OpenCascade 中的几何数据结构有详细 的介绍 OpenCascade 中 BRep 格式中的曲线总共分为九种, 不过有二维三维之分 : 1. 直线 Line 2. 圆 Circle 3. 椭圆 Ellipse 4. 抛物线 Parabola 5. 双曲线 Hyperbola 6.Bezier 曲线 Bezier Curve 7.B-Spline 曲线 B-Spline Curve 8. 裁剪曲线 Trimmed Curve 9. 偏移曲线 Offset Curve 曲线的几何数据都有一个抽象基类 Geom_Curve, 类图如下所示 : Figure 1.1 Geometry curve class diagram 抽象基类 Geom_Curve 有几个纯虚函数 FirstParameter() LastParameter() Value(), 根据这几个虚函数, 就可以计算曲线上对应参数 U 的值 类图如下图所示 :
Geom_Circle Geom_BezierCurve Geom_Ellipse Geom_Curve +Standard_Real FirstParameter() +Standard_Real LastParameter() +gp_pnt Value(const Standard_Real U) Geom_BSplineCurve Geom_Hyperbola Geom_TrimmedCurve Geom_Parabola Geom_Line Figure 1.2 Geom_Curve Inherited class diagram 每种曲线都对那些纯虚函数进行实现, 使计算曲线上点的方式统一
二 程序示例 Code Example 根据抽象基类 Geom_Curve 的几个纯虚函数 : 1.FirstParameter(); 2.LastParameter(); 3.Value(u); 利用多态可将曲线上点都以统一的方式计算出来, 并使用 GL_LINE_STRIP 绘制出来 示例程序如下所示 : /* * Copyright (c) 2013 eryar All Rights Reserved. * * File : Main.cpp * Author : eryar@163.com * Date : 2013-08-09 18:09 * Version : 1.0v * * Description : Draw OpenCascade Geometry Curves in OpenSceneGraph. * */ // OpenSceneGraph library. #include <osgdb/readfile> #include <osgviewer/viewer> #include <osgviewer/viewereventhandlers> #include <osgga/statesetmanipulator> #pragma comment(lib, "osgd.lib") #pragma comment(lib, "osgdbd.lib") #pragma comment(lib, "osggad.lib") #pragma comment(lib, "osgviewerd.lib") // OpenCascade library. #include <TColgp_Array1OfPnt.hxx> #include <TColStd_Array1OfReal.hxx> #include <TColStd_Array1OfInteger.hxx> #include <Geom_Circle.hxx> #include <Geom_Ellipse.hxx> #include <Geom_Hyperbola.hxx> #include <Geom_Parabola.hxx> #include <Geom_BezierCurve.hxx> #include <Geom_BSplineCurve.hxx> #pragma comment(lib, "TKernel.lib") #pragma comment(lib, "TKMath.lib") #pragma comment(lib, "TKG3d.lib") // Curve Segment Delta. const double CURVE_SEGMENT_DELTA = 0.01; /*
* @brief Build geometry curve of OpenCascade. */ osg::node* buildcurve(const Geom_Curve& curve) osg::ref_ptr<osg::geode> geode = new osg::geode(); osg::ref_ptr<osg::geometry> linesgeom = new osg::geometry(); osg::ref_ptr<osg::vec3array> pointsvec = new osg::vec3array(); gp_pnt point; double dfirst = curve.firstparameter(); double dlast = curve.lastparameter(); Precision::IsNegativeInfinite(dFirst)? dfirst = -1.0 : dfirst; Precision::IsInfinite(dLast)? dlast = 1.0 : dlast; for (double u = dfirst; u <= dlast; u += CURVE_SEGMENT_DELTA) point = curve.value(u); } 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, 0, pointsvec->size())); geode->adddrawable(linesgeom.get()); } return geode.release(); /** * @breif Build geometry curve of OpenCascade. */ osg::node* buildscene() osg::ref_ptr<osg::group> root = new osg::group();
// 1. Build circle curve. Geom_Circle circle(gp::yoz(), 1.0); root->addchild(buildcurve(circle)); // 2. Build ellipse curve. Geom_Ellipse ellipse(gp::zox(), 1.0, 0.3); root->addchild(buildcurve(ellipse)); // 3. Build Hyperbola curve. Geom_Hyperbola hyperbola(gp::xoy(), 1.0, 0.6); root->addchild(buildcurve(hyperbola)); // 4. Build parabola curve. Geom_Parabola parabola(gp::zox(), 1.0); root->addchild(buildcurve(parabola)); // 5. Build Bezier curve. TColgp_Array1OfPnt poles(1, 4); poles.setvalue(1, gp_pnt(-1, -1, 0)); poles.setvalue(2, gp_pnt(1, 2, 0)); poles.setvalue(3, gp_pnt(3, 0, 0)); poles.setvalue(4, gp_pnt(4, 1, 0)); Geom_BezierCurve beziercurve(poles); root->addchild(buildcurve(beziercurve)); // 6. Build BSpline curve. TColgp_Array1OfPnt ctrlpnts(1, 3); TColStd_Array1OfReal knots(1, 5); TColStd_Array1OfInteger mults(1, 5); ctrlpnts.setvalue(1, gp_pnt(0, 1, 0)); ctrlpnts.setvalue(2, gp_pnt(1, -2, 0)); ctrlpnts.setvalue(3, gp_pnt(2, 3, 0)); knots.setvalue(1, 0.0); knots.setvalue(2, 0.25); knots.setvalue(3, 0.5); knots.setvalue(4, 0.75); knots.setvalue(5, 1.0); mults.init(1); Geom_BSplineCurve bsplinecurve(ctrlpnts, knots, mults, 1); root->addchild(buildcurve(bsplinecurve));
} 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(); 因抛物线和双曲线的 FirstParameter() 和 LastParameter() 为负无穷和正无穷, 所以对其进行处理, 只输出了部分曲线 程序效果如下图所示 : Figure 2.1 OpenCascade Geometry Curves in OpenSceneGraph
三 结论 Conclusion OpenCascade 的几何数据使用还是很方便的, 只要将相应的曲线构造出来之后, 计算曲线上的点使用函数 Value() 即可, 还可计算相应参数处的微分值等 通过理解 BRep Format Description White Paper, 可将 BRep 文件中数据导入 OpenCascade 中与上面实现的程序进行对比, 结果正确 如下图所示 : Figure 3.1 B-Spline in OpenSceneGraph Figure 3.2 B-Spline in OpenCascade Draw