BRep Builder
eryar@163.com
1 Introduction
類BRep_Builder提供了創建、修改BRep模型的方法。使用這個類,你可以從底層自己構建BRep體,前提條件是你要對BRep模型的數據結構有一定理解。邊界表示法BRep的重點在邊界的定義,打開BRep_Builder的類圖:
可以看到其中重載了很多UpdateEdge函數,每個UpdateEdge函數都修改了Edge中的幾何數據,包括邊界的定義數據。若能理解每個UpdateEdge函數,則對OpenCASCADE的BREP數據結構就能理解了。本文主要介紹其中兩個函數的用法:Add和Remove。
2 Add Shape
BRep_Builder的Add函數的字面意思是將一個Shape添加到另外一個Shape中。因這個函數的實現比較簡單,把源碼列出如下:
void TopoDS_Builder::Add (TopoDS_Shape& aShape, const TopoDS_Shape& aComponent) const { // From now the Component cannot be edited aComponent.TShape()->Free(Standard_False); // Note that freezing aComponent before testing if aShape is free // prevents from self-insertion // but aShape will be frozen when the Exception is raised if (aShape.Free()) { static const unsigned int aTb[9]= { //COMPOUND to: (1<<((unsigned int)TopAbs_COMPOUND)), //COMPSOLID to: (1<<((unsigned int)TopAbs_COMPOUND)), //SOLID to: (1<<((unsigned int)TopAbs_COMPOUND)) | (1<<((unsigned int)TopAbs_COMPSOLID)), //SHELL to: (1<<((unsigned int)TopAbs_COMPOUND)) | (1<<((unsigned int)TopAbs_SOLID)), //FACE to: (1<<((unsigned int)TopAbs_COMPOUND)) | (1<<((unsigned int)TopAbs_SHELL)), //WIRE to: (1<<((unsigned int)TopAbs_COMPOUND)) | (1<<((unsigned int)TopAbs_FACE)), //EDGE to: (1<<((unsigned int)TopAbs_COMPOUND)) | (1<<((unsigned int)TopAbs_SOLID)) | (1<<((unsigned int)TopAbs_WIRE)), //VERTEX to: (1<<((unsigned int)TopAbs_COMPOUND)) | (1<<((unsigned int)TopAbs_SOLID)) | (1<<((unsigned int)TopAbs_FACE)) | (1<<((unsigned int)TopAbs_EDGE)), //SHAPE to: 0 }; // const unsigned int iC=(unsigned int)aComponent.ShapeType(); const unsigned int iS=(unsigned int)aShape.ShapeType(); // if ((aTb[iC] & (1<<iS)) != 0) { TopoDS_ListOfShape& L = aShape.TShape()->myShapes; L.Append(aComponent); TopoDS_Shape& S = L.Last(); // // compute the relative Orientation if (aShape.Orientation() == TopAbs_REVERSED) S.Reverse(); // // and the Relative Location const TopLoc_Location& aLoc=aShape.Location(); if (!aLoc.IsIdentity()) S.Move(aLoc.Inverted()); // // Set the TShape as modified. aShape.TShape()->Modified(Standard_True); } else { throw TopoDS_UnCompatibleShapes("TopoDS_Builder::Add"); } } else { throw TopoDS_FrozenShape("TopoDS_Buider::Add"); } }
Add函數通過一個靜態的檢查列表,來檢查添加的Shape是不是合法的,即FACE只能添加到SHELL和COMPOUND中,EDGE只能添加到WIRE,SOLID和COMPOUND中等。添加之后還檢查了Shape的ORIENTATION及位置信息並作相應調整。不滿足條件的情況都會拋出異常,所以對於Add函數需要增加異常處理邏輯。
使用這個函數需要注意的是這個Add只是簡單的將Shape添加到TShape的Shape表中,並沒有維護BREP的邊界信息。
3 Remove Shape
與Add對應的有Remove函數,可以從一個Shape中刪除一個子Shape。還是打開源碼,有源碼有真相:
//======================================================================= //function : Remove //purpose : Remove a Shape from an other one //======================================================================= void TopoDS_Builder::Remove (TopoDS_Shape& aShape, const TopoDS_Shape& aComponent) const { // check if aShape is not Frozen TopoDS_FrozenShape_Raise_if (!aShape.Free(),"TopoDS_Builder::Remove"); // compute the relative Orientation and Location of aComponent TopoDS_Shape S = aComponent; if (aShape.Orientation() == TopAbs_REVERSED) S.Reverse(); S.Location(S.Location().Predivided(aShape.Location())); TopoDS_ListOfShape& L = aShape.TShape()->myShapes; TopoDS_ListIteratorOfListOfShape It(L); while (It.More()) { if (It.Value() == S) { L.Remove(It); aShape.TShape()->Modified(Standard_True); break; } It.Next(); } }
從源碼中可知,Remove實現的邏輯也是很簡單的:
l 檢查Shape是不是Free的,若不是則拋出異常;
l 計算要刪除Component的ORIENTATION和LOCATION;
l 從Shape列中查找Component,若找到將其從列表中刪除;
刪除操作比添加操作要簡單,一個是把已有的數據刪除,一個是從無到有的構建數據。從函數實現代碼來看,刪除操作也是簡單的從Shape列表中刪除指定的Shape。刪除之后多余的邊界信息還會存在原來的Shape中,要確保刪除的Shape之后沒有多余信息,還需要刪除沒有使用的PCurves。
上圖所示為刪除一個底面的圓柱體。
4 Conclusion
類BRep_Builder的操作需要以充分理解OpenCASCADE的BREP數據結構為前提,因為其Add和Remove函數並沒有提供維護邊界的功能,只是將指定的Shape添加到列表中或從列表中刪除。