BRep Builder
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添加到列表中或从列表中删除。