OCCT 学习笔记:创建瓶子教程的三个关键知识点

server/2025/3/6 21:47:50/

对OCCT已经有了多年了解,但时不时还是要翻一翻它的官方文档。今天重读了:Bottle Tutorial

教程概况

在这里插入图片描述
这篇教程文档围绕使用Open CASCADE Technology进行3D建模展开,以创建一个瓶子模型为例,逐步介绍建模过程及相关技术要点,主要内容如下:

  1. 教程概述
    • 目的:教会读者使用Open CASCADE Technology服务对3D对象建模,帮助读者将其作为工具来思考和应用,并非介绍所有类。
    • 前提条件:假定读者具备C++使用和设置经验,Open CASCADE Technology旨在增强C++的3D建模能力。
  2. 模型规格:定义了瓶子的关键参数,包括高度(70mm)、宽度(50mm)、厚度(30mm),且瓶子轮廓(底部)以全局笛卡尔坐标系原点为中心。
  3. 建模步骤
    • 构建轮廓:先定义支撑点,选用gp_Pnt类创建点对象;接着利用这些点计算轮廓几何,涉及线段和圆弧;再通过TopoDS和BRepBuilderAPI等相关类构建拓扑结构;最后通过反射现有导线并合并的方式完成轮廓。
    • 构建瓶身:使用BRepBuilderAPI_MakeFace和BRepPrimAPI_MakePrism类将轮廓拉伸为实体;利用BRepFilletAPI_MakeFillet类对边缘倒圆角;通过创建圆柱体并与瓶身融合添加瓶颈;借助BRepOffsetAPI_MakeThickSolid类创建空心实体。
    • 构建螺纹:计算两个不同半径的圆柱面;在圆柱面的参数化空间定义2D曲线,包括椭圆弧和线段;使用BRepBuilderAPI_MakeEdge和BRepBuilderAPI_MakeWire类构建边缘和导线;调用BRepLib::BuildCurves3d方法计算3D曲线,通过BRepOffsetAPI_ThruSections类创建螺纹实体。
    • 构建最终组合体:运用TopoDS_Compound和BRep_Builder类将瓶身和螺纹组合成单一形状,完成瓶子建模。
  4. 附录:给出了MakeBottle函数的完整定义,展示了整个建模过程在代码层面的实现细节。

关键知识点

几何和拓扑

在OCC中,几何和拓扑经常成对出现。例如:

    // Profile : Define the GeometryHandle(Geom_TrimmedCurve) anArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3,aPnt4);Handle(Geom_TrimmedCurve) aSegment1 = GC_MakeSegment(aPnt1, aPnt2);Handle(Geom_TrimmedCurve) aSegment2 = GC_MakeSegment(aPnt4, aPnt5);// Profile : Define the TopologyTopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(aSegment1);TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(anArcOfCircle);TopoDS_Edge anEdge3 = BRepBuilderAPI_MakeEdge(aSegment2);TopoDS_Wire aWire  = BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3);

OpenCasCade是一个开源的CAD/CAM/CAE几何建模内核,它广泛应用于各种工业设计和工程领域。在OpenCasCade中,几何(Geometry)和拓扑(Topology)是两个核心概念,它们紧密相关且相互协作,共同构成了复杂的三维模型表示。以下从基本概念、相互关系和协同工作机制几个方面介绍它们的关系:

基本概念

  • 几何:几何主要关注的是物体的形状和尺寸等数学描述。在OpenCasCade中,几何元素由精确的数学方程定义,用于表示点、线、面、体等基本形状。例如,一个点可以用三维空间中的坐标 ( x , y , z ) (x, y, z) (x,y,z) 来表示;一条直线可以用线性方程描述;一个平面可以用平面方程表示;而像圆柱、圆锥等复杂曲面则由更复杂的数学函数来定义。几何元素提供了模型的精确几何信息,是构建模型的基础。
  • 拓扑:拓扑关注的是几何元素之间的连接关系和相对位置,而不考虑具体的形状和尺寸。OpenCasCade中的拓扑元素包括顶点(Vertex)、边(Edge)、面(Face)、壳(Shell)、体(Solid)等。例如,一个边连接两个顶点,一个面由多条边围成,一个体由多个面组成。拓扑结构定义了几何元素之间的邻接关系和层次结构,它描述了模型的整体结构和组织方式。

