摘要Abstract:本文結合OpenCascade的BRep格式描述文檔和源程式,對BRep格式進行分析,詳細說明BRep的資料組織形式。結合源程式,可以對OpenCascade中Modeling Data子產品中的模型資料結構進行了解。 關鍵字Key Words:OpenCascade, BRep Format, ModelingData
OpenCascade BRep Format Description
摘要Abstract:本文結合OpenCascade的BRep格式描述文檔和源程式,對BRep格式進行分析,詳細說明BRep的資料組織形式。結合源程式,可以對OpenCascade中Modeling Data子產品中的模型資料結構進行了解。
關鍵字Key Words:OpenCascade, BRep Format, ModelingData
一、引言 Introduction
OpenCascade中的BRep格式主要用來存儲3D模型,也可用來存儲由下列元素組成的模型:vertices, edges, wires, faces, shells, solids, compsolids, compounds, edge triangulations, face triangulations, polylines on triangulations, space location and orientation.
本格式的目的就是為了便于了解,也使用了類似BNF的定義方式。以下章節都是按下面的格式組織的:
l 該部分的示例;
l 該部分的類BNF定義;
l 該部分的詳細說明;
l 該部分的源程式片段。
二、通用結構 Format Common Structure
BRep格式檔案的讀寫采用了ASCII的編碼方式,該格式的資料都是文本形式存儲。
BRep格式使用了下面的BNF術語:
1) <\n>:換行;
2) <_\n>:
3) <_>:空格;
4) <flag>:标志位:0和1;
5) <int>:整數,範圍-231到231-1;
6) <real>:實數,範圍-1.7976931348623159X10308到1.7976931348623158X10308;
7) <2D point>:二維點,兩個實數;
8) <3D point>:三維點,三個實數;
9) <2D direction>:二維方向矢量,兩個實數,平方和為1,即為機關方向矢量;
10) <3D direction>:三維方向矢量,三個實數,平方和為1,即為機關方向矢量;
11) <+>
BRep格式包含以下部分:
1) <content type>
2) <version>
3) <locations>
4) <geometry>
5) <shapes>
<content type>部分:
<content type>也可以有其它的值。
<version>部分:
不同版本之間的差別将會在本文檔中說明。
三、<locations>部分 Section <locations>
示例:
BNF 定義:
詳細說明:
<location data 1>定義了3X4的矩陣Q,描述了三維空間的線性變換,并滿足如下約定:
矩陣Q是線性變換矩陣,它可以通過矩陣乘法将一個點(x, y, z)變換成另外一點(u, v, w):
Q也可能是以下基本變換矩陣的組合:
1) 平移變換矩陣:
2) 繞任意軸旋轉的變換矩陣,軸的方向為D(Dx, Dy, Dz),旋轉角度ψ:
3) 縮放變換矩陣:
4) 中心對稱變換矩陣:
5) 軸對稱變換矩陣:
6) 平面對稱變換矩陣:
<location data 2>解釋為組合變換的幂。<location data 2>是整數對li, pi的序列。這個序列将被解釋為:
Lli是<location record>部分的變換矩陣。
讀取<locations>部分的類為TopTools_LocationSet,程式代碼如下所示:
1 //=======================================================================
2 //function : Read
3 //purpose :
4 //=======================================================================
5 void TopTools_LocationSet::Read(Standard_IStream& IS)
6 {
7 myMap.Clear();
8
9 char buffer[255];
10 Standard_Integer l1,p;
11
12 IS >> buffer;
13 if (strcmp(buffer,"Locations")) {
14 cout << "Not a location table "<<endl;
15 return;
16 }
17
18 Standard_Integer i, nbLoc;
19 IS >> nbLoc;
20
21 TopLoc_Location L;
22 gp_Trsf T;
23
24 //OCC19559
25 Message_ProgressSentry PS(GetProgress(), "Locations", 0, nbLoc, 1);
26 for (i = 1; i <= nbLoc&& PS.More(); i++, PS.Next()) {
27 if ( !GetProgress().IsNull() )
28 GetProgress()->Show();
29
30 Standard_Integer typLoc;
31 IS >> typLoc;
32
33 if (typLoc == 1) {
34 ReadTrsf(T,IS);
35 L = T;
36 }
37
38 else if (typLoc == 2) {
39 L = TopLoc_Location();
40 IS >> l1;
41 while (l1 != 0) {
42 IS >> p;
43 TopLoc_Location L1 = myMap(l1);
44 L = L1.Powered(p) *L;
45 IS >> l1;
46 }
47 }
48
49 if (!L.IsIdentity()) myMap.Add(L);
50 }
51 }
雖然代碼風格不好,縮進、括号什麼的都不工整,看起來很吃力,但是結合源程式,對上面的詳細說明的了解還是很有幫助的。
其中變量nbLoc是<location record count>的值,成員變量myMap是TopLoc_Location的一個map。當是<location record 1>時把<location data 1>都放到TopLoc_Location的map中。當是<location record 2>時将li的變換矩陣TopLoc_Location乘pi次方。<flag>0表示<location data 2>的結束。
四、<geometry>部分
<geometry>包含以下子部分:
1.<2D curves>
2.<3D curves>
3.<3D polygons>
4.<polygons on triangulations>
5.<surfaces>
6.<triangulations>
讀取<geometry>部分的類為BRepTools_ShapeSet,程式代碼如下所示:
1 //=======================================================================
2 //function : ReadGeometry
3 //purpose :
4 //=======================================================================
5 void BRepTools_ShapeSet::ReadGeometry(Standard_IStream& IS)
6 {
7 //OCC19559
8 myCurves2d.SetProgress(GetProgress());
9 myCurves.SetProgress(GetProgress());
10 mySurfaces.SetProgress(GetProgress());
11
12 if ( !GetProgress().IsNull()) {
13 if( GetProgress()->UserBreak() ) return;
14 GetProgress()->NewScope ( 15, "2D Curves" );
15 }
16 myCurves2d.Read(IS);
17
18 if ( !GetProgress().IsNull()) {
19 if( GetProgress()->UserBreak() ) return;
20 GetProgress()->EndScope();
21 GetProgress()->Show();
22
23 GetProgress()->NewScope ( 15, "3D Curves" );
24 }
25 myCurves.Read(IS);
26
27 if ( !GetProgress().IsNull()) {
28 if( GetProgress()->UserBreak() ) return;
29 GetProgress()->EndScope();
30 GetProgress()->Show();
31
32 GetProgress()->NewScope ( 10, "3D Polygons" );
33 }
34 ReadPolygon3D(IS);
35 if ( !GetProgress().IsNull() ) {
36 if( GetProgress()->UserBreak() ) return;
37 GetProgress()->EndScope();
38 GetProgress()->Show();
39
40 GetProgress()->NewScope ( 10, "Polygons On Triangulation" );
41 }
42 ReadPolygonOnTriangulation(IS);
43 if ( !GetProgress().IsNull()) {
44 if( GetProgress()->UserBreak() ) return;
45 GetProgress()->EndScope();
46 GetProgress()->Show();
47
48 GetProgress()->NewScope ( 10, "Surfaces" );
49 }
50 mySurfaces.Read(IS);
51 if ( !GetProgress().IsNull() ) {
52 if( GetProgress()->UserBreak() ) return;
53 GetProgress()->EndScope();
54 GetProgress()->Show();
55
56 GetProgress()->NewScope ( 15, "Triangulations" );
57 }
58 ReadTriangulation(IS);
59 if ( !GetProgress().IsNull()) {
60 if( GetProgress()->UserBreak() ) return;
61 GetProgress()->EndScope();
62 GetProgress()->Show();
63 }
64 }
4.1 子部分<3D curves>
BNF定義:
由Curves開始,後面是曲線的數量,再下面是每條曲線的具體資料。
讀取<curves>部分的類為GeomTools_CurveSet,程式代碼如下所示:
1 #define LINE 1
2 #define CIRCLE 2
3 #define ELLIPSE 3
4 #define PARABOLA 4
5 #define HYPERBOLA 5
6 #define BEZIER 6
7 #define BSPLINE 7
8 #define TRIMMED 8
9 #define OFFSET 9
10 //=======================================================================
11 //function : ReadCurve
12 //purpose :
13 //=======================================================================
14 Standard_IStream& GeomTools_CurveSet::ReadCurve(Standard_IStream& IS,
15 Handle(Geom_Curve)& C)
16 {
17 Standard_Integer ctype;
18
19 try {
20 OCC_CATCH_SIGNALS
21 IS >> ctype;
22 switch (ctype) {
23
24 case LINE :
25 {
26 Handle(Geom_Line) CC;
27 IS >> CC;
28 C = CC;
29 }
30 break;
31
32 case CIRCLE :
33 {
34 Handle(Geom_Circle) CC;
35 IS >> CC;
36 C = CC;
37 }
38 break;
39
40 case ELLIPSE :
41 {
42 Handle(Geom_Ellipse) CC;
43 IS >> CC;
44 C = CC;
45 }
46 break;
47
48 case PARABOLA :
49 {
50 Handle(Geom_Parabola) CC;
51 IS >> CC;
52 C = CC;
53 }
54 break;
55
56 case HYPERBOLA :
57 {
58 Handle(Geom_Hyperbola) CC;
59 IS >> CC;
60 C = CC;
61 }
62 break;
63
64 case BEZIER :
65 {
66 Handle(Geom_BezierCurve) CC;
67 IS >> CC;
68 C = CC;
69 }
70 break;
71
72 case BSPLINE :
73 {
74 Handle(Geom_BSplineCurve) CC;
75 IS >> CC;
76 C = CC;
77 }
78 break;
79
80 case TRIMMED :
81 {
82 Handle(Geom_TrimmedCurve) CC;
83 IS >> CC;
84 C = CC;
85 }
86 break;
87
88 case OFFSET :
89 {
90 Handle(Geom_OffsetCurve) CC;
91 IS >> CC;
92 C = CC;
93 }
94 break;
95
96 default:
97 {
98 Handle(Geom_Curve) CC;
99 GeomTools::GetUndefinedTypeHandler()->ReadCurve(ctype,IS,CC);
100 C = CC;
101 }
102 }
103 }
104 catch(Standard_Failure) {
105 #ifdef DEB
106 Handle(Standard_Failure) anExc = Standard_Failure::Caught();
107 cout <<"EXCEPTION in GeomTools_CurveSet::ReadCurve(..)!!!" << endl;
108 cout << anExc << endl;
109 #endif
110 C = NULL;
111 }
112 return IS;
113 }
因為重載了操作符>>,使不同的類調用了不同的處理函數。
因為讀取點和方向用得很頻繁,是以将讀取點和方向的函數程式先列出如下所示:
1 //=======================================================================
2 //function : ReadPnt
3 //purpose :
4 //=======================================================================
5 static Standard_IStream& operator>>(Standard_IStream& IS, gp_Pnt& P)
6 {
7 Standard_Real X=0.,Y=0.,Z=0.;
8 IS >> X >> Y >> Z;
9 P.SetCoord(X,Y,Z);
10 return IS;
11 }
12
13 //=======================================================================
14 //function : ReadDir
15 //purpose :
16 //=======================================================================
17 static Standard_IStream& operator>>(Standard_IStream& IS, gp_Dir& D)
18 {
19 Standard_Real X=0.,Y=0.,Z=0.;
20 IS >> X >> Y >> Z;
21 D.SetCoord(X,Y,Z);
22 return IS;
23 }
4.1.1 <3D curve record 1>-Line
<3D curve record 1>定義了直線。直線資料由一個三維點P和一個三維方向矢量D組成。通過點P且方向為D的直線由下面的參數方程來定義:
示例資料表示的直線為通過點P(1,0,3),方向D(0,1,0),得到的參數方程為:
讀取直線部分的程式代碼如下所示:
1 //=======================================================================
2 //function : ReadCurve
3 //purpose :
4 //=======================================================================
5 static Standard_IStream& operator>>(Standard_IStream& IS,
6 Handle(Geom_Line)& L)
7 {
8 gp_Pnt P(0.,0.,0.);
9 gp_Dir AX(1.,0.,0.);
10 IS >> P >> AX;
11 L = new Geom_Line(P,AX);
12 return IS;
13 }
4.1.2 <3D curve record 2>-Circle
<3D curve record 2>定義了圓。圓的資料包含一個三維點P,一個正交坐标系的三個軸的方向N,Dx,Dy,還有一個非負的實數r。其中點P為圓心坐标,圓位于平面的法向量為N的平面上,圓的半徑為r。圓的參數方程如下所示:
示例資料表示的圓為:圓心P(1,2,3),位于平面的法向量N(0,0,1),圓的方向Dx=(1,0,-0),Dy=(-0,1,0),半徑r=4,其參數方向為:
讀取圓部分的程式代碼如下所示:
1 //=======================================================================
2 //function : ReadCurve
3 //purpose :
4 //=======================================================================
5 static Standard_IStream& operator>>(Standard_IStream& IS,
6 Handle(Geom_Circle)& C)
7 {
8 gp_Pnt P(0.,0.,0.);
9 gp_Dir A(1.,0.,0.),AX(1.,0.,0.),AY(1.,0.,0.);
10 Standard_Real R=0.;
11 IS >> P >> A >> AX >> AY >> R;
12 C = new Geom_Circle(gp_Ax2(P,A,AX),R);
13 return IS;
14 }
4.1.3 <3D curve record 3>-Ellipse
<3D curve record 3>定義了橢圓。橢圓的資料包含三維點P,三維正交坐标系N、Dmaj、Dmin和兩個非負實數rmaj和rmin,且rmin<=rmaj。橢圓位于中心點P,法向量為N的平面上,且長軸、短軸的方向分别為Dmaj, Dmin,長軸、短軸上的半徑分别為rmaj, rmin。橢圓的參數方程定義如下所示:
示例資料表示的橢圓的中心點P=(1,2,3),平面的法向量N=(0,0,1),長軸方向Dmaj=(1,0,-0),短軸方向Dmin=(-0,1,0),長軸半徑為5,短軸半徑為4,
讀取橢圓部分的程式代碼如下所示:
1 //=======================================================================
2 //function : ReadCurve
3 //purpose :
4 //=======================================================================
5 static Standard_IStream& operator>>(Standard_IStream& IS,
6 Handle(Geom_Ellipse)& E)
7 {
8 gp_Pnt P(0.,0.,0.);
9 gp_Dir A(1.,0.,0.),AX(1.,0.,0.),AY(1.,0.,0.);
10 Standard_Real R1=0.,R2=0.;
11 IS >> P >> A >> AX >> AY >> R1 >> R2;
12 E = new Geom_Ellipse(gp_Ax2(P,A,AX),R1,R2);
13 return IS;
14 }
4.1.4 <3D curve record 4>-Parabola
<3D curve record 4>定義了抛物線。抛物線資料包含三維點P,三維正交坐标系坐标軸方向N,Dx,Dy和一個非負的實數f。抛物線通過點P,且位于法向量為N的平面上,焦點長度為f,其參數方程如下所示:
示例資料表示的抛物線過點P=(1,2,3),位于平面的法向N=(0,0,1),抛物線的另兩個軸方向Dx=(1,0,-0),Dy=(-0,1,0),焦點長度f=16。參數方程為:
讀取抛物線部分的程式代碼如下所示:
1 //=======================================================================
2 //function : ReadCurve
3 //purpose :
4 //=======================================================================
5 static Standard_IStream& operator>>(Standard_IStream& IS,
6 Handle(Geom_Parabola)& C)
7 {
8 gp_Pnt P(0.,0.,0.);
9 gp_Dir A(1.,0.,0.),AX(1.,0.,0.),AY(1.,0.,0.);
10 Standard_Real R1=0.;
11 IS >> P >> A >> AX >> AY >> R1;
12 C = new Geom_Parabola(gp_Ax2(P,A,AX),R1);
13 return IS;
14 }
4.1.5 <3D curve record 5>-Hyperbola
<3D curve record 5>定義了雙曲線。雙曲線定義資料有三維點P,三維正交坐标系坐标軸方向為N,Dx,Dy和兩個非負實數Kx,Ky。雙曲線過P點且法向量為N的平面上,其參數方程如下所示:
示例資料表示的雙曲線過點P=(1,2,3)且位于的平面的法向N=(0,0,1),其它的資料Dx=(1,0,-0),Dy=(-0,1,0),Kx=5和Ky=4。其參數方程為:
讀取雙曲線部分的程式代碼如下所示:
1 //=======================================================================
2 //function : ReadCurve
3 //purpose :
4 //=======================================================================
5 static Standard_IStream& operator>>(Standard_IStream& IS,
6 Handle(Geom_Hyperbola)& H)
7 {
8 gp_Pnt P(0.,0.,0.);
9 gp_Dir A(1.,0.,0.),AX(1.,0.,0.),AY(1.,0.,0.);
10 Standard_Real R1=0.,R2=0.;
11 IS >> P >> A >> AX >> AY >> R1 >> R2;
12 H = new Geom_Hyperbola(gp_Ax2(P,A,AX),R1,R2);
13 return IS;
14 }
4.1.6 <3D curve record 6>-Bezier Curve
<3D curve record 6>定義了Bezier曲線。Bezier曲線資料包含有理标志r,曲線的次數m(degree m <= 25檢視源代碼可知OpenCascade可處理的B樣條次數不超過25)和帶權的控制點(weight poles)。當有理标志位r=0時,weight poles就是m+1個三維點:B0,B1...Bn;當有理标志位r=1時,weight poles就是帶權的控制點B0 h0... Bm hm。Bi是三維點,hi是[0,m]正實數,即權因子。當有理标志位r=0時,即不是有理Bezier曲線時,hi=1。Bezier曲線參數方程如下所示:
示例資料表示的Bezier曲線是有理Bezier曲線,因其有理标志位r=1,次數m=2,帶權控制點及權因子分别為:B0=(0,1,0),h0=4,B1=(1,-2,0),h1=5,B2=(2,3,0),h2=6。Bezier曲線的參數方程如下所示:
讀取Bezier曲線部分的程式代碼如下所示:
1 //=======================================================================
2 //function : ReadCurve
3 //purpose :
4 //=======================================================================
5 static Standard_IStream& operator>>(Standard_IStream& IS,
6 Handle(Geom_BezierCurve)& B)
7 {
8 Standard_Boolean rational=Standard_False;
9 IS >> rational;
10
11 // poles and weights
12 Standard_Integer i=0,degree=0;
13 IS >> degree;
14
15 TColgp_Array1OfPnt poles(1,degree+1);
16 TColStd_Array1OfReal weights(1,degree+1);
17
18 for (i = 1; i <= degree+1; i++) {
19 IS >> poles(i);
20 if (rational)
21 IS >> weights(i);
22 }
23
24 if (rational)
25 B = new Geom_BezierCurve(poles,weights);
26 else
27 B = new Geom_BezierCurve(poles);
28
29 return IS;
30 }
4.1.7 <3D curve record 7>-B-Spline curve
<3D curve record 7>定義了B-Spline曲線。B-Spline曲線包含了有理标志位r,曲線次數m<=25,控制點數n>=2,重節點數k,帶權控制點wieght poles和重節點multiplicity knots。
當有理标志位r=0時,是非有理B樣條曲線,weight poles有n個三維點B1,...,Bn;當有理标志位r=1時,是有理B樣條曲線,weight poles是n個帶權控制點對:B1, h1, .... Bn, hn。這裡Bi表示一個三維點,hi表示一個[0,1]正實數。當有理标志位r=0時,hi=1。
重節點有k對u1, q1, ... uk, qk。這裡ui是重複度為qi>=1的節點。
B-Spline曲線的參數方程如下所示:
其中Ni,j有如下的遞歸定義:
示例資料表示的B樣條曲線為:有理标志位r=1,次數m=1,控制點數n=3,重節點數k=5,帶權控制點:B1=(0,1,0),h1=4,B2=(1,-2,0),h2=5,B3=(2,3,0),h3=6;重節點u1=0,q1=1,u2=0.25,q2=1,u3=0.5,q3=1,u4=0.75,q4=1,u5=1,q5=1。B-Spline曲線的參數方程如下所示:
讀取B-Spline曲線部分的程式代碼如下所示:
1 //=======================================================================
2 //function : ReadCurve
3 //purpose :
4 //=======================================================================
5 static Standard_IStream& operator>>(Standard_IStream& IS,
6 Handle(Geom_BSplineCurve)& B)
7 {
8
9 Standard_Boolean rational=Standard_False,periodic=Standard_False;
10 IS >> rational >> periodic;
11
12 // poles and weights
13 Standard_Integer i=0,degree=0,nbpoles=0,nbknots=0;
14 IS >> degree >> nbpoles >> nbknots;
15
16 TColgp_Array1OfPnt poles(1,nbpoles);
17 TColStd_Array1OfReal weights(1,nbpoles);
18
19 for (i = 1; i <= nbpoles; i++) {
20 IS >> poles(i);
21 if (rational)
22 IS >> weights(i);
23 }
24
25 TColStd_Array1OfReal knots(1,nbknots);
26 TColStd_Array1OfInteger mults(1,nbknots);
27
28 for (i = 1; i <= nbknots; i++) {
29 IS >> knots(i) >> mults(i);
30 }
31
32 if (rational)
33 B = new Geom_BSplineCurve(poles,weights,knots,mults,degree,periodic);
34 else
35 B = new Geom_BSplineCurve(poles,knots,mults,degree,periodic);
36
37 return IS;
38 }
4.1.8 <3D curve record 8>-Trimmed Curve
<3D curve record 8>定義了裁剪曲線(trimmed curve)。裁剪曲線資料包含:兩個實數umin,umax和<3D curve record>,且umin<umax。裁剪曲線是将<3D curve record>描述的曲線B限制在[umin,umax]。裁剪曲線的參數方程如下所示:
示例資料表示的裁剪曲線為:umin=-4,umax=5,曲線B(u)=(1,2,3)+u(1,0,0)。裁剪曲線的參數方程如下所示:
讀取裁剪曲線部分的程式代碼如下所示:
1 //=======================================================================
2 //function : ReadCurve
3 //purpose :
4 //=======================================================================
5
6 static Standard_IStream& operator>>(Standard_IStream& IS,
7 Handle(Geom_TrimmedCurve)& C)
8 {
9 Standard_Real p1=0.,p2=0.;
10 IS >> p1 >> p2;
11 Handle(Geom_Curve) BC;
12 GeomTools_CurveSet::ReadCurve(IS,BC);
13 C = new Geom_TrimmedCurve(BC,p1,p2);
14 return IS;
15 }
4.1.9 <3D curve record 9>-Offset Curve
<3D curve record 9>定義了偏移曲線(offset curve)。偏移曲線的資料包含偏移距離d,偏移方向D和曲線資料<3D curve record>。偏移曲線是将<3D curve record>描述的曲線沿矢量
偏移距離d後的結果。偏移曲線的參數方程如下所示:
示例資料表示的偏移曲線為偏移距離d=2,方向D=(0,1,0),基曲線B(u)=(1,2,3)+u(1,0,0),其參數方程如下所示:
讀取偏移曲線部分程式代碼如下所示:
1 //=======================================================================
2 //function : ReadCurve
3 //purpose :
4 //=======================================================================
5 static Standard_IStream& operator>>(Standard_IStream& IS,
6 Handle(Geom_OffsetCurve)& C)
7 {
8 Standard_Real p=0.;
9 IS >> p;
10 gp_Dir D(1.,0.,0.);
11 IS >> D;
12 Handle(Geom_Curve) BC;
13 GeomTools_CurveSet::ReadCurve(IS,BC);
14 C = new Geom_OffsetCurve(BC,p,D);
15 return IS;
16 }