OCCT-Tutorials_and_Demos_03:Novice_Guide
Tutorials and Demos 03
Modeling: Bottle Tutorials
原文链接: https://dev.opencascade.org/doc/overview/html/occt__tutorial.html
Overview 概述
This tutorial will teach you how to use Open CASCADE Technology services to model a 3D object. The purpose of this tutorial is not to describe all Open CASCADE Technology classes but to help you start thinking in terms of Open CASCADE Technology as a tool.
本教程将教您如何使用OpenCASCADE技术服务来建模3D对象。本教程的目的不是描述所有开放式CASCADE技术类,而是帮助您开始将开放式CASCADE技术作为一种工具进行思考。
Prerequisites 先决条件
This tutorial assumes that you have experience in using and setting up C++. From a programming standpoint, Open CASCADE Technology is designed to enhance your C++ tools with 3D modeling classes, methods and functions. The combination of all these resources will allow you to create substantial applications.
本教程假定您具有使用和设置C的经验。从编程的角度来看,OpenCASCADE技术旨在通过3D建模类、方法和函数来增强C工具。所有这些资源的组合将允许您创建大量应用程序。
The Model 模型
To illustrate the use of classes provided in the 3D geometric modeling toolkits, you will create a bottle as shown:
为了说明3D几何建模工具包中提供的类的使用,您将创建一个瓶子,如下所示:
In the tutorial we will create, step-by-step, a function that will model a bottle as shown above. You will find the complete source code of this tutorial, including the very function MakeBottle in the distribution of Open CASCADE Technology. The function body is provided in the file samples/qt/Tutorial/src/MakeBottle.cxx.
在本教程中,我们将逐步创建一个函数,该函数将对如上所示的瓶子进行建模。您将找到本教程的完整源代码,包括OpenCASCADETechnology发行版中的MakeBottle函数。函数体在文件samples/qt/Tutorial/src/MakeBottle.cxx中提供。
Model Specifications 型号规格
We first define the bottle specifications as follows:
我们首先定义瓶子规格如下:
Object Parameter 对象参数 | Parameter Name 参数名称 | Parameter Value 参数值 |
---|---|---|
Bottle height | MyHeight | 70mm |
Bottle width | MyWidth | 50mm |
Bottle thickness | MyThickness | 30mm |
In addition, we decide that the bottle’s profile (base) will be centered on the origin of the global Cartesian coordinate system.
此外,我们决定瓶子的轮廓(底部)将以全局笛卡尔坐标系的原点为中心。
This modeling requires four steps:
- build the bottle’s Profile
- build the bottle’s Body
- build the Threading on the bottle’s neck
- build the result compound
该建模需要四个步骤:
- 建立瓶子的轮廓
- 打造瓶身
- 在瓶子的颈部建立螺纹
- 构建结果复合
Building the Profile
Defining Support Points 定义支持点
To create the bottle’s profile, you first create characteristic points with their coordinates as shown below in the (XOY) plane. These points will be the supports that define the geometry of the profile.
要创建瓶子的轮廓,首先要在(XOY)平面中创建特征点及其坐标,如下所示。这些点将是定义轮廓几何图形的支撑。
There are two classes to describe a 3D Cartesian point from its X, Y and Z coordinates in Open CASCADE Technology:
- the primitive geometric gp_Pnt class
- the transient Geom_CartesianPoint class manipulated by handle
在OpenCASCADE技术中,有两个类可以从X、Y和Z坐标描述三维笛卡尔点:
- 原始几何gp_Pnt类
- 由handle操纵的瞬时Geom_CartesianPoint类
A handle is a type of smart pointer that provides automatic memory management. To choose the best class for this application, consider the following:
- gp_Pnt is manipulated by value. Like all objects of its kind, it will have a limited lifetime.
- Geom_CartesianPoint is manipulated by handle and may have multiple references and a long lifetime.
句柄是一种提供自动内存管理的智能指针。要为此应用程序选择最佳类别,请考虑以下事项:
- gp_Pnt由值操纵。像所有同类物体一样,它的寿命有限。
- Geom_CartesianPoint由句柄操纵,可能具有多个引用和较长的使用寿命。
Since all the points you will define are only used to create the profile’s curves, an object with a limited lifetime will do. Choose the gp_Pnt class. To instantiate a gp_Pnt object, just specify the X, Y, and Z coordinates of the points in the global Cartesian coordinate system:
由于您将定义的所有点仅用于创建轮廓的曲线,因此使用寿命有限的对象即可。选择gp_Pnt类。要实例化gp_Pnt对象,只需指定全局笛卡尔坐标系中点的X、Y和Z坐标:
1 | gp_Pnt aPnt1(-myWidth / 2., 0, 0); |
Once your objects are instantiated, you can use methods provided by the class to access and modify its data. For example, to get the X coordinate of a point:
对象实例化后,可以使用类提供的方法访问和修改其数据。例如,要获取点的X坐标:
1 | Standard_Real xValue1 = aPnt1.X(); |
Profile: Defining the Geometry 纵断面:定义几何图形
With the help of the previously defined points, you can compute a part of the bottle’s profile geometry. As shown in the figure below, it will consist of two segments and one arc.
借助先前定义的点,可以计算瓶子轮廓几何图形的一部分。如下图所示,它将由两段和一段弧组成。
To create such entities, you need a specific data structure, which implements 3D geometric objects. This can be found in the Geom package of Open CASCADE Technology. In Open CASCADE Technology a package is a group of classes providing related functionality. The classes have names that start with the name of a package they belong to. For example, Geom_Line and Geom_Circle classes belong to the Geom package. The Geom package implements 3D geometric objects: elementary curves and surfaces are provided as well as more complex ones (such as Bezier and BSpline). However, the Geom package provides only the data structure of geometric entities. You can directly instantiate classes belonging to Geom, but it is easier to compute elementary curves and surfaces by using the GC package. This is because the GC provides two algorithm classes which are exactly what is required for our profile:
要创建这样的实体,需要一个特定的数据结构,它实现了三维几何对象。这可以在Open CASCADE Technology的Geom包中找到。在开放式CASCADE技术中,包是一组提供相关功能的类。类的名称以所属包的名称开头。例如,Geom_Line和Geom_Circle类属于Geom包。Geom包实现了三维几何对象:提供了基本曲线和曲面以及更复杂的曲线和曲面(如Bezier和BSpline)。然而,Geom包仅提供几何实体的数据结构。您可以直接实例化属于Geom的类,但使用GC包可以更容易地计算基本曲线和曲面。这是因为GC提供了两个算法类,这正是我们的配置文件所需的:
-
Class GC_MakeSegment to create a segment. One of its constructors allows you to define a segment by two end points P1 and P2
-
Class GC_MakeArcOfCircle to create an arc of a circle. A useful constructor creates an arc from two end points P1 and P3 and going through P2.
-
类GC_MakeSegment以创建段。它的一个构造函数允许您通过两个端点P1和P2定义线段
-
类GC_MakeArcOfCircle以创建圆弧。一个有用的构造器从两个端点P1和P3创建一条弧,并穿过P2。
Both of these classes return a Geom_TrimmedCurve manipulated by handle. This entity represents a base curve (line or circle, in our case), limited between two of its parameter values. For example, circle C is parameterized between 0 and 2PI. If you need to create a quarter of a circle, you create a Geom_TrimmedCurve on C limited between 0 and M_PI/2.
这两个类都返回由句柄操纵的Geom_TrimedCurve。该实体表示一条基本曲线(在本例中为直线或圆),限制在两个参数值之间。例如,圆C在0和2PI之间被参数化。如果需要创建四分之一的圆,可以在C上创建限制在0和M_PI/2之间的Geom_TrimedCurve。
1 | Handle(Geom_TrimmedCurve) aArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3,aPnt4); |
All GC classes provide a casting method to obtain a result automatically with a function-like call. Note that this method will raise an exception if construction has failed. To handle possible errors more explicitly, you may use the IsDone and Value methods. For example:
所有GC类都提供了一个强制转换方法,通过类似函数的调用自动获得结果。请注意,如果构造失败,此方法将引发异常。为了更明确地处理可能的错误,可以使用IsDone和Value方法。例如:
1 | GC_MakeSegment mkSeg (aPnt1, aPnt2); |
Profile: Defining the Topology
You have created the support geometry of one part of the profile but these curves are independent with no relations between each other. To simplify the modeling, it would be right to manipulate these three curves as a single entity. This can be done by using the topological data structure of Open CASCADE Technology defined in the TopoDS package: it defines relationships between geometric entities which can be linked together to represent complex shapes. Each object of the TopoDS package, inheriting from the TopoDS_Shape class, describes a topological shape as described below:
您已经创建了轮廓的一部分的支撑几何图形,但这些曲线是独立的,彼此之间没有任何关系。为了简化建模,将这三条曲线作为单个实体进行操作是正确的。这可以通过使用TopoDS包中定义的开放式CASCADE技术的拓扑数据结构来实现:它定义了几何实体之间的关系,这些几何实体可以链接在一起以表示复杂的形状。TopoDS包的每个对象继承自TopoDS_Shape类,描述如下所述的拓扑形状:
Shape | Open CASCADE Technology Class | Description |
---|---|---|
Vertex | TopoDS_Vertex | Zero dimensional shape corresponding to a point in geometry. 与几何图形中的点相对应的零维形状。 |
Edge | TopoDS_Edge | One-dimensional shape corresponding to a curve and bounded by a vertex at each extremity. 与曲线相对应的一维形状,并由每个末端的顶点限定。 |
Wire | TopoDS_Wire | Sequence of edges connected by vertices. 由顶点连接的边序列。 |
Face | TopoDS_Face | Part of a surface bounded by a closed wire(s). 由闭合导线界定的曲面的一部分。 |
Shell | TopoDS_Shell | Set of faces connected by edges. 由边连接的一组面。 |
Solid | TopoDS_Solid | Part of 3D space bounded by Shells. 由壳限定的三维空间的一部分。 |
CompSolid | TopoDS_CompSolid | Set of solids connected by their faces. 由面连接的一组实体。 |
Compound | TopoDS_Compound | Set of any other shapes described above. 上述任何其他形状的集合。 |
Referring to the previous table, to build the profile, you will create:
- Three edges out of the previously computed curves.
- One wire with these edges.
参考上表,要构建概要文件,您将创建:
- 先前计算的曲线中的三条边。
- 一根带有这些边的电线。
However, the TopoDS package provides only the data structure of the topological entities. Algorithm classes available to compute standard topological objects can be found in the BRepBuilderAPI package. To create an edge, you use the BRepBuilderAPI_MakeEdge class with the previously computed curves:
然而,TopoDS包仅提供拓扑实体的数据结构。可用于计算标准拓扑对象的算法类可以在BRpBuilderAPI包中找到。若要创建边,请使用BRepBuilderAPI_MakeEdge类和先前计算的曲线:
1 | TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(aSegment1); |
In Open CASCADE Technology, you can create edges in several ways. One possibility is to create an edge directly from two points, in which case the underlying geometry of this edge is a line, bounded by two vertices being automatically computed from the two input points. For example, anEdge1 and anEdge3 could have been computed in a simpler way:
在OpenCASCADE技术中,您可以通过多种方式创建边。一种可能是直接从两个点创建一条边,在这种情况下,该边的基本几何图形是一条线,由两个顶点自动从两个输入点计算出。例如,anEdge1和anEdge3可以以更简单的方式计算:
1 | TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(aPnt1, aPnt3); |
To connect the edges, you need to create a wire with the BRepBuilderAPI_MakeWire class. There are two ways of building a wire with this class:
- directly from one to four edges
- by adding other wire(s) or edge(s) to an existing wire (this is explained later in this tutorial)
When building a wire from less than four edges, as in the present case, you can use the constructor directly as follows:
要连接边,需要使用BRepBuilderAPI_MakeWire类创建导线。有两种方法可以使用该类构建导线:
- 直接从一条边到四条边
- 通过将其他导线或边添加到现有导线中(这将在本教程后面解释)
当从少于四条边构建导线时,如本例所示,可以直接使用构造函数,如下所示:
1 | TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3); |
Profile: Completing the Profile 配置文件:完成配置文件
Once the first part of your wire is created you need to compute the complete profile. A simple way to do this is to:
- compute a new wire by reflecting the existing one.
- add the reflected wire to the initial one.
创建导线的第一部分后,需要计算整个轮廓。一个简单的方法是:
- 通过反映现有导线来计算新导线。
- 将反射线添加到初始线。
To apply a transformation on shapes (including wires), you first need to define the properties of a 3D geometric transformation by using the gp_Trsf class. This transformation can be a translation, a rotation, a scale, a reflection, or a combination of these. In our case, we need to define a reflection with respect to the X axis of the global coordinate system. An axis, defined with the gp_Ax1 class, is built out of a point and has a direction (3D unitary vector). There are two ways to define this axis. The first way is to define it from scratch, using its geometric definition:
- X axis is located at (0, 0, 0) - use the gp_Pnt class.
- X axis direction is (1, 0, 0) - use the gp_Dir class. A gp_Dir instance is created out of its X, Y and Z coordinates.
要在形状(包括导线)上应用变换,首先需要使用gp_Trsf类定义三维几何变换的属性。这种转换可以是平移、旋转、缩放、反射或这些的组合。在我们的例子中,我们需要定义相对于全局坐标系X轴的反射。用gp_Ax1类定义的轴由一个点构建,并具有一个方向(3D酉向量)。有两种方法可以定义此轴。第一种方法是使用其几何定义从头定义:
- X轴位于(0,0,0) - 使用gp_Pnt类。
- X轴方向为(1,0,0) - 使用gp_Dir类。gp_Dir实例是根据其X、Y和Z坐标创建的。
1 | gp_Pnt aOrigin(0, 0, 0); |
The second and simplest way is to use the geometric constants defined in the gp package (origin, main directions and axis of the global coordinate system). To get the X axis, just call the gp::OX method:
第二种也是最简单的方法是使用gp包中定义的几何常数(原点、主方向和全局坐标系的轴)。要获得X轴,只需调用gp::OX方法:
1 | gp_Ax1 xAxis = gp::OX(); |
As previously explained, the 3D geometric transformation is defined with the gp_Trsf class. There are two different ways to use this class:
- by defining a transformation matrix by all its values
- by using the appropriate methods corresponding to the required transformation (SetTranslation for a translation, SetMirror for a reflection, etc.): the matrix is automatically computed.
如前所述,3D几何变换是用gp_Trsf类定义的。有两种不同的方法可以使用此类:
- 通过定义变换矩阵的所有值
- 通过使用与所需转换相对应的适当方法(转换时使用SetTranslation,反射时使用SetMirror等):自动计算矩阵。
Since the simplest approach is always the best one, you should use the SetMirror method with the axis as the center of symmetry.
因为最简单的方法总是最好的,所以应该使用以轴为对称中心的SetMirror方法。
1 | gp_Trsf aTrsf; |
You now have all necessary data to apply the transformation with the BRepBuilderAPI_Transform class by specifying:
- the shape on which the transformation must be applied.
- the geometric transformation
现在,您已经拥有了所有必要的数据,可以通过指定以下内容来使用BRpBuilderAPI_Transform类应用转换:
- 必须应用变换的形状。
- 几何变换
1 | BRepBuilderAPI_Transform aBRepTrsf(aWire, aTrsf); |
BRepBuilderAPI_Transform does not modify the nature of the shape: the result of the reflected wire remains a wire. But the function-like call or the BRepBuilderAPI_Transform::Shape method returns a TopoDS_Shape object:
BRepBuilderAPI_Transform不会修改形状的性质:反射线的结果仍然是一条线。但是类似函数的调用或BRpBuilderAPI_Transform::Shape方法返回一个TopoDS_Shape对象:
1 | TopoDS_Shape aMirroredShape = aBRepTrsf.Shape(); |
What you need is a method to consider the resulting reflected shape as a wire. The TopoDS global functions provide this kind of service by casting a shape into its real type. To cast the transformed wire, use the TopoDS::Wire method.
您需要的是将生成的反射形状视为导线的方法。TopoDS全局函数通过将形状转换为其真实类型来提供此类服务。要铸造变换的导线,请使用TopoDS::wire方法。
The bottle’s profile is almost finished. You have created two wires: aWire and aMirroredWire. You need to concatenate them to compute a single shape. To do this, you use the BRepBuilderAPI_MakeWire class as follows:
- create an instance of BRepBuilderAPI_MakeWire.
- add all edges of the two wires by using the Add method on this object.
瓶子的轮廓几乎完成了。您已经创建了两条导线:aWire和aMirroredWire。您需要连接它们以计算单个形状。为此,可以按如下方式使用BRepBuilderAPI_MakeWire类:
- 创建BRepBuilderAPI_MakeWire的实例。
- 通过在此对象上使用add方法添加两条导线的所有边。
1 | BRepBuilderAPI_MakeWire mkWire; |
Building the Body 构建身体
Prism the Profile 棱镜轮廓
To compute the main body of the bottle, you need to create a solid shape. The simplest way is to use the previously created profile and sweep it along a direction. The Prism functionality of Open CASCADE Technology is the most appropriate for that task. It accepts a shape and a direction as input and generates a new shape according to the following rules:
要计算瓶子的主体,需要创建一个实体形状。最简单的方法是使用先前创建的轮廓并沿某个方向扫掠。Open CASCADE Technology的Prism功能最适合该任务。它接受形状和方向作为输入,并根据以下规则生成新形状:
Shape | Generates |
---|---|
Vertex | Edge |
Edge | Face |
Wire | Shell |
Face | Solid |
Shell | Compound of Solids |
您当前的配置文件是一条导线。参考“形状/生成”表,需要计算其线的面以生成实体。要创建面,请使用BRepBuilderAPI_MakeFace类。如前所述,面是由闭合导线界定的曲面的一部分。通常,BRepBuilderAPI_MakeFace计算曲面和一条或多条导线的面。当导线位于平面上时,将自动计算曲面。
1 | TopoDS_Face myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile); |
The BRepPrimAPI package provides all the classes to create topological primitive constructions: boxes, cones, cylinders, spheres, etc. Among them is the BRepPrimAPI_MakePrism class. As specified above, the prism is defined by:
- the basis shape to sweep;
- a vector for a finite prism or a direction for finite and infinite prisms.
BRepPrimAPI包提供了创建拓扑图元构造的所有类:长方体、圆锥体、圆柱体、球体等。其中包括BRepPrimAPI_MakePrism类。如上所述,棱镜的定义如下:
- 要扫描的基本形状;
- 有限棱镜的矢量或有限和无限棱镜的方向。
You want the solid to be finite, swept along the Z axis and to be myHeight height. The vector, defined with the gp_Vec class on its X, Y and Z coordinates, is:
您希望实体是有限的,沿Z轴扫掠,高度为myHeight。在其X、Y和Z坐标上用gp_Vec类定义的矢量为:
1 | gp_Vec aPrismVec(0, 0, myHeight); |
All the necessary data to create the main body of your bottle is now available. Just apply the BRepPrimAPI_MakePrism class to compute the solid:
创建瓶子主体所需的所有数据现在都可用。只需应用BRepPrimAPI_MakePrism类来计算实体:
1 | TopoDS_Shape myBody = BRepPrimAPI_MakePrism(myFaceProfile, aPrismVec); |
Applying Fillets 应用圆角
The edges of the bottle’s body are very sharp. To replace them by rounded faces, you use the Fillet functionality of Open CASCADE Technology. For our purposes, we will specify that fillets must be:
- applied on all edges of the shape
- have a radius of myThickness / 12
瓶身的边缘非常锋利。要用圆角面替换它们,可以使用Open CASCADE Technology的圆角功能。出于我们的目的,我们将指定圆角必须:
- 应用于形状的所有边缘
- 半径为myThickness/12
To apply fillets on the edges of a shape, you use the BRepFilletAPI_MakeFillet class. This class is normally used as follows:
- Specify the shape to be filleted in the BRepFilletAPI_MakeFillet constructor.
- Add the fillet descriptions (an edge and a radius) using the Add method (you can add as many edges as you need).
- Ask for the resulting filleted shape with the Shape method.
要在形状的边上应用圆角,请使用BRepFilletAPI_MakeFillet类。此类通常使用如下:
- 在BRepFilletAPI_MakeFillet构造函数中指定要圆角的形状。
- 使用Add方法添加圆角描述(边和半径)(可以根据需要添加任意多条边)。
- 使用shape方法询问生成的圆角形状。
1 | BRepFilletAPI_MakeFillet mkFillet(myBody); |
To add the fillet description, you need to know the edges belonging to your shape. The best solution is to explore your solid to retrieve its edges. This kind of functionality is provided with the TopExp_Explorer class, which explores the data structure described in a TopoDS_Shape and extracts the sub-shapes you specifically need. Generally, this explorer is created by providing the following information:
- the shape to explore
- the type of sub-shapes to be found. This information is given with the TopAbs_ShapeEnum enumeration.
要添加圆角描述,需要知道属于形状的边。最佳解决方案是探索实体以检索其边缘。TopExp_Explorer类提供了这种功能,它探索TopoShape中描述的数据结构,并提取您特别需要的子形状。通常,通过提供以下信息创建此资源管理器:
- 要探索的形状
- 要查找的子形状的类型。此信息与TopAbs_ShapeEnum枚举一起提供。
1 | TopExp_Explorer anEdgeExplorer(myBody, TopAbs_EDGE); |
An explorer is usually applied in a loop by using its three main methods:
- More() to know if there are more sub-shapes to explore.
- Current() to know which is the currently explored sub-shape (used only if the More() method returns true).
- Next() to move onto the next sub-shape to explore.
资源管理器通常通过使用其三种主要方法应用于循环中:
-More()以了解是否有更多子形状需要探索。
-Current()以了解当前探索的子形状(仅当More()方法返回true时使用)。
-Next()移动到要探索的下一个子形状。
1 | while(anEdgeExplorer.More()){ |
In the explorer loop, you have found all the edges of the bottle shape. Each one must then be added in the BRepFilletAPI_MakeFillet instance with the Add() method. Do not forget to specify the radius of the fillet along with it.
在资源管理器循环中,您已找到瓶子形状的所有边缘。然后必须使用Add()方法在BRepFilletAPI_MakeFillet实例中添加每一个。不要忘记指定圆角的半径。
1 | mkFillet.Add(myThickness / 12., anEdge); |
Once this is done, you perform the last step of the procedure by asking for the filleted shape.
完成此操作后,通过请求圆角形状来执行过程的最后一步。
1 | myBody = mkFillet.Shape(); |
Adding the Neck 添加颈部
To add a neck to the bottle, you will create a cylinder and fuse it to the body. The cylinder is to be positioned on the top face of the body with a radius of myThickness / 4. and a height of myHeight / 10.
若要在瓶子上添加颈部,您将创建一个圆柱体并将其熔合到身体上。圆柱体将位于主体的顶面上,半径为myThickness/4。高度为myHeight/10。
To position the cylinder, you need to define a coordinate system with the gp_Ax2 class defining a right-handed coordinate system from a point and two directions - the main (Z) axis direction and the X direction (the Y direction is computed from these two). To align the neck with the center of the top face, being in the global coordinate system (0, 0, myHeight), with its normal on the global Z axis, your local coordinate system can be defined as follows:
要定位圆柱体,需要使用gp_Ax2类定义一个坐标系,该类从一个点和两个方向(主(Z)轴方向和X方向)定义右手坐标系(Y方向是从这两个方向计算的)。若要将颈部与顶面的中心对齐(位于全局坐标系(0,0,myHeight)中),其法线位于全局Z轴上,可以按如下方式定义局部坐标系:
1 | gp_Pnt neckLocation(0, 0, myHeight); |
To create a cylinder, use another class from the primitives construction package: the BRepPrimAPI_MakeCylinder class. The information you must provide is:
- the coordinate system where the cylinder will be located;
- the radius and height.
要创建圆柱体,请使用基本体构建包中的另一个类:BRepPrimAPI_MakeCylinder类。您必须提供的信息是:
- 圆柱体将位于的坐标系;
- 半径和高度。
1 | Standard_Real myNeckRadius = myThickness / 4.; |
You now have two separate parts: a main body and a neck that you need to fuse together. The BRepAlgoAPI package provides services to perform Boolean operations between shapes, and especially: common (Boolean intersection), cut (Boolean subtraction) and fuse (Boolean union). Use BRepAlgoAPI_Fuse to fuse the two shapes:
你现在有两个独立的部分:一个主体和一个颈部,你需要将它们融合在一起。BRepAlgoAPI包提供了在形状之间执行布尔运算的服务,尤其是:公共(布尔交集)、截断(布尔减法)和融合(布尔并集)。使用BRepAlgoAPI_Fuse融合两个形状:
1 | myBody = BRepAlgoAPI_Fuse(myBody, myNeck); |
Creating a Hollowed Solid 创建空心实体
Since a real bottle is used to contain liquid material, you should now create a hollowed solid from the bottle’s top face. In Open CASCADE Technology, a hollowed solid is called a Thick Solid and is internally computed as follows:
- Remove one or more faces from the initial solid to obtain the first wall W1 of the hollowed solid.
- Create a parallel wall W2 from W1 at a distance D. If D is positive, W2 will be outside the initial solid, otherwise it will be inside.
- Compute a solid from the two walls W1 and W2.
因为真正的瓶子是用来装液体材料的,所以现在应该从瓶子的顶面创建一个中空的固体。在开放式CASCADE技术中,空心实体称为厚实体,内部计算如下:
- 从初始实体移除一个或多个面以获得中空实体的第一壁W1。
- 在距离D处从W1创建平行墙W2。如果D为正,W2将位于初始实体的外部,否则将位于内部。
- 从两个壁W1和W2计算实体。
To compute a thick solid, you create an instance of the BRepOffsetAPI_MakeThickSolid class by giving the following information:
- The shape, which must be hollowed.
- The tolerance used for the computation (tolerance criterion for coincidence in generated shapes).
- The thickness between the two walls W1 and W2 (distance D).
- The face(s) to be removed from the original solid to compute the first wall W1.
要计算厚实体,请通过提供以下信息创建BRepOffsetAPI_MakeThickSolid类的实例:
- 必须挖空的形状。
- 用于计算的公差(生成形状中重合的公差标准)。
- 两个壁W1和W2之间的厚度(距离D)。
- 要从原始实体移除的面以计算第一壁W1。
The challenging part in this procedure is to find the face to remove from your shape - the top face of the neck, which:
- has a plane (planar surface) as underlying geometry;
- is the highest face (in Z coordinates) of the bottle.
这个过程中最具挑战性的部分是找到要从你的形状中移除的面部——颈部的上表面,这:
- 具有作为基础几何体的平面(平面);
- 是瓶子的最高面(在Z坐标中)。
To find the face with such characteristics, you will once again use an explorer to iterate on all the bottle’s faces to find the appropriate one.
要找到具有此类特征的面部,您将再次使用浏览器对所有瓶子的面部进行迭代,以找到合适的面部。
1 | for(TopExp_Explorer aFaceExplorer(myBody, TopAbs_FACE) ; aFaceExplorer.More() ; aFaceExplorer.Next()){ |
For each detected face, you need to access the geometric properties of the shape: use the BRep_Tool class for that. The most commonly used methods of this class are:
- Surface to access the surface of a face;
- Curve to access the 3D curve of an edge;
- Point to access the 3D point of a vertex.
对于每个检测到的面,您需要访问形状的几何属性:为此使用BRep_Tool类。此类最常用的方法有:
- 访问面表面的表面;
- 访问边缘的3D曲线的曲线;
- 点以访问顶点的三维点。
1 | Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace); |
As you can see, the BRep_Tool::Surface method returns an instance of the Geom_Surface class manipulated by handle. However, the Geom_Surface class does not provide information about the real type of the object aSurface, which could be an instance of Geom_Plane, Geom_CylindricalSurface, etc. All objects manipulated by handle, like Geom_Surface, inherit from the Standard_Transient class which provides two very useful methods concerning types:
- DynamicType to know the real type of the object
- IsKind to know if the object inherits from one particular type
如您所见,BRep_Tool::Surface方法返回由句柄操纵的Geom_Surface类的实例。然而,Geom_Surface类不提供有关对象aSurface的真实类型的信息,该类型可能是Geom_Plane、Geom_CylindricalSurface等的实例。所有由句柄操纵的对象(如Geom_Surface)都继承自Standard_Transient类,后者提供了两种非常有用的类型相关方法:
- DynamicType以了解对象的真实类型
- IsKind以了解对象是否继承自一个特定类型
DynamicType returns the real type of the object, but you need to compare it with the existing known types to determine whether aSurface is a plane, a cylindrical surface or some other type. To compare a given type with the type you seek, use the STANDARD_TYPE macro, which returns the type of a class:
DynamicType返回对象的真实类型,但需要将其与现有已知类型进行比较,以确定aSurface是平面、柱面还是其他类型。要将给定类型与所查找的类型进行比较,请使用STANDARD_type宏,该宏返回类的类型:
1 | if(aSurface->DynamicType() == STANDARD_TYPE(Geom_Plane)){ |
If this comparison is true, you know that the aSurface real type is Geom_Plane. You can then convert it from Geom_Surface to Geom_Plane by using the DownCast() method provided by each class inheriting Standard_Transient. As its name implies, this static method is used to downcast objects to a given type with the following syntax:
如果此比较为真,则知道aSurface实型为Geom_Plane。然后,可以使用继承Standard_Transient的每个类提供的DownCast()方法将其从Geom_Surface转换为Geom_Plane。顾名思义,此静态方法用于使用以下语法将对象向下转换为给定类型:
1 | Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurface); |
Remember that the goal of all these conversions is to find the highest face of the bottle lying on a plane. Suppose that you have these two global variables:
请记住,所有这些转换的目标都是找到位于平面上的瓶子的最高面。假设您有以下两个全局变量:
1 | TopoDS_Face faceToRemove; |
You can easily find the plane whose origin is the biggest in Z knowing that the location of the plane is given with the Geom_Plane::Location method. For example:
您可以很容易地找到原点在Z方向上最大的平面,因为知道平面的位置是通过Geom_plane::location方法给出的。例如:
1 | gp_Pnt aPnt = aPlane->Location(); |
You have now found the top face of the neck. Your final step before creating the hollowed solid is to put this face in a list. Since more than one face can be removed from the initial solid, the BRepOffsetAPI_MakeThickSolid constructor takes a list of faces as arguments. Open CASCADE Technology provides many collections for different kinds of objects: see TColGeom package for collections of objects from Geom package, TColgp package for collections of objects from gp package, etc. The collection for shapes can be found in the TopTools package. As BRepOffsetAPI_MakeThickSolid requires a list, use the TopTools_ListOfShape class.
现在您已经找到了颈部的顶面。创建空心实体之前的最后一步是将此面放入列表中。由于可以从初始实体中删除多个面,因此BRepOffsetAPI_MakeThickSolid构造函数将面列表作为参数。OpenCASCADETechnology为不同类型的对象提供了许多集合:参见TColGeom包获取Geom包中的对象集合,参见TColgp包获取gp包中对象集合等。形状集合可以在TopTools包中找到。由于BRepOffsetAPI_MakeThickSolid需要列表,请使用TopTools_ListOfShape类。
1 | TopTools_ListOfShape facesToRemove; |
All the necessary data are now available so you can create your hollowed solid by calling the BRepOffsetAPI_MakeThickSolid MakeThickSolidByJoin method:
所有必要的数据现在都可用,因此您可以通过调用BRepOffsetAPI_MakeThickSolid MakeThickSolidByJoin方法来创建空心实体:
1 | BRepOffsetAPI_MakeThickSolid aSolidMaker; |
Building the Threading 构建线程
Creating Surfaces 创建曲面
Up to now, you have learned how to create edges out of 3D curves. You will now learn how to create an edge out of a 2D curve and a surface. To learn this aspect of Open CASCADE Technology, you will build helicoidal profiles out of 2D curves on cylindrical surfaces. The theory is more complex than in previous steps, but applying it is very simple. As a first step, you compute these cylindrical surfaces. You are already familiar with the curves of the Geom package. Now you can create a cylindrical surface (Geom_CylindricalSurface) using:
- a coordinate system;
- a radius.
Using the same coordinate system neckAx2 used to position the neck, you create two cylindrical surfaces Geom_CylindricalSurface with the following radii:
到目前为止,您已经学习了如何从三维曲线创建边。现在,您将学习如何从二维曲线和曲面创建边。为了学习OpenCASCADE技术的这一方面,您将在圆柱表面上用2D曲线构建螺旋轮廓。该理论比前面的步骤更复杂,但应用起来非常简单。作为第一步,计算这些柱面。您已经熟悉Geom包的曲线。现在,可以使用以下方法创建圆柱曲面(Geom_CylindricalSurface):
- 坐标系;
- 半径。
使用用于定位颈部的同一坐标系neckAx2,可以创建具有以下半径的两个圆柱曲面Geom_CylindricalSurface:
Notice that one of the cylindrical surfaces is smaller than the neck. There is a good reason for this: after the thread creation, you will fuse it with the neck. So, we must make sure that the two shapes remain in contact.
请注意,其中一个圆柱形曲面小于颈部。这有一个很好的原因:创建线程后,您将将其与颈部融合。因此,我们必须确保两个形状保持接触。
1 | Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99); |
Defining 2D Curves 定义二维曲线
To create the neck of the bottle, you made a solid cylinder based on a cylindrical surface. You will create the profile of threading by creating 2D curves on such a surface. All geometries defined in the Geom package are parameterized. This means that each curve or surface from Geom is computed with a parametric equation. A Geom_CylindricalSurface surface is defined with the following parametric equation:
为了创建瓶子的颈部,您基于圆柱形表面制作了一个实心圆柱体。您将通过在这样的曲面上创建二维曲线来创建螺纹轮廓。Geom包中定义的所有几何图形都是参数化的。这意味着Geom中的每条曲线或曲面都是用参数方程计算的。Geom_CylindricalSurface曲面由以下参数方程定义:
P(U, V) = O + R * (cos(U) * xDir + sin(U) * yDir) + V * zDir, where :
- P is the point defined by parameters (U, V).
- O, *Dir, yDir and zDir are respectively the origin, the X direction, Y direction and Z direction of the cylindrical surface local coordinate system.
- R is the radius of the cylindrical surface.
- U range is [0, 2PI] and V is infinite.
P(U,V)=O+R*(cos(U)*xDir+sin(U)yDir)+VzDir,其中:
- P是由参数(U,V)定义的点。
- O、 *Dir、yDir和zDir分别是柱面局部坐标系的原点、X方向、Y方向和Z方向。
- R是柱面的半径。
- U范围为[0,2PI],V为无穷大。
The advantage of having such parameterized geometries is that you can compute, for any (U, V) parameters of the surface:
- the 3D point;
- the derivative vectors of order 1, 2 to N at this point.
具有此类参数化几何体的优点在于,可以计算曲面的任何(U,V)参数:
- 3D点;
- 此时阶数为1、2至N的导数向量。
There is another advantage of these parametric equations: you can consider a surface as a 2D parametric space defined with a (U, V) coordinate system. For example, consider the parametric ranges of the neck’s surface:
这些参数化方程还有另一个优点:可以将曲面视为使用(U,V)坐标系定义的二维参数化空间。例如,考虑颈部曲面的参数化范围:
Suppose that you create a 2D line on this parametric (U, V) space and compute its 3D parametric curve. Depending on the line definition, results are as follows:
假设您在此参数化(U,V)空间上创建一条二维线,并计算其三维参数化曲线。根据线定义,结果如下:
Case | Parametric Equation 参数化方程式 | Parametric Curve 参数化曲线 |
---|---|---|
U = 0 | P(V) = O + V * zDir | Line parallel to the Z direction 平行于Z方向的线 |
V = 0 | P(U) = O + R * (cos(U) * xDir + sin(U) * yDir) | Circle parallel to the (O, X, Y) plane 平行于(O,X,Y)平面的圆 |
U != 0 V != 0 | P(U, V) = O + R * (cos(U) * xDir + sin(U) * yDir) + V * zDir | Helicoidal curve describing the evolution of height and angle on the cylinder 描述圆柱体高度和角度演变的螺旋曲线 |
The helicoidal curve type is exactly what you need. On the neck’s surface, the evolution laws of this curve will be:
- In V parameter: between 0 and myHeighNeck for the height description
- In U parameter: between 0 and 2PI for the angle description. But, since a cylindrical surface is U periodic, you can decide to extend this angle evolution to 4PI as shown in the following drawing:
螺旋曲线类型正是您所需要的。在颈部表面上,该曲线的演化规律为:
- 在V参数中:高度描述在0和myHeighNeck之间
- 在U参数中:角度描述在0和2PI之间。但是,由于圆柱表面是U周期性的,您可以决定将此角度演变扩展到4PI,如下图所示:
In this (U, V) parametric space, you will create a local (X, Y) coordinate system to position the curves to be created. This coordinate system will be defined with:
- A center located in the middle of the neck’s cylinder parametric space at (2*PI, myNeckHeight / 2) in U, V coordinates.
- A X direction defined with the (2*PI, myNeckHeight/4) vector in U, V coordinates, so that the curves occupy half of the neck’s surfaces.
在这个(U,V)参数化空间中,您将创建一个局部(X,Y)坐标系来定位要创建的曲线。该坐标系将定义为:
- 位于颈部圆柱体参数化空间中间的中心,位于U、V坐标下的(2*PI,myNeckHeight/2)处。
- 用U、V坐标中的(2*PI,myNeckHeight/4)向量定义的X方向,以便曲线占据颈部曲面的一半。
To use 2D primitive geometry types of Open CASCADE Technology for defining a point and a coordinate system, you will once again instantiate classes from gp:
- To define a 2D point from its X and Y coordinates, use the gp_Pnt2d class.
- To define a 2D direction (unit vector) from its X and Y coordinates, use the gp_Dir2d class. The coordinates will automatically be normalized.
- To define a 2D right-handed coordinate system, use the gp_Ax2d class, which is computed from a point (origin of the coordinate system) and a direction - the X direction of the coordinate system. The Y direction will be automatically computed.
要使用OpenCASCADE技术的2D基本几何类型来定义点和坐标系,您将再次从gp实例化类:
- 要从X和Y坐标定义二维点,请使用gp_Pnt2d类。
- 要从X和Y坐标定义二维方向(单位向量),请使用gp_Dir2d类。坐标将自动标准化。
- 要定义二维右手坐标系,请使用gp_Ax2d类,该类是从一个点(坐标系的原点)和一个方向(坐标系X方向)计算的。将自动计算Y方向。
1 | gp_Pnt2d aPnt(2. * M_PI, myNeckHeight / 2.); |
You will now define the curves. As previously mentioned, these thread profiles are computed on two cylindrical surfaces. In the following figure, curves on the left define the base (on aCyl1 surface) and the curves on the right define the top of the thread’s shape (on aCyl2 surface).
现在将定义曲线。如前所述,这些螺纹轮廓是在两个圆柱表面上计算的。在下图中,左侧的曲线定义了底部(在aCyl1曲面上),右侧的曲线定义螺纹形状的顶部(在aCtyl2曲面上)。
You have already used the Geom package to define 3D geometric entities. For 2D, you will use the Geom2d package. As for Geom, all geometries are parameterized. For example, a Geom2d_Ellipse ellipse is defined from:
- a coordinate system whose origin is the ellipse center;
- a major radius on the major axis defined by the X direction of the coordinate system;
- a minor radius on the minor axis defined by the Y direction of the coordinate system.
您已经使用Geom包定义了三维几何图元。对于2D,您将使用Geom2d包。对于Geom,所有几何图形都是参数化的。例如,Geom2d_Ellipse椭圆的定义如下:
- 原点为椭圆中心的坐标系;
- 由坐标系的X方向限定的长轴上的主半径;
- 由坐标系的Y方向定义的短轴上的短半径。
Supposing that:
- Both ellipses have the same major radius of 2*PI,
- Minor radius of the first ellipse is myNeckHeight / 10,
- And the minor radius value of the second ellipse is a fourth of the first one,
假设:
- 两个椭圆具有相同的主半径2*PI,
- 第一个椭圆的小半径是myNeckHeight/10,
- 第二个椭圆的小半径值是第一个椭圆的四分之一,
Your ellipses are defined as follows:
椭圆的定义如下:
1 | Standard_Real aMajor = 2. * M_PI; |
To describe portions of curves for the arcs drawn above, you define Geom2d_TrimmedCurve trimmed curves out of the created ellipses and two parameters to limit them. As the parametric equation of an ellipse is P(U) = O + (MajorRadius * cos(U) * XDirection) + (MinorRadius * sin(U) * YDirection), the ellipses need to be limited between 0 and M_PI.
若要描述上面绘制的圆弧的曲线部分,请从创建的椭圆中定义Geom2d_TrimedCurve修剪曲线和两个参数来限制它们。由于椭圆的参数方程为P(U)=O+(MajorRadius*cos(U)XDirection)+(MinorRadiussin(U)*YDirection),椭圆需要限制在0和M_PI之间。
1 | Handle(Geom2d_TrimmedCurve) anArc1 = new Geom2d_TrimmedCurve(anEllipse1, 0, M_PI); |
The last step consists in defining the segment, which is the same for the two profiles: a line limited by the first and the last point of one of the arcs. To access the point corresponding to the parameter of a curve or a surface, you use the Value or D0 method (meaning 0th derivative), D1 method is for the first derivative, D2 for the second one.
最后一步是定义线段,这对于两个轮廓是相同的:一条由其中一个圆弧的第一点和最后一点限定的线。要访问与曲线或曲面的参数对应的点,可以使用值或D0方法(表示0阶导数),D1方法用于一阶导数,D2方法用于二阶导数。
1 | gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0); |
When creating the bottle’s profile, you used classes from the GC package, providing algorithms to create elementary geometries. In 2D geometry, this kind of algorithms is found in the GCE2d package. Class names and behaviors are similar to those in GC. For example, to create a 2D segment out of two points:
在创建瓶子的配置文件时,您使用了GC包中的类,提供了创建基本几何图形的算法。在2D几何中,这种算法可以在GCE2d包中找到。类名和行为与GC中的类似。例如,要从两点创建二维线段:
1 | Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2); |
Building Edges and Wires 建筑边缘和导线
As you did when creating the base profile of the bottle, you can now:
- compute the edges of the neck’s threading.
- compute two wires out of these edges.
与创建瓶子的基础轮廓时一样,现在可以:
- 计算颈部螺纹的边缘。
- 从这些边中计算两条线。
Previously, you have built:
- two cylindrical surfaces of the threading
- three 2D curves defining the base geometry of the threading
以前,您已经构建了:
- 螺纹的两个圆柱形表面
- 定义螺纹基本几何图形的三条2D曲线
To compute the edges out of these curves, once again use the BRepBuilderAPI_MakeEdge class. One of its constructors allows you to build an edge out of a curve described in the 2D parametric space of a surface.
要计算这些曲线的边,请再次使用BRepBuilderAPI_MakeEdge类。它的一个构造函数允许您从曲面的二维参数化空间中描述的曲线构建边。
1 | TopoDS_Edge anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1); |
Now, you can create the two profiles of the threading, lying on each surface.
现在,您可以在每个曲面上创建螺纹的两个轮廓。
1 | TopoDS_Wire threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1, anEdge2OnSurf1); |
Remember that these wires were built out of a surface and 2D curves. One important data item is missing as far as these wires are concerned: there is no information on the 3D curves. Fortunately, you do not need to compute this yourself, which can be a difficult task since the mathematics can be quite complex. When a shape contains all the necessary information except 3D curves, Open CASCADE Technology provides a tool to build them automatically. In the BRepLib tool package, you can use the BuildCurves3d method to compute 3D curves for all the edges of a shape.
请记住,这些导线是由曲面和二维曲线构建的。就这些导线而言,缺少一个重要的数据项:没有关于三维曲线的信息。幸运的是,你不需要自己计算,这可能是一项困难的任务,因为数学可能非常复杂。当形状包含除三维曲线之外的所有必要信息时,Open CASCADE Technology提供了一种工具来自动构建它们。在BRepLib工具包中,可以使用BuildCurves3d方法计算形状所有边的三维曲线。
1 | BRepLib::BuildCurves3d(threadingWire1); |
Creating Threading 创建线程
You have computed the wires of the threading. The threading will be a solid shape, so you must now compute the faces of the wires, the faces allowing you to join the wires, the shell out of these faces and then the solid itself. This can be a lengthy operation. There are always faster ways to build a solid when the base topology is defined. You would like to create a solid out of two wires. Open CASCADE Technology provides a quick way to do this by building a loft: a shell or a solid passing through a set of wires in a given sequence.
The loft function is implemented in the BRepOffsetAPI_ThruSections class, which you use as follows:
您已经计算了螺纹的导线。螺纹将是一个实心形状,因此现在必须计算导线的面、允许连接导线的面以及这些面的壳,然后计算实体本身。这可能是一个漫长的操作。定义基本拓扑时,总是有更快的方法来构建实体。您希望使用两根导线创建实体。OpenCASCADE技术提供了一种快速的方法来实现这一点,方法是建立一个阁楼:一个外壳或一个实体以给定的顺序穿过一组电线。
loft函数在BRpOffsetAPI_ThruSections类中实现,使用方法如下:
-
Initialize the algorithm by creating an instance of the class. The first parameter of this constructor must be specified if you want to create a solid. By default, BRepOffsetAPI_ThruSections builds a shell.
-
Add the successive wires using the AddWire method.
-
Use the CheckCompatibility method to activate (or deactivate) the option that checks whether the wires have the same number of edges. In this case, wires have two edges each, so you can deactivate this option.
-
Ask for the resulting loft shape with the Shape method.
-
通过创建类的实例来初始化算法。如果要创建实体,必须指定此构造函数的第一个参数。默认情况下,BRepOffsetAPI_ThruSections构建外壳。
-
使用AddWire方法添加连续的导线。
-
使用CheckCompatibility方法激活(或停用)检查导线是否具有相同数量的边的选项。在这种情况下,导线各有两条边,因此可以禁用此选项。
-
使用shape方法询问生成的放样形状。
1 | BRepOffsetAPI_ThruSections aTool(Standard_True); |
Building the Resulting Compound 构建生成的化合物
You are almost done building the bottle. Use the TopoDS_Compound and BRep_Builder classes to build single shape from myBody and myThreading:
你几乎完成了瓶子的制作。使用TopoDS_Compound和BRep_Builder类从myBody和myThreading构建单个形状:
1 | TopoDS_Compound aRes; |
Congratulations! Your bottle is complete. Here is the result snapshot of the Tutorial application:
祝贺你的瓶子是完整的。以下是Tutorial应用程序的结果快照:
We hope that this tutorial has provided you with a feel for the industrial strength power of Open CASCADE Technology. If you want to know more and develop major projects using Open CASCADE Technology, we invite you to study our training, support, and consulting services on our site at https://www.opencascade.com/content/technology-support. Our professional services can maximize the power of your Open CASCADE Technology applications.
我们希望本教程能让您感受到开放式CASCADE技术的工业实力。如果您想了解更多信息并使用开放式CASCADE技术开发主要项目,我们邀请您在我们的网站上学习我们的培训、支持和咨询服务,网址为https://www.opencascade.com/content/technology-support.我们的专业服务可以最大限度地发挥开放式CASCADE技术应用程序的威力。
Appendix 附录
Complete definition of MakeBottle function (defined in the file src/MakeBottle.cxx of the Tutorial):
MakeBottle函数的完整定义(在教程的src/MakeBottle.cxx文件中定义):
1 | TopoDS_Shape MakeBottle(const Standard_Real myWidth, const Standard_Real myHeight, |