相互关系

  • 拓扑依赖于几何:拓扑元素需要基于几何元素来定义其具体形状。例如,一个拓扑边(TopoDS_Edge)必须依赖于一个几何曲线(如Geom_Line、Geom_Circle等)来确定其在空间中的形状和位置。没有几何曲线的支持,拓扑边就只是一个抽象的连接关系,没有实际的形状。同样,一个拓扑面(TopoDS_Face)需要基于一个几何曲面(如Geom_Plane、Geom_CylindricalSurface等)来定义其表面形状。
  • 几何通过拓扑组织:几何元素通过拓扑结构进行组织和管理,形成复杂的三维模型。拓扑结构为几何元素提供了一种结构化的表示方式,使得可以方便地对模型进行操作和分析。例如,通过拓扑结构可以快速找到与某个面相邻的其他面,或者找到组成一个体的所有面。这种组织方式使得模型的构建、修改和查询更加高效和灵活。

协同工作机制

  • 模型构建:在创建三维模型时,首先需要定义几何元素,如点、线、面等,然后通过拓扑结构将这些几何元素组合起来。例如,要创建一个立方体,需要先定义六个平面作为几何元素,然后通过拓扑结构将这些平面连接起来,形成一个封闭的体。在OpenCasCade中,可以使用各种API来完成这些操作,如BRepBuilderAPI_MakeEdge用于创建拓扑边,BRepBuilderAPI_MakeFace用于创建拓扑面,BRepPrimAPI_MakeBox用于创建立方体等基本体素。
  • 模型操作:在对模型进行操作(如平移、旋转、缩放、布尔运算等)时,几何和拓扑需要协同工作。例如,在进行布尔运算(如并、交、差)时,不仅要对几何形状进行计算,还要更新拓扑结构以反映新的连接关系。OpenCasCade提供了一系列的算法和工具来处理这些操作,确保几何和拓扑的一致性。
  • 模型分析:在对模型进行分析(如计算体积、表面积、曲率等)时,需要同时利用几何和拓扑信息。例如,计算一个体的体积需要知道其表面的几何形状和拓扑结构,通过对各个面的积分来得到体积值。OpenCasCade提供了各种分析工具和算法,利用几何和拓扑信息来完成这些计算任务。

示例代码说明

以下是一个简单的OpenCasCade代码示例,展示了如何创建一个简单的拓扑边并关联几何曲线:

#include <gp_Pnt.hxx>
#include <GC_MakeSegment.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <TopoDS_Edge.hxx>int main() {// 定义两个点作为几何信息gp_Pnt p1(0, 0, 0);gp_Pnt p2(10, 0, 0);// 创建一个几何线段Handle(Geom_TrimmedCurve) segment = GC_MakeSegment(p1, p2);// 基于几何线段创建一个拓扑边BRepBuilderAPI_MakeEdge edgeBuilder(segment);TopoDS_Edge edge = edgeBuilder.Edge();return 0;
}

在这个示例中,首先定义了两个点 p1p2,然后使用 GC_MakeSegment 创建了一个几何线段。接着,使用 BRepBuilderAPI_MakeEdge 基于这个几何线段创建了一个拓扑边。这体现了几何和拓扑的紧密结合,几何为拓扑提供了具体的形状信息,而拓扑则将几何元素组织成有意义的结构。

拓扑数据结构的遍历

在 OpenCasCade 这个开源的 CAD/CAM/CAE 几何建模内核中,TopExp_Explorer 类是一个非常重要的工具,主要用于遍历拓扑数据结构中的元素。下面将从其功能、成员函数、工作原理以及使用示例等方面进行详细介绍。

功能概述

TopExp_Explorer 类的核心功能是对 OpenCasCade 中的拓扑数据结构(如 TopoDS_Shape 及其派生类)进行遍历操作。通过该类,可以方便地访问拓扑形状中的各种拓扑元素,例如顶点(TopAbs_VERTEX)、边(TopAbs_EDGE)、面(TopAbs_FACE)等,这在模型分析、修改以及布尔运算等操作中非常有用。

