?
OpenCASCADE Make Primitives-Box
Abstract. By making a simple box to demonstrate the BRep data structure of the OpenCASCADE. The construction method is different from BRepPrimAPI_MakeBox. In the paper construct the box from vertex, edge to solid, while in BRepPrimAPI_MakeBox from solid, shell to vertex. From the construction, the BRep data structure in OpenCASCADE also can be called the Winged-Edge data structure.
Key Words. OpenCASCADE, BRep, Box, The Winged-Edge Structure
1. Introduction
OpenCASCADE的Toolit TKPrim中提供了基本圖元的創建功能,像Box, Cylinder, Sphere等等。直接使用Package BRepPrimAPI中的功能,可以方便地創建出基本圖元,而不用關心其內部的數據結構。
Figure 1. BRepPrimAPI Package classes
為 了理解ModelingData模塊中OpenCASCADE的邊界表示法BRep數據結構,決定參考其實現,自己來創建出基本圖元,進而理解其中的 BRep數據結構。本文以最簡單的長方體Box入手,從點、邊到體的創建出一個形狀。并將構造的形狀在Draw Test Harness中進行顯示,且進行布爾運算,來驗證構造結果的正確性。
2. Make a Face of the Box
在OpenCASCADE的包BRepPrim中,構造長方體的方式是形狀的根結點出發到葉子結點,即從Shell到Face到Wire最后到Vertex,如下圖所示:
Figure 2.1 Data structure of a Shape
為了程序演示的清晰,本文中采用與OpenCASCADE中相反的方式,即先從葉子結點出發,逐步回到根結點,即先構造出頂點、邊最后到實體。長方體由六個面構成,所以先從一個面開始來構造。將一個面構造成功后,其他六個面的構造方法就相同了。
構造使用了BRep_Builder,在創建相應的拓樸的同時可以將其相關的幾何信息設置進去。如創建頂點Vertex時,可以將點的坐標信息及容差值設置進去,代碼如下所示:
BRep_Builder aBuilder;
//
make vertex of the box.
aBuilder.MakeVertex(aVertices[
0
], aPoints[
0
], Precision::Confusion());
aBuilder.MakeVertex(aVertices[
1
], aPoints[
1
], Precision::Confusion());
aBuilder.MakeVertex(aVertices[
2
], aPoints[
2
], Precision::Confusion());
aBuilder.MakeVertex(aVertices[
3
], aPoints[
3
], Precision::Confusion());
aBuilder.MakeVertex(aVertices[
4
], aPoints[
4
], Precision::Confusion());
aBuilder.MakeVertex(aVertices[
5
], aPoints[
5
], Precision::Confusion());
aBuilder.MakeVertex(aVertices[
6
], aPoints[
6
], Precision::Confusion());
aBuilder.MakeVertex(aVertices[
7
], aPoints[
7
], Precision::Confusion());
創建邊的同時,將其邊中的三維曲線信息也設置進去,代碼如下所示:
//
make edges of the box.
aBuilder.MakeEdge(aEdges[
0
],
new
Geom_Line(aLines[
0
]), Precision::Confusion());
aBuilder.MakeEdge(aEdges[
1
],
new
Geom_Line(aLines[
1
]), Precision::Confusion());
aBuilder.MakeEdge(aEdges[
2
],
new
Geom_Line(aLines[
2
]), Precision::Confusion());
aBuilder.MakeEdge(aEdges[
3
],
new
Geom_Line(aLines[
3
]), Precision::Confusion());
aBuilder.MakeEdge(aEdges[
4
],
new
Geom_Line(aLines[
4
]), Precision::Confusion());
aBuilder.MakeEdge(aEdges[
5
],
new
Geom_Line(aLines[
5
]), Precision::Confusion());
aBuilder.MakeEdge(aEdges[
6
],
new
Geom_Line(aLines[
6
]), Precision::Confusion());
aBuilder.MakeEdge(aEdges[
7
],
new
Geom_Line(aLines[
7
]), Precision::Confusion());
aBuilder.MakeEdge(aEdges[
8
],
new
Geom_Line(aLines[
8
]), Precision::Confusion());
aBuilder.MakeEdge(aEdges[
9
],
new
Geom_Line(aLines[
9
]), Precision::Confusion());
aBuilder.MakeEdge(aEdges[
10
],
new
Geom_Line(aLines[
10
]),Precision::Confusion());
aBuilder.MakeEdge(aEdges[
11
],
new
Geom_Line(aLines[
11
]),Precision::Confusion());
創建的邊Edge還需要與頂點Vertex關聯上,且需要注意頂點的反向,示例代碼如下所示:
//
set the vertex info of the edges.
//
edge 0:
{
TopoDS_Vertex V1
= aVertices[
0
];
TopoDS_Vertex V2
= aVertices[
1
];
V2.Reverse();
aBuilder.Add(aEdges[
0
], V1);
aBuilder.Add(aEdges[
0
], V2);
aBuilder.UpdateVertex(V1, ElCLib::Parameter(aLines[
0
], aPoints[
0
]),
aEdges[
0
], Precision::Confusion());
aBuilder.UpdateVertex(V2, ElCLib::Parameter(aLines[
0
], aPoints[
1
]),
aEdges[
0
], Precision::Confusion());
BRepTools::Update(aEdges[
0
]);
}
接著創建Wire,創建Wire時需要注意邊的反向,從而構造成一個閉合的Wire,代碼如下所示:
//
make wires of the box.
aBuilder.MakeWire(aWires[
0
]);
//
wire 1: bottom
{
TopoDS_Edge E1
= aEdges[
0
];
TopoDS_Edge E2
= aEdges[
1
];
TopoDS_Edge E3
= aEdges[
2
];
TopoDS_Edge E4
= aEdges[
3
];
E3.Reverse();
E4.Reverse();
aBuilder.Add(aWires[
0
], E1);
aBuilder.Add(aWires[
0
], E2);
aBuilder.Add(aWires[
0
], E3);
aBuilder.Add(aWires[
0
], E4);
BRepTools::Update(aWires[
0
]);
}
關鍵是面的創建及面創建后,設置邊與面的關聯信息,即PCurve的信息。如果沒有PCurve的信息,可視化顯示就不能正確顯示出面,即網格化算法會失敗。長方體底面的創建及PCurve設置代碼如下所示:
//
make faces of the box.
aBuilder.MakeFace(aFaces[
0
],
new
Geom_Plane(aPlanes[
0
]),Precision::Confusion());
aBuilder.Add(aFaces[
0
], aWires[
0
]);
//
set bottom pcurve info of between the edge and surface.
{
//
pcurve 0:
double
u =
0.0
;
double
v =
0.0
;
double
du =
0.0
;
double
dv =
0.0
;
gp_Dir DX
= aPlanes[
0
].XAxis().Direction();
gp_Dir DY
= aPlanes[
0
].YAxis().Direction();
ElSLib::Parameters(aPlanes[
0
], aLines[
0
].Location(), u, v);
du
= aLines[
0
].Direction() *
DX;
dv
= aLines[
0
].Direction() *
DY;
aBuilder.UpdateEdge(aEdges[
0
],
new
Geom2d_Line(gp_Lin2d(gp_Pnt2d(u, v),
gp_Dir2d(du, dv))), aFaces[
0
], Precision::Confusion());
//
pcurve 1:
ElSLib::Parameters(aPlanes[
0
], aLines[
1
].Location(), u, v);
du
= aLines[
1
].Direction() *
DX;
dv
= aLines[
1
].Direction() *
DY;
aBuilder.UpdateEdge(aEdges[
1
],
new
Geom2d_Line(gp_Lin2d(gp_Pnt2d(u, v),
gp_Dir2d(du, dv))), aFaces[
0
], Precision::Confusion());
//
pcurve 2:
ElSLib::Parameters(aPlanes[
0
], aLines[
2
].Location(), u, v);
du
= aLines[
2
].Direction() *
DX;
dv
= aLines[
2
].Direction() *
DY;
aBuilder.UpdateEdge(aEdges[
2
],
new
Geom2d_Line(gp_Lin2d(gp_Pnt2d(u, v),
gp_Dir2d(du, dv))), aFaces[
0
], Precision::Confusion());
//
pcurve 3:
ElSLib::Parameters(aPlanes[
0
], aLines[
3
].Location(), u, v);
du
= aLines[
3
].Direction() *
DX;
dv
= aLines[
3
].Direction() *
DY;
aBuilder.UpdateEdge(aEdges[
3
],
new
Geom2d_Line(gp_Lin2d(gp_Pnt2d(u, v),
gp_Dir2d(du, dv))), aFaces[
0
], Precision::Confusion());
}
歷經艱辛,最后終于將一個面創建出來了,且可以在Draw Test Harness中顯示,如下圖所示:
Figure 2.2 A Face of the Box in Draw Test Harness
如上圖所示,在Darw Test Harness中,邊的顏色是有講究的,說明如下:
In Draw Test Harness, shapes are displayed using isoparametric curves. There is color coding for the Edges:
v A red edge is an isolated edge, which belongs to no faces;
v A green edge is a free boundary edge, which belongs to one face;
v A yello edge is shared edge, which belongs to at least two faces;
Figure 2.3 Color Coding for Edges in Draw Test Harness
如上圖所示,紅色的邊表示此邊不屬于任何一個面;綠色的邊表示此邊只屬于一個面;黃色的面表示此面至少屬于兩個面。
Figure 2.4 Shared Edges of the Box
如上圖所示,當創建出長方體的三個面時,側面與上下兩個底面相連的邊顯示成了黃色。其他邊都是綠色。
3. Finish the Box
將長方體的六個面按上述方式創建完畢后,需要驗證其正確性。于是將生成的數據導出為Brep格式,并與其他基本體進行布爾運算。
當導出的長方體為Shell時進行布爾運算會得到的也是殼體,如下圖所示的結果:
Figure 3.1 Box Shell Cut a Cylinder
當導出的長方體為Solid時,若面的方式未正確設置,則布爾運算會失敗,如下圖所示:
Figure 3.2 Box Solid Cut a Cylinder
如上圖所示,長方體與圓柱體的交線都已經計算出來了,但由于面的方向不對,不知道去除哪些面,保留哪些面。
將面的方向正確設置后,導出為Solid,進行布爾運算,結果正確,如下圖所示:
Figure 3.3 Box Cut Cylinder
測試用的Tcl腳本代碼如下所示:
#
# Tcl script to test the box BRep data.
# eryar@163.com
# 2014-11-16 21:55
# OpenCASCADE6.8.0
#
pload ALL
restore d
:/box.
brep b
pcylinder c
1.5
2
bop b c
bopcut r
vdisplay r
?
4. Conclusion
通過創建基本圖元,從而進一步來理解OpenCASCADE中的邊界表示BRep的數據結構。需要注意的事項有:
v 創建邊時,需要設置邊中幾何曲線的范圍;
v 創建邊時,需要設置正確與邊相關頂點的方向;
v 創建環時,需要確保環中邊的參數曲線PCurve能在參數空間中閉合;
v 創建面后,需要在邊中設置與面相關的幾何信息;
v 創建體時,需要所有面的方向正確;
注: 最后發現前不久寫的一篇文章有誤,說OpenCASCADE的BRep不是翼邊結構。其實從邊出發是可以找到與點、面相關的信息的。因為 OpenCASCADE中拓樸結構中有包含關系,所以頂點信息已經包含在邊中了,直接遍歷邊即可得到與此邊相關的頂點信息。所以,這樣看來 OpenCASCADE中的BRep表示法也是翼邊的數據結構。
原文如下:
邊界表示方式比較。因為一般的書籍上都詳細重 點描述了邊界表示中以為邊為核心的翼邊數據結構,所以有人想從這方面來給OpenCASCADE中的Brep表示法來給個說法。結合上面的類圖可知,從邊 出發并不能訪問到與這條邊相關的其他信息,如頂點的信息。如果硬是想在這里給個名分,倒是從點出發可以找到邊及面的幾何信息,所以OpenCASCADE 中的Brep表示法應該更像是以點為基礎的表示方法。OpenNURBS中通過ON_BrepTrim,可以訪問其他的信息,而ON_BrepTrim與 邊ON_BrepEdge的意義有些相似,所以應該是以邊為核心的翼邊結構了。
5. References
1. OpenCASCADE BRep vs. OpenNURBS Brep. OpenCASCADE BRep vs. OpenNURBS BRep
?
PDF Version and Source Code: OpenCASCADE Make Primitives-Box
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

