Posted on 2020-06-16 11:04
eryar 阅读(2786)
评论(0) 编辑 收藏 引用 所属分类:
2.OpenCASCADE
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添加到列表中或从列表中删除。
为了方便大家在移动端也能看到我的博文和讨论交流,现已注册微信公众号,欢迎大家扫描下方二维码关注。