Open Cascade建模示例.doc_第1页
Open Cascade建模示例.doc_第2页
Open Cascade建模示例.doc_第3页
Open Cascade建模示例.doc_第4页
Open Cascade建模示例.doc_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1 概述本示例讲述如何使用Open Cascade来创建一个3D模型,目的并不是介绍所有的Open Cascade类,而是对Open Cascade 有个基本了解;1.1 基本要求要求有使用C+的经验。从编程角度来说,Open Cascade提供了高效的模型库、方法和函数,来进行C+开发。利用这些资源,可以开发出稳定的应用程序。1.2项目在这里利用3D几何模型工具提供的类创建一个瓶子,如下图所示:在这里,会将每一步的在一个函数里生成。函数的完整的源代码在程序中,有一个MakeBottle函数。这个函数在Tutorial/src/MakeBottle.cxx文件中。1.3 项目说明首先,定义瓶子的一些参数:内容参数名称参数值瓶高MyHeight70mm瓶宽MyWidth50mm瓶厚MyThickness30mm现在,假定世界笛卡尔直角坐标系的原点位于瓶子底部的中心。 创建这个模型需要四步:l 创建瓶子的外形;l 创建瓶子体;l 创建瓶颈上的螺纹;l 合并生成瓶子;2 创建瓶子外形2.1 定义关键点为了创建瓶子的外型,第一步是生成特征点,这些点的坐标位于XOY平面内,如下图所示,用这些点来生成瓶子的几何外形:在Open Cascade中,有两个类来描述3D点的X,Y,Z坐标。l gp_Pnt类l 通过句柄分配一个临时的Geom_CartesianPoint类;句柄就是可以自动分配内存的指针类型。那么到底在应用程序中哪种类合适呢?一般的做法是:l gp_Pnt是按值传递,和其它对象一样,有固定的生命周期;l Geom_CartesianPoint是按句柄分配,可以多次引用,有长的生命周期;由于现在定义的这些点只是在生成瓶子的外形时有用,生命周期有限,因此,选择使用gp_Pnt类。定义一个gp_Pnt对象,只要定义点在世界坐标系的X,Y,Z坐标值就可以了。gp_Pnt aPnt1(-myWidth / 2. , 0 , 0); gp_Pnt aPnt2(-myWidth / 2. , -myThickness / 4. , 0); gp_Pnt aPnt3(0 , -myThickness / 2. , 0); gp_Pnt aPnt4(myWidth / 2. , -myThickness / 4. , 0); gp_Pnt aPnt5(myWidth / 2. , 0 , 0); 如果使用Geom_CartesianPoint类,语法会有点不同,所有对象按句柄分配,需要使用标准C+的new关键字,如下所示:Handle(Geom_CartesianPoint) aPnt1 = new Geom_CartesianPoint(-myWidth / 2. , 0 , 0); 一旦分配了对象,就可以使用它们的方法。再重复一下,语法和C+一样,比如,为了得到一个点的X坐标:gp_Pnt aPnt1(0,0,0); Handle(Geom_CartesianPoint) aPnt2 = new Geom_CartesianPoint(0 , 0 , 0); Standard_Real xValue1 = aPnt1.X(); Standard_Real xValue2 = aPnt2-X(); 2.2 外形轮廓:定义几何体利用前面定义的点,可以计算瓶子几何外形的一部分。如下图所示,它由两个线段和一个圆弧组成。myImageBottle08为了创建这个实体,需要定义一个数据结构,来实现3D几何对象,可以在Open Cascade 的Geom开发包中找到。一个Open Cascade开发包是一组类。这一组类完成的功能相同,或者结构类似,Open Cascade类的前面的名称和包的名称一样,比如,Geom_Line类和Geom_Circle类都属于Geom包。Geom包生成3D几何对象:一般的曲线和多个曲线(比如Bezier和BSpline)所组成的平面.Geom包只提供了几何实体的数据结构。可以直接创建属于Geom包的类。因此,使用GC包中的计算一般曲线和平面的类更容易一些。这是因为在GC包中提供的两个有关计算的类,它对外形计算来说更合适:l GC_MakeSegment类用来创建一个线段。其中一个构造函数是用两个点P1和P2来定义一个线段。l GC_MakeArcOfCircle类创建一个园的一部分(圆弧)。一个非常有用的构造函数是用圆弧的两个端点和所通过的一个点来生成;这些类通过一个句柄返回一个Geom_TrimmedCurve。这个实体表示一个基本的曲线。通过两个参数来限制。比如,一个圆C的参数是0到2PI,如果需要生成一个四分之一圆,在C上应用Geom_TrimmedCurve方法,将值限制为0到PI/2:Handle(Geom_TrimmedCurve) aArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3 ,aPnt4); Handle(Geom_TrimmedCurve) aSegment1 = GC_MakeSegment(aPnt1 , aPnt2); Handle(Geom_TrimmedCurve) aSegment2 = GC_MakeSegment(aPnt4 , aPnt5); 所有的GC类都提供有重载的方法,可以根据不同的函数类型得到相应的结果,可以调用它的IsDone方法,通过返回的值来进行不同处理,这样程序会更安全,比如:GC_MakeSegment mkSeg (aPnt1 , aPnt2); Handle(Geom_TrimmedCurve) aSegment1; if(mkSegment.IsDone() aSegment1 = mkSeg.Value(); . 2.3 外形:定义拓朴结构现在已经创建了外形的一部分,但是这些曲线还是相互独立的,相互间没有任何关系。为了建模方便,需要将这三条曲线生成为一个实体对象。在TopoDS包中,有一个Open Cascade拓朴数据结构,可以使用它来完成:它可以链接一个几何实体到另一个几何实体上,生成复合图形;这个包中的对象,都是从TopeDS_Shape基类继承而来的,下面是各种拓朴图形的描述:图形Open Cascade类描述顶点TopoDS_Vertex零维图形,表示几何体上的一个点边TopoDS_Edge一维图形,表示一个曲线和一个有边界的向量网格TopoDS_Wire由顶点连起来的一系列边面TopoDS_Face由闭合的网格组成的边界平面壳TopoDS_Shell通过边连接起起来一组面体TopoDS_Solid由壳组成的有边界的三维空间复合体TopoDS_CompSolid通过面连接的一组体复合对象TopoDS_Compound由上面各种图形形成的一个集合参考前面的表,可以看出,创建一个外形轮廓,需要生成:l 用前面生成的曲线构建出三条边l 用这些边形成一个网格myImageBottle10TopoDS包中只提供了拓扑实体的数据结构。在BRepBuilderAPI包中,可以找到计算标准拓朴对象的算法类。为了创建一个边,通过前面得出曲线,使用BRepBuilderAPI_MakeEdge类来完成:TopoDS_Edge aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1); TopoDS_Edge aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle); TopoDS_Edge aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2); 在Open CASCADE中,有几种创建边的方法。可以直接通过两点来创建一个边,在这种情况下所生成的边是直线。输入的两个顶点是直线的两个端点。比如:TopoDS_Edge aEdge1 = BRepBuilderAPI_MakeEdge(aPnt1 , aPnt3); TopoDS_Edge aEdge2 = BRepBuilderAPI_MakeEdge(aPnt4 , aPnt5); 可以这样简单地生成边aEdge1和 aEdge3 。为了将边连接起来,需要用BRepBuilderAPI_MakeWire类来生成一个网格。有两种方法:l 直接通过一至四个边来生成;l 在一个现有的网格上添加其它的网格或边(这点在本示例的后面会解释);用低于四个边来生成网格时,可以直接使用下面的构造函数来直接生成:TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(aEdge1 , aEdge2 , aEdge3);2.4外形轮廓:完成外形当创建完网格的第一部分后,接下来需要做的是生成整个外形。比较简单的方法是:1. 通过反射现在的网格生成一个新的网格;2. 添加反射的网格到原来的网格中;myImageBottle12 为了在图形上应用变换,需要使用gp_Trsf类来定义一个3D几何变换属性。这种变换可能是平移、旋转、缩放或反射,或者这几种的组合;现在的情况是,需要定义一个反射,它以世界坐标系下的X轴做为对称轴。轴,可以用gp_Ax1来定义,通过一个点和一个方向(3D单位向量)来生成。定义这个轴有两种方法:l 第一种方法是根据草图,使用几何方法定义:X轴位于(0 , 0 , 0):使用gp_Pnt类X辆的方向是(1 , 0 , 0):使用gp_Dir类,通过它的X,Y,Z坐标来生成一个gp_Dir实例gp_Pnt aOrigin(0 , 0 , 0); gp_Dir xDir(1 , 0 , 0); gp_Ax1 xAxis(aOrigin , xDir); l 第二种也是最简单的方法是直接使用gp包中的几何常量(原点,常用方向及世界坐标系下的坐标轴),得到X轴,可以调用gp:OX方法:gp_Ax1 xAxis = gp:OX();前面说过,可以使用gp_Trsf类来定义一个3D几何变换属性。使用这个类有两种不同的方法:l 根据草图定义一个变换矩阵;l 利用恰当的方法生成所需的变换(平移用SetTranslation(),镜像用SetMirror()等):变换矩阵自动计算完成;一般来说,最简单的总是最好的。使用SetMirror方法,用轴来做为对称中心;gp_Trsf aTrsf; aTrsf.SetMirror(xAxis); 使用BRepBuilderAPI_Transform类来应用所定义的变换。 至此,所需的要数据都已准备完成:l 要应用变换的图形l 几何变换BRepBuilderAPI_Transform aBRepTrsf(aWire , aTrsf);BRepBuilderAPI_Transform并不修改原来的图形:反射生成的网格仍是一个网格。但是调用类似BRepBuilderAPI_Transform:Shape这样的方法会返回一个TopoDS_Shape对象:TopoDS_Shape aMirroredShape = aBRepTrsf.Shape();假如需要反射后的结果也是一个网格。TopoDS全局函数提供生成一个图形为它的实际类型的方法。为了生成经过变换的网格,可以使用TopoDS:Wire方法;TopoDS_Wire aMirroredWire = TopoDS:Wire(aMirroredShape);瓶子的外形快完成了。已经创建了两个网格:一个网格和一个反射网格。现在要做的是把它们合成为一个单一的图形。可以使用BRepBuilderAPI_MakeWire类来做这点:a) 创建一个BRepBuilderAPI_MakeWire实例对象b) 使用Add方法将两个网格的所有边都添加到此对象上。BRepBuilderAPI_MakeWire mkWire; mkWire.Add(aWire); mkWire.Add(aMirroredWire); TopoDS_Wire myWireProfile = mkWire.Wire();创建瓶体3.1 轮廓体为了生成瓶子的瓶体。需要生成一个实体图形,最简单的方法是使用前面创建的外形并沿着一个方向进行推移:Open CASCADE 的实体函数非常适合实现它。它接受一个图形和一个方向为输入参数;然后生成一个图形,生成的规则如下:图形生成顶点边边面网格壳面体壳复合的实体现在的外形是一个网格。参考图形/生成表。利用网格面可以生成体;为了生成面,可以使用BRepBuilderAPI_MakeFace类。前面说过,面是由封闭的网格生成的有边界表面。通常,面可以由一个表面和一个或多个网格通过BRepBuilderAPI_MakeFace来生成。如果网格位于一个平面内,表面会自动生成:TopoDS_Face myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile); 在BRepPrimAPI包中提供了一些类,用来生成具有拓朴结构的图元:长方体、园环、园柱、球等。都位于BRepPrimAPI_MakePrism类中,按照上面所说,这个类要由这些来定义:l 推移所用的基本图形l 有一定长度的向量或有一定长度的方向,或者无限长;现在需要的是有一定长度的实体,沿着Z轴推移myHeight大小的高度。这个向量,可以由gp_Vec类来定义它的X,Y,Z坐标值:gp_Vec aPrismVec(0 , 0 , myHeight); 所有生成瓶体的数据现在都准备好了,下面所做的只是用BRepPrimAPI_MakePrism类来生成实体:TopoDS_Shape myBody = BRepPrimAPI_MakePrism(myFaceProfile , aPrismVec);3.2 园角生成的瓶体,边角比较锐利,要用圆滑的面打钝它。可以使用在Open CASCADE中的园角功能;根据位置的不同,园角实现方法也不同,比如,可以沿着一条直线,或者沿着边缘线来计算。我们的目的是,用简单的方法来生成园角,约定:l 在图形的所有边上做园角l 园角的半径值为myThickness/12;为了生成一个边的园角,可以使用BRepFilletAPI_MakeFillet类,这个类的一般用法是:1. 在BRepFilletAPI_MakeFillet 的构造函数中传入需要园角的图形;2. 应用Add方法,同时加入园角的参数值(要加入的边和半径),在这里,要加入所有需园角的边;3. 使用Shape方法得到园角后的图形;BRepFilletAPI_MakeFillet mkFillet(myBody); 为了添加园角的说明,需要知道图形都有哪些边。最好的解决方法是遍历实体的所有边。可以用TopExp_Explorer类来完成。要遍历的数据结构定义是在TopoDS_Shape中,可以根据需要扩展子图形;一般来说,要遍历的话,要提供下面的内容:l 要遍历的图形l 要找的子图形的类型。可以用TopAbs_ShapeEnum枚举结构体来定义它。TopExp_Explorer aEdgeExplorer(myBody , TopAbs_EDGE); 应用一个遍历循环过程中主要用到三个方法:l 是否还有子图形要遍历;l 得到当前要遍历的子图形;l 得到下一个要遍历的子图形( 如果More()方法返回的结果为真);while(aEdgeExplorer.More() TopoDS_Edge aEdge = TopoDS:Edge(aEdgeExplorer.Current(); /Add edge to fillet algorithm . aEdgeExplorer.Next(); 在遍历循环中,找瓶子图形的所有边。每个边都用Add方法添加到BRepFilletAPI_MakeFillet实例中。记住,要把要园角的半径值也传进去;mkFillet.Add(myThickness / 12. , aEdge); 一旦完成,最后一步是得到园角后的图形:myBody = mkFillet.Shape();3.3添加瓶颈要添加瓶颈,需生成一个园柱并把它焊到瓶体上;园柱的位置在瓶体的顶面,半径设定myThickness/4,高度设定myHeight/10。gp_Pnt neckLocation(0 , 0 , myHeight); gp_Dir neckNormal = gp:DZ(); gp_Ax2 neckAx2(neckLocation , neckNormal); 为了定位园柱,要用gp_Ax2类来定义一个右手坐标系,这个坐标系可以由一个点和两个方向来定义,这两个方向分别是法线方向和轴方向,轴方向可以由这两个方向计算得出。瓶子体上面的中心,在世界坐标系中的坐标是(0,0,myHeight),法线是轴。所以,局部坐标系可以这们定义:gp_Pnt neckLocation(0 , 0 , myHeight); gp_Dir neckNormal = gp:DZ(); gp_Ax2 neckAx2(neckLocation , neckNormal); 为了生成园柱,要用图元包中的另一个类:BRepPrimAPI_MakeCylinder类。需要提供以下内容:l 园柱所在的坐标系;l 园柱的半径和高度;Standard_Real myNeckRadius = myThickness / 4.;Standard_Real myNeckHeight = myHeight / 10;TopoDS_Shape myNeck = BRepPrimAPI_MakeCylinder(neckAx2 , myNeckRadius , myNeckHeight); 现在有了两部分,瓶子体和要焊上去的瓶颈;在BRepAlgoAPI包中提供了对两个图形布尔操作的方法:共同(布尔交),切(布尔减),焊(布尔并);使用BRepAlgoAPI_Fuse可以把两个图形焊在一起:myBody = BRepAlgoAPI_Fuse(myBody , myNeck);3.4创建镂空实体实际的瓶子都是用来装液体的,现在要从瓶子顶面生成一个镂空的实体;在Open CASCADE中,一个镂空的实体称为一个有厚度的体,生成步骤:1. 从初始的实体中移除一个或多个面得到第一个镂空实体的面;2. 生成一个平行于的面,两个面之间的距离是,如果为正,则在初始实体的外面,否则在里面;3. 通过和生成实体;for(TopExp_Explorer aFaceExplorer(myBody , TopAbs_FACE) ; aFaceExplorer.More() ; aFaceExplorer.Next() TopoDS_Face aFace = TopoDS:Face(aFaceExplorer.Current(); TopoDS_Face aFace = TopoDS:Face(aFaceExplorer.Current(); 为了生成一个有厚度的实体,可以生成一个BRepOffsetAPI_MakeThickSolid类的实例,给它传递以下值:l 要镂空的图形l 需要计算的公差l 两个面和之间的厚度(距离)l 从原始的实体中移除面而生成的第一个面;这一步最不好做的是从图形中找到要移除的面:瓶颈园柱体的顶面;这个面:l 在几何体上的一个平面;l 瓶子上的最高的面(按轴来说);有了这个面的这些特征,可以再次遍历瓶子的所有面并找到这个面:for(TopExp_Explorer aFaceExplorer(myBody , TopAbs_FACE) ; aFaceExplorer.More() ; aFaceExplorer.Next() TopoDS_Face aFace = TopoDS:Face(aFaceExplorer.Current(); TopoDS_Face aFace = TopoDS:Face(aFaceExplorer.Current(); 为了检测每个面,需要找到它的表面。有一个工具类可以处理图形的几何属性:BRep_Tool类,这个类常见的用法有:l 对于表面:可以处理表面上的面;l 对于曲线:可以处理曲线上的边;l 对于向量:可以处理向量上的点;Handle(Geom_Surface) aSurface = BRep_Tool:Surface(aFace); 可以看出,BRep_Tool:Surface方法返回一个Geom_Surface类的实例,这个实例是通过句柄分配;但是,Geom_Surface类并不提供aSurface对象的实际类型的信息,这个引用的类型可能是Geom_Plane,Geom_CylindricalSurface等;类似Geom_Surface,所有的对象是通过句柄分配,这些对象是从Standard_Transient派生出来的。在这里与类型相关的两个有用的方法是:l DynamicType方法:可以得出对象的实际类型;l IsKind方法:可以计算一个对象是否是从某种类型派生出来的;DynamicType方法返回对象的实际类型,但是要用它和已知类型比较来得出aSurface是一个平面,还是一个园柱侧面或其它类型;为了用所给定的类型和要找的类型相比较,可以使用STANDARD_TYPE宏。这个宏返回一个类的类型;if(aSurface-DynamicType() = STANDARD_TY

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论