eryar

PipeCAD - Plant Piping Design Software.
RvmTranslator - Translate AVEVA RVM to OBJ, glTF, etc.
posts - 603, comments - 590, trackbacks - 0, articles - 0

BRep Builder

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函数,则对OpenCASCADEBREP数据结构就能理解了。本文主要介绍其中两个函数的用法:AddRemove

 2 Add Shape

BRep_BuilderAdd函数的字面意思是将一个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只能添加到SHELLCOMPOUND中,EDGE只能添加到WIRESOLIDCOMPOUND中等。添加之后还检查了ShapeORIENTATION及位置信息并作相应调整。不满足条件的情况都会抛出异常,所以对于Add函数需要增加异常处理逻辑。

使用这个函数需要注意的是这个Add只是简单的将Shape添加到TShapeShape表中,并没有维护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实现的逻辑也是很简单的:

检查Shape是不是Free的,若不是则抛出异常;

计算要删除ComponentORIENTATIONLOCATION

Shape列中查找Component,若找到将其从列表中删除;

 

删除操作比添加操作要简单,一个是把已有的数据删除,一个是从无到有的构建数据。从函数实现代码来看,删除操作也是简单的从Shape列表中删除指定的Shape。删除之后多余的边界信息还会存在原来的Shape中,要确保删除的Shape之后没有多余信息,还需要删除没有使用的PCurves

 

上图所示为删除一个底面的圆柱体。

 4 Conclusion

BRep_Builder的操作需要以充分理解OpenCASCADEBREP数据结构为前提,因为其AddRemove函数并没有提供维护边界的功能,只是将指定的Shape添加到列表中或从列表中删除。


为了方便大家在移动端也能看到我的博文和讨论交流,现已注册微信公众号,欢迎大家扫描下方二维码关注。
Shing Liu(eryar@163.com)

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理