1.Building the Profile
1.1 Defining Support Points
在Open CASCADE中定义三维笛卡尔坐标系的有两种不同的类:
原始集合gp_Pnt类(生存周期有限,在使用完后被自动销毁)
由句柄控制的Geom_CartesianPoint类(具有较长的生存周期)
两者之间的定义和使用的区别:
gp_Pnt aPnt1(0,0,0);
Handle(Geom_Cartesian_Point) aPnt2=new Geom_CartesianPoint(0,0,0);
Standard_Real xValue=aPnt1.x();
Standard_Real xValue=qPnt2->x();
定义如下四个点:
Standard_Real myHeight = 70, myWidth = 50, myThickness = 30;
//初始化五个点,由gp_Pnt类型定义。
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);
1.2 Defining the Geometry
定义几何体:由上面定义的五个点来实现:由两个线段和一段弧组成
要创建这样的实体,需要一个特定的数据结构,它实现了3D集合对象。上述结构可以在OCC的Geom包(包是一组提供相关功能的类)中找到。Geom包实现了3D几何对象:提供了基本的曲线和曲面以及更复杂的曲线(Bezier和BSpline)。 Geom_line and Geom_Circle.
但是,Geom包仅仅提供了几何实体的数据结构,可以通过直接实例化类来使用,但可以用更加容易技术基本曲线和曲面的GC包,因为GC提供两个我们所需要的算法:
GC_MakeSegment class:to create a segment。
GC_MakeArcOfCircle class:to create an arc of a circle 。
上述两个类的返回值都是Geom_TrimmedCurve类型的句柄。
//将五个点连接为几何体
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和Value方法:
GC_MakeSegment mkSeg(aPnt1,aPnt2);
Handle(Geom_TrimmedCurve) aSegment1;
if(mkSeg.IsDone())
{
aSegment1=mkSeg.Value();
....
}
1.3 Defining the Topology
1.2中创建了轮廓的一部分几何支撑,但这些曲线是独立的,彼此之间没有关系。为了简化模型,将这三条曲线作为一个整体来操作。通过OCCT中的ToopoDS包的数据结构来实现:他定义了几何实体之间的关系,这些几何实体可以间接在一起来表示复杂的形状,TopoDS包中的每个对象都继承自TopoDS_Shape类,它们所描述的拓扑形状如下所示:
shape | Open CASCADE Class | Description |
---|---|---|
Vertex | TopoDS_Vertex | 与几何中的一点相对应的0维形状 |
Edge | TopoDS_Edge | 与曲线相对应的一维形状,每个顶点(Vertex)上都有一个端点(extremity) |
Wire | TopoDS_Wire | 由点(Vertex)连接的按序排好的边。 |
Face | TopoDS_Face | 以闭合导线(closed wire)为界的表名的一部分 |
Shell | TopoDS_Shell | 由边连接的一组面 |
Solid | TopoDS_Solid | 由shell包围的三维空间的一部分 |
CompSolid | TopoDS_CompSolid | 由表名连接的Solid的集合 |
Compound | TopoDS_Compound | 上面描述的任何其他形状的集合 |
参考上表,我们可以创建:
先前计算的曲线三条边(edge)。
One Wire with these edges.
然而,TopoDS包仅提供拓扑实体的数据结构,可用于计算标准拓扑对象的算法类可以在BRepBuilderAPI包中找到。要创建一天边可以使用BRepBuilderAPI_MakeEdge类和先前计算了的曲线。连接这些边可以使用BRepBuilderAPI_MakeWire类
//定义其拓扑结构
TopoDS_Edge aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1);
TopoDS_Edge aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle);
TopoDS_Edge aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2);
//连接上述三条边
TopoDS_Wire aWire=BRepBuilderAPI_MakeWire(aEdge1,aEdge2,aEdge3);
1.4 Completing the Profile
一旦创建了连接的第一部分,就需要计算完整的概要文件。一种简单的方法是:通过放射(镜像)现有线路来创建新的线路
要对形状(包括导线)转换,首先需要使用gp_Trsf类定义3D几何转换的属性(平移、旋转、缩放、反射或这些的组合)。本例子中,我们需要定于关于坐标系x轴的反射。用gp_Ax1类定义的轴是由点和向量构成的:
方法一:
gp_Pnt aOrigin (0,0,0);//x轴坐落于点(0,0,0)
gp_Dir xDir(1,0,0);//方向向量
gp_Ax1 xAxis(aOrigin,xDir);//x轴
方法二:使用gp包中定义的几何常数(坐标系的原点、主方向和轴),要得到x轴,只需调用gp::OX()
gp_Ax1 xAxis=gp::OX();
在上诉对称轴确定后,需要使用gp_Tfsf类来进行3D几何转换。使用SetMirror方法来确定镜像的对称轴:
gp_Trsf aTrsf;
aTrsf.SetMirror(xAxis);
在完成所有数据的存储后,使用BRepBuilderAPI_Transform类来进行转换。
BRepBuilderAPI_Transform aBRepTrsf(aWire,aTrsf);
BRepBuilderAPI_Transform不会修改形状的性质:镜像的线依然是线。但是BRepBuilderAPI_Transform::Shape方法返回一个TopoDS_Shape对象。接着,通过TopoDS的全局函数将镜像结果的形状转换为导线,使用TopoDS::Wire方法。
TopoDS_Shape aMirrorShape=aBRepTrsf.Shape();//转换为TopoDS_Shape类型
TopoDS_Wire aMirrorWire=TopoDS::Wire(aMirrorShape);
到目前为止已经创建了两个导线:aWire和aMirrorWire.现在需要将这两个导线连接起来计算单个的形状:
首先创建BRepBuilderAPI_MakeWire实例,然后将这两个线通过Add方法加到这个实例中。
BRepBuilderAPI_MakeWire mkWire;
mkWire.Add(aWire);
mkWire.Add(aMirrorWire);
TopoDS_Wire myWireProfile=mkWire.Wire();
2.Building the Body
2.1 Prism the Profile
创建瓶子的主体,可以通过以前创建的概要文件(profile)沿着某一方向进行扫描。利用BRepBuilderAPI_MakeFace类来创建面(面是由闭合曲线包围的表面边界的一部分)
TopoDS_Face myFaceProfile=BRepBuilderAPI_MakeFace(myWireProfile);
利用BRepPrimAPI包提供的BRepPrimAPI_MakePrism类进行扫描,创建几何实体:
gp_Vec aPrismVec(0,0,myHeight);//有向向量:方向和距离
TopoDS_Shape myBody=BRepPrimAPI_MakePrism(myFaceProfile,aPrismVec);//创建实体
2.2 Applying Fillets (倒圆角)
将2.1中的棱柱进行倒圆角操作:应用于所有边、半径为厚度的1/2.
要在棱柱边缘使用Fillet(倒圆角),可以使用BRepFilletAPI_MakeFillet类:
1.在BRepFilletAPI_MakeFillet构造函数中指定要填充的形状
BRepFilletAPI_MakeFillet mkFillet(myBody);
2.使用其Add方法添加fillet的边和半径(可以根据需要添加任意多的边)
而在添加倒角边的时候,需要提前知道所有的边:通过TopExp_Explorer类提供的功能,选取TopoDS_Shape中描述的数据结构,提取指定的子形状。
TopExp_Explorer anEdgeExplorer(myBody,TopAbs_EDGE);//TopAbs_ShapeEnum::TopAbs_EDGE
注:the type of sub-shapes to be found.由TopAbs_ShapeEnum枚举给出。
在所得到的anEdgeExplorer实例中包含三个主要方法:More():是否还存在更多子形状
Current():当前子形状,只有More()为true是可用。
Next():下一个子形状。
While(anEdgeExplorer.More())
{
TopoDS_Edge anEdge=TopoDS::Edge(anEdgeExplorer.Current));
mkFillet.Add(myThickness/12.,anEdge);
anEdge.Next();
}
3. 得到倒角后的瓶身
myBody=mkFillet.Shape();
2.3 Adding the Neck
创建瓶子的颈部,需要先创建一个圆柱体,将其与瓶身融合,圆柱体放置在瓶身的顶部表名,半径为myThickness、4,高度为myHeight/10。
myBody=BRepAlgoAPI_Fuse(myBody,myNeck);
对于该圆柱体的定位,需要一个坐标系。gp_Ax2类从一点和两个方向定义坐标系(主轴z方向和x方向,y方向从这两个方向计算)。法线在z轴上,代码定义如下:
gp_Pnt neckLocation(0,0,myHeight);
gp_Dir neckAxis=gp::DZ();
gp_Ax2 neckAx2(neckLocation,neckAxis)
用BRepPrimAPI_MakeCylinder类来创建圆柱体:
Standard_Real myNeckRadius = myThickness/4.;
Standard_Real myNeckHeight = myHeight/10.;
BRepPrimAPI_MakeCylinder MKCylinder(neckAx2,myNeckRadius,myNeckHeight);
TopoDS_Shape myNeck=MKCylinder.Shape();
到此为止,有两个独立的几何实体:一个瓶身主体,一个需要融合的颈部。可使用BRepAlgoAPI包挺的布尔操作来实现:包括布尔交叉、布尔减法、布尔联合。使用BRepAlgoAPI_Fuse来进行布尔联合操作:
3.4 Creating a Hollowed Solid
将上述的实体瓶子变为空心瓶子
从顶部创造一个中空的实体,BRepOffsetAPI_MakeThickSolid类计算实体厚度
TopoDS_Face faceToRemove;//选择一个面作为基础几何面
Standard_Real zMax = -1;//瓶子的最高坐标,后面进行比较替换
//对瓶子的所有面的特征进行迭代。
for (TopExp_Explorer aFaceExplorer(myBody, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next())
{
TopoDS_Face aFace = TopoDS::Face(aFaceExplorer.Current());
//检查aface是否是瓶子的颈部最上面
Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);//对于检测到的面,你需要访问形状的几何属性,为此使用BRep_Tool类
if (aSurface->DynamicType() == STANDARD_TYPE(Geom_Plane))//类型检测
{
//将Geom_Surface类型转换为Geom_Plane类型。
Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurface);
gp_Pnt aPnt = aPlane->Location();//获取当前平面坐标点
Standard_Real aZ = aPnt.Z();
if (aZ > zMax)
{
zMax = aZ;
faceToRemove = aFace;
}
}
}
//BRepOffsetAPI_MakeThickSolid以一个面列表为参数,所以使用TopTools_ListOfShape::Append()添加面参数。
TopTools_ListOfShape facesToRemove;
facesToRemove.Append(facesToRemove);
BRepOffsetAPI_MakeThickSolid BodyMaker;
BodyMaker.MakeThickSolidByJoin(myBody, facesToRemove, -myThickness / 50, 1.e-3);
myBody = BodyMaker.Shape();