成员函数

  • 构造函数
    • TopExp_Explorer(const TopoDS_Shape& S, const TopAbs_ShapeEnum ToFind, const TopAbs_ShapeEnum ToAvoid = TopAbs_SHAPE):初始化一个 TopExp_Explorer 对象,用于遍历形状 S 中类型为 ToFind 的拓扑元素,同时可以选择跳过类型为 ToAvoid 的元素。
  • 遍历控制函数
    • Standard_Boolean More():检查是否还有更多的元素可供遍历。如果还有未访问的元素,返回 Standard_True;否则返回 Standard_False
    • void Next():将迭代器移动到下一个元素。
  • 元素访问函数
    • const TopoDS_Shape& Current():返回当前正在访问的拓扑元素。

工作原理

TopExp_Explorer 类通过维护一个内部的迭代器来实现对拓扑形状的遍历。当创建 TopExp_Explorer 对象时,它会根据指定的形状和要查找的元素类型进行初始化。在调用 More() 函数时,它会检查是否还有未访问的元素;调用 Next() 函数时,迭代器会移动到下一个元素;而 Current() 函数则返回当前迭代器指向的元素。

使用示例

以下是一个简单的示例,展示了如何使用 TopExp_Explorer 类来遍历一个拓扑形状中的所有边:

#include <TopoDS_Shape.hxx>
#include <TopExp_Explorer.hxx>
#include <TopAbs_ShapeEnum.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <iostream>int main() {// 创建一个立方体形状BRepPrimAPI_MakeBox boxMaker(10.0, 10.0, 10.0);TopoDS_Shape box = boxMaker.Shape();// 创建一个 TopExp_Explorer 对象,用于遍历立方体中的所有边TopExp_Explorer edgeExplorer(box, TopAbs_EDGE);// 遍历所有边并输出边的数量int edgeCount = 0;for (; edgeExplorer.More(); edgeExplorer.Next()) {// 获取当前边const TopoDS_Shape& currentEdge = edgeExplorer.Current();edgeCount++;}std::cout << "The number of edges in the box is: " << edgeCount << std::endl;return 0;
}

代码解释

  1. 创建拓扑形状:使用 BRepPrimAPI_MakeBox 类创建一个立方体形状。
  2. 初始化 TopExp_Explorer 对象:创建一个 TopExp_Explorer 对象 edgeExplorer,指定要遍历的形状为立方体 box,要查找的元素类型为 TopAbs_EDGE(即边)。
  3. 遍历拓扑元素:使用 for 循环结合 More()Next() 函数遍历立方体中的所有边。在每次循环中,使用 Current() 函数获取当前正在访问的边。
  4. 输出结果:统计边的数量并输出。

通过这个示例,可以看到 TopExp_Explorer 类提供了一种简单而有效的方式来遍历拓扑形状中的元素,方便进行各种拓扑分析和操作。

创建螺旋线720度

这里的重点是如何创建720度的螺旋线。先看看官方的代码,然后逐行解释,最后是关键点的分析。

    myBody = aSolidMaker.Shape();// Threading : Create SurfacesHandle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99);Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 1.05);// Threading : Define 2D Curvesgp_Pnt2d aPnt(2. * M_PI, myNeckHeight / 2.);gp_Dir2d aDir(2. * M_PI, myNeckHeight / 4.);gp_Ax2d anAx2d(aPnt, aDir);Standard_Real aMajor = 2. * M_PI;Standard_Real aMinor = myNeckHeight / 10;Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4);Handle(Geom2d_TrimmedCurve) anArc1 = new Geom2d_TrimmedCurve(anEllipse1, 0, M_PI);Handle(Geom2d_TrimmedCurve) anArc2 = new Geom2d_TrimmedCurve(anEllipse2, 0, M_PI);gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0);gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(M_PI);Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2);// Threading : Build Edges and WiresTopoDS_Edge anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1);TopoDS_Edge anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment, aCyl1);TopoDS_Edge anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(anArc2, aCyl2);TopoDS_Edge anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment, aCyl2);TopoDS_Wire threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1, anEdge2OnSurf1);TopoDS_Wire threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2, anEdge2OnSurf2);BRepLib::BuildCurves3d(threadingWire1);BRepLib::BuildCurves3d(threadingWire2);// Create Threading BRepOffsetAPI_ThruSections aTool(Standard_True);aTool.AddWire(threadingWire1);aTool.AddWire(threadingWire2);aTool.CheckCompatibility(Standard_False);TopoDS_Shape myThreading = aTool.Shape();

代码注释

对上面的代码进行解释。

