OpenCASCADE Make Primitives-Box

OpenCASCADE Make Primitives-Box

eryar@163.com html

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 shell

1. Introduction 數據結構

OpenCASCADE的Toolit TKPrim中提供了基本圖元的建立功能,像Box, Cylinder, Sphere等等。直接使用Package BRepPrimAPI中的功能,能夠方便地建立出基本圖元,而不用關心其內部的數據結構。 測試

wps_clip_image-27189

Figure 1. BRepPrimAPI Package classes ui

爲 了理解ModelingData模塊中OpenCASCADE的邊界表示法BRep數據結構,決定參考其實現,本身來建立出基本圖元,進而理解其中的 BRep數據結構。本文以最簡單的長方體Box入手,從點、邊到體的建立出一個形狀。並將構造的形狀在Draw Test Harness中進行顯示,且進行布爾運算,來驗證構造結果的正確性。 spa

2.Make a Face of the Box rest

在OpenCASCADE的包BRepPrim中,構造長方體的方式是形狀的根結點出發到葉子結點,即從Shell到Face到Wire最後到Vertex,以下圖所示: htm

wps_clip_image-5617

Figure 2.1 Data structure of a Shape blog

爲了程序演示的清晰,本文中採用與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中顯示,以下圖所示:

wps_clip_image-17990

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;

wps_clip_image-27097

Figure 2.3 Color Coding for Edges in Draw Test Harness

如上圖所示,紅色的邊表示此邊不屬於任何一個面;綠色的邊表示此邊只屬於一個面;黃色的面表示此面至少屬於兩個面。

wps_clip_image-13274

Figure 2.4 Shared Edges of the Box

如上圖所示,當建立出長方體的三個面時,側面與上下兩個底面相連的邊顯示成了黃色。其餘邊都是綠色。

3.Finish the Box

將長方體的六個面按上述方式建立完畢後,須要驗證其正確性。因而將生成的數據導出爲Brep格式,並與其餘基本體進行布爾運算。

當導出的長方體爲Shell時進行布爾運算會獲得的也是殼體,以下圖所示的結果:

wps_clip_image-88

Figure 3.1 Box Shell Cut a Cylinder

當導出的長方體爲Solid時,若面的方式未正確設置,則布爾運算會失敗,以下圖所示:

wps_clip_image-331

Figure 3.2 Box Solid Cut a Cylinder

如上圖所示,長方體與圓柱體的交線都已經計算出來了,但因爲面的方向不對,不知道去除哪些面,保留哪些面。

將面的方向正確設置後,導出爲Solid,進行布爾運算,結果正確,以下圖所示:

wps_clip_image-22873

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

相關文章
相關標籤/搜索