OpenCascade拓扑对象之:TopoDS_Shape对象及其子对象


TopoDS_Shape对象的子对象,作为一个链表保存在TopoDS_TShape对象中,如下:

class TopoDS_TShape : public Standard_Transient
{
...
private:
...

  TopoDS_ListOfShape myShapes;
  Standard_Integer myFlags;
};

这里,myShapes是一个TopoDS_Shape对象的列表。

首先,该列表放在BopoDS_TShape中,即放在共享对象中,是因为对一些共享对象的子对象,通常也是需要被共享的。例如:一个FaceWire对象,如果Face是被共享,Wire对象也是随之共享的。

其次,使用TopoDS_Shape对象,而不是TopoDS_TShape对象,因为子对象也可以具有方向、位置等信息,或者说子对象也可以是被多处共享的对象。例如:EdgeVertex对象,会把汇集到该Vertex的多条Edge共享,但对每个Edge来说,该Vertex的方向可能是不同的。

这里,父子关系是一个单向的关系,即每个对象记录了各自的子对象列表,非常简单。反过来的引用关系,没有记录,例如:wire所在的face是谁,没有记录。这个应当由如下原因:

A) 由于OCCT的对象共享基于句柄机制,使用了基于引用计数的技术。如果记录了反向拓扑对象的信息,则可能引起循环依赖。例如:Face记录了Edge的共享对象,而Edge又反向记录了Face对象,则会形成循环依赖,当对象自动释放时,可能两者都释放不了,这个是引用计数计数的一个问题。

B)出于共享的考虑。因为,可能一个Wire对象既可能是一个Face的外环,也可以是另一个Face的内环(例如:孔的情况)。特别是由于OCCT支持non-manifold情形,一个Wire可能被多个Face所共享,因此记录反向关系,管理起来会比较复杂,特别是模型频繁改变的情况下。

如此一来,要获取子对象所在的父对象,通常需要建表机制,通过遍历父对象的子对象,建立子对象和父对象对应关系的表,例如:遍历FaceEdge,建立Edgeface间的表,从而获得Edge邻接的Face对象列表。这个主要是TopExp包中的类TopExp提供了对应的建表方法,这个方法在OCCT的拓扑算法中是主要的方式,这个也导致OCCT的一些处理效率比较慢。

相对Parasolid中的简洁记录,例如:

struct LOOP_s // Loop

{

int node_id; // $d

union ATTRIB_GROUP_u attributes_groups; // $p

struct FIN_s *fin; // $p

struct FACE_s *face; // $p

struct LOOP_s *next; // $p

};

参见《Parasolid XT Format Reference

Loop直接记录了所在的faceOCCT的方式显然是低效的。

 

   对拓扑对象的子对象进行遍历,是不能直接遍历上述列表的,通常借助两个类:

  TopoDS_Iterator类:遍历拓扑对象的直属子对象,例如:遍历Face的子对象Wire对象。

  TopExp_Explorer类:可以遍历拓扑对象的任意子对象,例如:遍历Face的Edge对象。

  两个类都考虑了子对象对父对象的方向的继承(复合),这个是很关键的一步,决定了获取子对象的最终方向是否正确。

  如下是典型的代码:

      // Explore face to find all boundaries
      for (TopoDS_Iterator aIw(face); aIw.More(); aIw.Next()) {
        if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
        for (TopoDS_Iterator aIIe(aIw.Value()); aIIe.More(); aIIe.Next()) {     
          const TopoDS_Shape& edge = aIIe.Value();

  这里是依次遍历Face的裁剪环对象Wire,进而遍历Wire的Edge子对象。

  TopExp_Explorer anIt (theFace, TopAbs_EDGE);
  for ( ; anIt.More(); anIt.Next())
  {
    TopoDS_Edge aCurEdge =  TopoDS::Edge (anIt.Current());

  这里是直接遍历Face的Edge对象,对每个对象进行处理。