1. 获取瓶身实体
myBody = aSolidMaker.Shape();

这行代码的作用是从 aSolidMaker 对象中获取最终的瓶身实体形状,并将其赋值给 myBody 变量。aSolidMaker 通常是之前用于构建瓶身的操作对象,比如可能是通过拉伸、布尔运算等操作来创建瓶身的类实例。

2. 创建螺纹所需的圆柱面
Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99);
Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 1.05);
  • 这里创建了两个 Geom_CylindricalSurface 类型的圆柱面对象 aCyl1aCyl2
  • neckAx2 是一个 gp_Ax2 类型的对象,它定义了圆柱面的位置和方向(轴)。
  • myNeckRadius 是瓶颈的半径,aCyl1 的半径为 myNeckRadius * 0.99aCyl2 的半径为 myNeckRadius * 1.05,这两个不同半径的圆柱面将用于后续定义螺纹的内外边界。
3. 定义二维曲线
gp_Pnt2d aPnt(2. * M_PI, myNeckHeight / 2.);
gp_Dir2d aDir(2. * M_PI, myNeckHeight / 4.);
gp_Ax2d anAx2d(aPnt, aDir);Standard_Real aMajor = 2. * M_PI;
Standard_Real aMinor = myNeckHeight / 10;Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);
Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4);
Handle(Geom2d_TrimmedCurve) anArc1 = new Geom2d_TrimmedCurve(anEllipse1, 0, M_PI);
Handle(Geom2d_TrimmedCurve) anArc2 = new Geom2d_TrimmedCurve(anEllipse2, 0, M_PI);
gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0);
gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(M_PI);Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2);
  • 定义局部坐标系
    • gp_Pnt2d aPnt(2. * M_PI, myNeckHeight / 2.); 定义了一个二维点 aPnt,作为局部坐标系的原点。
    • gp_Dir2d aDir(2. * M_PI, myNeckHeight / 4.); 定义了一个二维方向 aDir
    • gp_Ax2d anAx2d(aPnt, aDir); 基于上述点和方向创建了一个二维坐标系 anAx2d
  • 创建椭圆曲线
    • aMajoraMinor 分别表示椭圆的长半轴和短半轴。
    • anEllipse1anEllipse2 是两个不同短半轴的椭圆曲线,它们都基于 anAx2d 坐标系。
  • 截取椭圆弧
    • anArc1anArc2 分别是从 anEllipse1anEllipse2 上截取的 0 到 π \pi π 范围内的椭圆弧。
  • 创建线段
    • anEllipsePnt1anEllipsePnt2anEllipse1 上参数为 0 和 π \pi π 的点。
    • aSegment 是连接这两个点的线段。
4. 构建边缘和导线
TopoDS_Edge anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1);
TopoDS_Edge anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment, aCyl1);
TopoDS_Edge anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(anArc2, aCyl2);
TopoDS_Edge anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment, aCyl2);
TopoDS_Wire threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1, anEdge2OnSurf1);
TopoDS_Wire threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2, anEdge2OnSurf2);
BRepLib::BuildCurves3d(threadingWire1);
BRepLib::BuildCurves3d(threadingWire2);
  • 创建边缘
    • BRepBuilderAPI_MakeEdge 用于将二维曲线(如椭圆弧和线段)映射到三维圆柱面上,创建对应的拓扑边缘。例如,anEdge1OnSurf1 是将椭圆弧 anArc1 映射到圆柱面 aCyl1 上得到的边缘。
  • 创建导线
    • BRepBuilderAPI_MakeWire 用于将多个边缘组合成一个导线。threadingWire1threadingWire2 分别是由两个边缘组合而成的导线。
  • 计算三维曲线
    • BRepLib::BuildCurves3d 用于为导线中的边缘计算三维曲线,确保导线在三维空间中有明确的几何表示。
5. 创建螺纹实体
BRepOffsetAPI_ThruSections aTool(Standard_True);
aTool.AddWire(threadingWire1);
aTool.AddWire(threadingWire2);
aTool.CheckCompatibility(Standard_False);TopoDS_Shape myThreading = aTool.Shape();
  • 创建放样工具
    • BRepOffsetAPI_ThruSections 是一个用于通过一系列导线创建实体的工具类,Standard_True 表示创建封闭的实体。
  • 添加导线
    • aTool.AddWire(threadingWire1)aTool.AddWire(threadingWire2) 将之前创建的两个导线添加到放样工具中。
  • 检查兼容性
    • aTool.CheckCompatibility(Standard_False) 表示不进行导线之间的兼容性检查。
  • 获取螺纹实体
    • aTool.Shape() 调用工具类的 Shape 方法,生成最终的螺纹实体,并将其赋值给 myThreading 变量。

综上所述,这段代码通过创建圆柱面、定义二维曲线、构建边缘和导线,最后使用放样工具创建了瓶子瓶颈部分的螺纹实体。

720度

在这里插入图片描述
圆柱面本身展开是360度的,也就是2PI,但圆柱面本身是无穷的,或者说越过了2PI,就又从0开始了。上面这个二维空间需要一定的想象能力,是把圆柱展开了两次。
在这里插入图片描述
在这个二维空间进行绘制的结果如上图,代码如下:

    Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);Handle(Geom2d_TrimmedCurve) anArc1 = new Geom2d_TrimmedCurve(anEllipse1, 0, M_PI);gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0);gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(M_PI);Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2);

在这里插入图片描述
把上述二维的线投到圆柱面的结果如上图所示,代码如下:

    // Threading : Build Edges and WiresTopoDS_Edge anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1);TopoDS_Edge anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment, aCyl1);TopoDS_Wire threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1, anEdge2OnSurf1);BRepLib::BuildCurves3d(threadingWire1);

http://www.ppmy.cn/server/172981.html

相关文章

STL——stack与queue的介绍及模拟实现

目录 前言 stack与queue 容器适配器 deque的介绍 deque的底层 deque的接口 stack和queue的实现 stack模拟实现 queue模拟实现 小结 前言 前面我们介绍了那个库里面的链表以及顺序表两个容器&#xff0c;通过这两个容器作为底层&#xff0c;我们可以去实现一些其他的数…

飞机大战lua迷你世界脚本

-- 迷你世界飞机大战 v1.2 -- 星空露珠工作室制作 -- 最后更新&#xff1a;2024年1月 ----------------------------- -- 迷你世界API适配配置 ----------------------------- local UI { BASE_ID 7477478487091949474-22856, -- UI界面ID ELEMENTS { BG 1, -- 背景 BTN_LE…

C/C++ | 每日一练 (5)

&#x1f4a2;欢迎来到张胤尘的技术站 &#x1f4a5;技术如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 C/C | 每日一练 (5)题目参考答案引用引用和指针的区别…

3-7 WPS JS宏 工作表移动复制实例-2(多工作簿的多工作表合并)学习笔记

************************************************************************************************************** 点击进入 -我要自学网-国内领先的专业视频教程学习网站 *******************************************************************************************…

STM32-智能小车项目

项目框图 ST-link接线 实物图&#xff1a; 正面&#xff1a; 反面&#xff1a; 相关内容 使用L9110S电机模块 电机驱动模块L9110S详解 | 良许嵌入式 测速模块 语音模块SU-03T 网站&#xff1a;智能公元/AI产品零代码平台 一、让小车动起来 新建文件夹智能小车项目 在里面…

【华为OD机考】华为OD笔试真题解析(20)--投篮大赛

题目描述 你现在是一场采用特殊赛制投篮大赛的记录员。这场比赛由若干回合组成&#xff0c;过去几回合的得分可能会影响以后几回合的得分。 比赛开始时&#xff0c;记录是空白的&#xff0c;你会得到一个记录操作的字符串列表ops&#xff0c;其中ops[i]是你需要记录的第i项操…

1分钟从零开始搭建机器人管理系统(WindSurf)

1. 软件安装 可以直接安装作为IDE或者作为插件到其它IDE https://codeium.com/download 对话方式构建系统&#xff08;可以更换Claude 3.7、DeepSeek R1等模型&#xff09; 创建一个BS架构的机器人远程操控系统&#xff0c;具备机器人状态及位置实时更新&#xff0c;可以实…

前端实现word文档的生成和下载

一 前提 应项目需求&#xff0c;需要把前端生成word文档并下载。此项目我使用的是vue框架。本篇文章主要是记录自己在实现中遇到的问题以及最终使用方式。 二 实现方式 我的方式是将 html 转为word文档并下载。现在网上最常见的是使用 html-docx-js 配合 file-saver 使用…