occt_modeling_data(一)——拓扑

下面是我基于opencascade英文文档中关于occt_modeling_data中Topology部分进行的翻译,英文好的还是建议直接看文档,部分我不肯定的地方我会附上英文原句。如发现有错误欢迎评论区留言。

OCCT Topolog允许用户访问和操纵物体的数据,且不需要处理它们的2D或3D表示。而OCCT Geometry提供了一个从坐标或特征值方面关于物体的描述,Topology在特征空间描述数据结构。这些描述使用位置和这个空间部分的限制。

拓扑库允许你构建纯拓扑数据结构。拓扑定义了简单几何实体之间的关系。通过这种方式,你可以使简单实体的集合构建复杂形状。由于一个内置非流形(non-manifold)(或者称为混合维度)特征,你可以构建模型,混合以下实体:

  • 0D 实体 —— 比如点
  • 1D 实体 —— 比如曲线
  • 2D 实体 —— 比如曲面
  • 3D 实体 —— 比如体

例如,你可以构建一个由几个不同的包含内嵌曲线和曲面且与外部边界连通或非连通的单一实体。

抽象拓扑数据结构描述一个基础实体 —— 一个形状,可以被分为如下几种组成拓扑:

  • 顶点 —— 一个零维形状,对应几何中的点
  • 边 —— 一个对应一条曲线的形状,每个端点有一个顶点作为边界
  • 线框 —— 连接点的边的一个序列
  • 面 —— 一个平面的部分(2D几何)或一个由闭合线框作为边界的曲面(3D几何)的部分
  • 壳 —— 由线框边界的一些边连接的面的集合
  • 刚体 —— 由一个壳作为边界的3D空间的一部分
  • 复合刚体 —— 刚体的集合

线框和刚体要么是无限的,要么是闭合的。

有着3D隐式几何的面也可以借助连通三角形的几何近似隐式曲面。曲面可以是未被定义的,只保留由三角形表示的面。如果是这样,模型就是纯多边形。

拓扑定义了简单几何实体之间的关系,这就能互相连接以表示复杂形状。

抽象拓扑(Abstract Topology)由六个包提供。前三个包描述了在Open CASCADE Technology中使用的拓扑数据结构:

  • TopAbs 包给拓扑驱动的应用提供了通用的资源。这包含了用于描述基础拓扑概念的枚举类型:topological shapeorientationstate。它也提供了管理这些枚举类型的方法。
  • TopLoc 包给处理3D局部坐标系统提供了资源:Datum3DLocationDatum3D 描述了一个基础的坐标系统,而 Location 包含了一系列基础坐标系统。
  • TopoDS 包描述了建模和构建纯拓扑的数据结构的类。

三个额外的包提供了工具区访问和操作这个抽象拓扑:

  • TopTools 包提供了基础工具用于拓扑数据结构
  • TopExp 包提供了类去查找和操作描述于TopoDS包中的拓扑数据结构
  • BRepTools 包提供了查找、操作、读取和写入BRep数据结构。这些更复杂的数据结构将拓扑描述和额外的几何信息进行组合,然后包含评估相同物体不同可能表征相同性的规则,例如,一个点。


形状内容(Shape content)

TopAbs 包提供了描述基础拓扑含义的枚举类型,以及处理这些枚举类型的方法。它不包含类。这个包已经与拓扑的剩余部分分离,因为它包含的概念是所有拓扑工具都足够通用的。通过保持建模资源的独立,避免了枚举类型的重定义。TopAbs 包定义了三个概念:

  • Type —— TopAbs_ShapeEnum
  • Orientation —— TopAbs_Orientation
  • State —— StateTopAbs_State

拓扑类型(Topological types)

TopAbs 包含了 TopAbs_ShapeEnum 枚举类型,下面列举了不同的拓扑种类:

  • COMPOUND —— 一组任意类型的拓扑物体
  • COMPSOLID —— 复合刚体是一个由面连接的刚体集合。它将WIRE和SHELL的概念扩展到刚体
  • SOLID —— 由壳限制的空间的一部分。它是三维的。
  • SHELL —— 由边相连的面集。一个壳可能是开放也可能是闭合的。
  • FACE —— 在2D它是一个平面的一部分;在3D它是一个曲面的一部分。它的几何是被轮廓所约束(剪裁(trimmed))的。它是二维的。
  • WIRE —— 由顶点连接的边的集合。它可能是开放的或是封闭轮廓,具体依赖于边是否是关联的。
  • EDGE —— 一个与被约束的曲线对应的拓扑元素。一条边一般是被顶点约束。它是一维的。
  • VERTEX —— 一个与一个点对应的拓扑元素。它是零维的。
  • SHAPE —— 一个包含上述所有的通用项。

一个拓扑模型可以被认为是有着连接关系的物体的一个图。当在2D或3D空间中建模一个部分,它必须属于列举在 ShapeEnum 枚举类型中的一个。TopAbs 包列出了可以在任何模型中找到的所有物体。它不能被扩展,但其子集可以被使用。例如,刚体的概念是在2D无用的。

枚举的项以由复杂到简单的顺序出现,因为物体在它们的表述中可以包含更简单的物体。例如,一个面参考了它的线框、边和顶点。


朝向(Orientation)

朝向的概念由 TopAbs_Orientation 枚举类型表示。朝向是一个定义不同建模人员对于方向性质的通用概念。当一个形状限制一个集合域,朝向就被使用;然后这是和边界的概念紧密关联的。如下有三个例子:

  • 一个顶点约束的曲线
  • 一条边约束的曲面
  • 一个面约束的空间

在每个案例中,拓扑格式被用作一个更高维度几何区域的边界,其定义了两个局部区域,任意一个作为默认区域。(遵循右手法则)

  • 对于一个由一个顶点约束的曲线,默认区域是参数大于那个顶点的点集。那就是说它是在顶点后沿着曲线自然方向的曲线部分。
  • 对于一个由一条边约束的曲面,默认区域是沿着它自然方向左边的部分。更准确的说,它是由曲面方向了法向量与曲线切向量的向量积。
  • 对于一个由一个面约束的空间,默认区域实在曲面法向量的相反方向。

基于这个默认区域,朝向决定了为了去保持的区域的定义,这被称为 interior 或 material。这里由四个定义内部的朝向。

朝向的概念是非常通用的,它可以被用在任何区域或边界出现的上下文中。因此。当描述一条边和一个轮廓相交时,他可能不仅描述了相交的顶点,也描述了边是如何穿过作为边界的轮廓。边将因此被分为两个区域:exterior 和 interior 相交的顶点将成为边界。因此一个朝向可以与一个相交顶点有关联。

针对 Orientation enumeration TopAbs 包定义了四种方法。


状态(State)

TopAbs_State 枚举类型描述了一个顶点或一组顶点的位置相对一个区域的关系。这里有四个项:

UNKNOWN 项被引入,因为这个枚举类型经常被用作表示一个计算的结果,而计算可能会失败。这个项可以在不可能知道一个点实在内部还是外部时使用,比如说在一个开放的线框或面。


State 枚举也可以被用于确定一个物体的不同部分。下图展示了一个边与一个面相交的部分。


形状位置(Shape Location)

一个局部坐标系统可以被视为如下的任意一项:

  • 一个有着一个原点和三个正交向量的右手三面体。gp_Ax2 包与这个定义有关。
  • 一个a+1行列式的变换,允许局部坐标和全局坐标的变换参考框架。这与 gp_Trsf 有关。

TopLoc 包区别了两个概念:

  • TopLoc_Datum3D 类提供了基本的参考坐标,由一个轴的右手正交系统或一个右手酉变换表示。
  • TopLoc_Location 类提供了由基础参考坐标组合的复合参考坐标。它是一个组合一系列参考基本标志的一个标志。最终累积的变换被顺序保存以避免对于整个列表的变换和重新计算。

两个参考坐标是相同的,只要它们以相同顺序组合相同基本坐标。这里没有数值比较。两个坐标因此可以对应相同的变换,而不需要是相同的,如果它们从相同的基本坐标开始构建。

例如,对于三个基本坐标:R1,R2,R3

复合坐标是:

C1 = R1 * R2;
C2 = R2 * R3;
C3 = C1 * R3;
C4 = R1 * C2;

注意 C3C4 是相同的,因为它们都是 R1 * R2 * R3

TopLoc 包主要用于拓扑数据结构,但是它也可以用于其他目的。

坐标的改变
TopLoc_Datum3D 类表示基本坐标的一个变化。这样的改变必须是共享的,所以这个类继承自 Standard_Transient。坐标由一个变换 gp_Trsfpackage 表示。这个变换没有缩放系数。


操作形状和子形状(Manipulating shapes and sub-shapes)

TopoDS 包以如下特征描述了拓扑数据结构:

  • 引用一个既没有朝向也没有位置的抽象形状。
  • 通过 tool 类访问数据结构。

就像上面提到的那样,OCCT Topology 在参数空间内描述物体的数据结构。这些描述使用这个空间内部和边界部分的定位。形状的类别可以描述为顶点、面和形状。顶点以参数空间的定位的形式进行定义。而面和形状则以这个空间的约束进行定义。

OCCT 拓扑描述也允许以这些项定义的简单形状可以组合为集合。例如,边的集合形成一个线框;面的集合形成一个壳,刚体的集合形成一个复合刚体(composite solid)(CompSolid in Open CASCADE Technology)。你也可以按任意顺序组合将形状组合进复合体。最后,你可以给定一个性质一个朝向(orientation)和一个位置(location)。

按复杂程度从顶点到复合刚体列举形状,让我们能使用数据结构的概念去将一个形状分解为多个简单形状。这就是 TopoDS 包的目的。

一个形状的模型是一个共享的数据结构,应为它可以被其他形状使用(一条边可以被一个刚体的多个面使用)。一个共享的数据结构通过引用处理。当一个简单的引用是不够的时候,两种信息被添加:一个朝向(orientation)和一个局部坐标引用(local coordinate reference)。

  • 一个朝向表面被引用的形状是否被用在一个边界(Orientation from TopAbs)。
  • 一个局部参考坐标(Location from TopLoc)允许引用在一个不同于它定义位置的形状。

TopoDS_TShape 类是所有形状描述的根类。它包含了一系列形状。继承TopoDS_TShape的类可以进行一个几何域的描述如果必要的话(例如,一个几何点与一个TVertex有关)。一个 TopoDS_TShape 是一个在它引用的定义框架(definition frame of reference)下的一个形状。这个类使用引用来操作。

TopoDS_Shape 类描述了对于一个形状的引用。它包含了对于一个底层抽象形状的引用,一个朝向,和一个局部参考坐标。这个类使用值进行操作,因此不会被共享。

表示底层抽象形状的类不会被直接引用TopoDS_Shape 类总是被用于引用它。

对于每个形状特定的信息(the geometric support)总是通过继承源于TopoDS_TShape的类来添加。下图是一个两个面通过一条边连接而形成的壳(shell)。

T

在前面的图中,壳通过底层形状 TS 描述,面通过 TF1TF2 描述。这里还有从 TE1~TE7的七条边,以及从 TV1~TV6 的六个点。

线框 TW1 引用 TE1 ~ TE4 的边;TW2 引用 TE4 ~ TE7 的边。

顶点被边按如下引用:TE1(TV1,TV4),TE2(TV1,TV2),TE3(TV2,TV3),TE4(TV3,TV4),TE5(TV4,TV5),TE6(TV5,TV6),TE7(TV3,TV6)

注意这个数据结构不包含任何反引用(back references)。所有的引用都是从更复杂的底层形状到更简单的形状。访问信息的技术将会在后面讲解。数据是尽可能紧凑的。子物体(Sub-objects)可以被不同的物体所共享。

两个非常相似的形状,可能是相同的形状的两个版本,可能会共享相同的子物体。数据结构中局部坐标的使用允许对于一个重复被共享的子结构的描述。

紧凑的数据结构避免了与复制操作关联的信息的损失,这经常被用于创建一个物体的一个新的版本,或者当应用一个坐标变换。

下图展示了包含一个刚体两个版本的一个数据结构。第二个版本呈现一系列的相同空洞(holes)在不同的位置。数据结构是紧凑的,仍可以在子元素内保存全部信息。

TSh2 对底层面 TFcyl 的三个引用有着相关的局部坐标系统,这与孔洞的连续位置相对应。

继承TopoDS_Shape的类
TopoDS 基于类 TopoDS_Shape 和定义它底层形状的类。这有明显的优势,但主要的缺点就是这些类是过于通用了。它们可以表示的不同形状无法对它们分类(Vertex,Edge,etc.) 因此这是可能地去引入检查,以避免不一致性,比如将一个面插入到一个边。

TopoDS 包提供了两个类集,一个集合继承既没有朝向也没有位置的底层形状,另一个集合继承 TopoDS_ShapeTopDS_Shape 可以表示在TopAbs包中枚举的那些标准拓扑形状。

下面的类继承 TopoDS_Shape:

  • TopoDS_Vertex
  • TopoDS_Edge
  • TopoDS_Wire
  • TopoDS_Face
  • TopoDS_Shell
  • TopoDS_Solid
  • TopoDS_CompSolid

尽管其与继承TopoDS_TShape 的类的名字具有相似性,但它们的使用方式有着巨大的差别。

  • TopoDS_Shape 类和继承于它的类,是操作拓扑物体的正常方式。TopoDS_TShape 被隐藏。TopoDS_TShape 描述了一个类,在它的原始局部系统,且没有朝向。TopoDS_Shape 是一个对 TopoDS_TShape 的引用,且有一个朝向与一个局部参考。

  • TopoDS_TShape 类被递延(deferred);TopoDS_Shape类则不是。使用 TopoDS_Shape 类允许操作拓扑物体,而不需要知道它们的类别。它是个通用的形式。纯的拓扑算法经常使用 TopoDS_Shape 类。

  • TopoDS_TShape 类通过引用被操作;TopoDS_Shape 通过值被操作。一个 TopoDS_Shape 是不超过一个增加了一个朝向和一个局部坐标的引用。TopoDS_Shapes 的共享是无意义的。而共享底层的 TopoDS_TShapes是重要的。对参数的分配或传递不会复制数据结构:这只会创建新的 TopoDS_Shapes 引用相同的 TopoDS_TShape

  • 尽管继承于 TopoDS_TShape 的类被用于添加额外的信息,而对于继承于 TopoDS_Shape 的类并不会添加额外的区域。继承于 TopoDS_Shape 的类仅服务于特例化一个引用,以便从静态类型控制中受益(carried out by the compiler)。例如,一个接受 TopoDS_Face 作为参数的流程与接受 TopoDS_Shape作为参数的流程相比,对于编译器而言是更精确的。相较于使用 TopoDS 中的类,那是毫无意义地去派生其他类。对于一个拓扑数据结构的所有引用都由 Shape 类组成,且它的继承类定义在 TopoDS

这里没有针对继承于 TopoDS_Shape 的类的构造器,否则类型控制将会失效,尽管使用了 implicit casting(C++的一个特性)。TopoDS 包提供了包方法给 casting TopoDS_Shape 中的一个物体到其子类中的一个,且使用类型验证(type verification)。

下面的例子说明一个接受 TopoDS_Shape 类型的一个参数的流程,然后如果它是顶点,将其放入一个变量 V,如果是一条边则调用 ProcessEdge 方法。

#include <TopoDS_Vertex.hxx>
#include <TopoDS_Edge.hxx>
void ProcessEdge (const TopoDS_Edge& theEdge);
void Process (const TopoDS_Shape& theShape)
{
if (theShape.Shapetype() == TopAbs_VERTEX)
{
TopoDS_Vertex V;
V = TopoDS::Vertex (theShape); // Also correct
TopoDS_Vertex V2 = theShape; // Rejected by the compiler
TopoDS_Vertex V3 = TopoDS::Vertex (theShape); // Correct
}
else if (theShape.ShapeType() == TopAbs_EDGE)
{
ProcessEdge (theShape); // This is rejected
ProcessEdge (TopoDS::Edge (theShape)); // Correct
}
else
{
std::cout << "Neither a vertex nor an edge?\n";
ProcessEdge (TopoDS::Edge (theShape));
// OK for compiler but an exception will be raised at run-time
}
}

拓扑数据结构的查找(Exploration of Topological Data Structures)

TopExp 包提供了查找描述在 TopoDS 包中数据结构的工具。查找一个数据结构意味着找到一个给定类型的所有子物体,例如,找到一个刚体的所有面。

TopExp 包提供了 TopExp_Explorer 类去找到一个给定类型的所有子物体。一个查找器使用下面参数进行构建:

  • 将要在哪个形状中进行查找
  • 查找形状的类别,比如 VERTEX,EDGE,SHAPE除外,不被允许
  • 避免(avoid)形状的类别,比如 SHELL,EDGE。默认的,这个形状是SHAPE。这个默认值意味着对查找没有约束。

查找器访问整个结构,以便找到需要类型的形状,且不包含在避免的类型中。下面的例子展示了如何找出形状 S 中的所有面:

void test()
{
TopoDS_Shape S;
for (TopExp_Explorer Ex (S, TopAbs_FACE); Ex.More(); Ex.Next())
{
ProcessFace (Ex.Current());
}
}

查找所有不在边上的点

for (TopExp_Explorer Ex (S, TopAbs_VERTEX, TopAbs_EDGE); Ex.More(); Ex.Next()) {}

找到所有在壳上的面,再找到所有不在壳上的面:

void test()
{
TopExp_Explorer Ex1, Ex2;
TopoDS_Shape S;
for (Ex1.Init (S, TopAbs_SHELL); Ex1.More(); Ex1.Next())
{
// visit all shells
for (Ex2.Init (Ex1.Current(), TopAbs_FACE); Ex2.More(); Ex2.Next())
{
// visit all the faces of the current shell
ProcessFaceinAshell(Ex2.Current());
...
}
}
for (Ex1.Init (S, TopAbs_FACE, TopAbs_SHELL); Ex1.More(); Ex1.Next())
{
// visit all faces not in a shell
ProcessFace (Ex1.Current());
}
}

查找器(Explorer)假定物体只包含一个相同类型的物体或者下层类型的物体。例如,如果要求查找面,他不会看线框、边或顶点去看它们是否包含面。

TopExp包的MapShapes 方法允许填充一个Map。一个使用 Explorer 类的查找器可以访问一个物体超过一次,只要这个物体被引用超过一次。例如,一个刚体的一条边通常是被两个面引用。为了只处理一个物体一次,它们应该被替换近一个 Map

例子

void TopExp::MapShapes (const TopoDS_Shape& S,
const TopAbs_ShapeEnum T,
TopTools_IndexedMapOfShape& M)
{
TopExp_Explorer Ex (S, T);
while (Ex.More())
{
M.Add (Ex.Current());
Ex.Next();
}
}

在下面的例子中,一个物体的所有面和所有边都按照如下规则绘制:

  • 面使用由 FacelsoColor 颜色的 Nblso iso-parametric lines 组成的网格表示
  • 边以暗示共享这条边数量的颜色进行绘制
    1. FreeEdgeColor 的边,就是不属于任意一个面(即线框元素)
    2. BorderEdgeColor 的边,表示属于一个单一的面
    3. SharedEdgeColor 的边,表示属于不止一个面
  • DrawEdgeDrawFaceIso 方法对于显示特有的边和面

如下步骤被执行:

  1. 将边存进一个 Map 然后并行构建一个整形数组去记录共享这条边的面数。这个数组被初始化为0
  2. 查找每个面。每个面都被绘制。
  3. 查找边,对于每个边,在数组中增加面的计数
  4. 对于边的 Map,使用与面数量相关的颜色绘制每条边
void DrawShape (const TopoDS_Shape& aShape,
const Standard_Integer nbIsos,
const Quantity_Color FaceIsocolor,
const Quantity_Color FreeEdgeColor,
const Quantity_Color BorderEdgeColor,
const Quantity_Color SharedEdgeColor)
{
// Store the edges in a Map
TopTools_IndexedMapOfShape edgemap;
TopExp::MapShapes (aShape, TopAbs_EDGE, edgeMap);
// Create an array set to zero
TColStd_Array1OfInteger faceCount (1, edgeMap.Extent());
faceCount.Init (0);
// Explore the faces.
TopExp_Explorer expFace(aShape,TopAbs_FACE);
while (expFace.More())
{
// Draw the current face.
DrawFaceIsos (TopoDS::Face (expFace.Current()), nbIsos, FaceIsoColor);
// Explore the edges of the face
TopExp_Explorer expEdge (expFace.Current(), TopAbs_EDGE);
while (expEdge.More())
{
// Increment the face count for this edge
++faceCount[edgemap.FindIndex (expEdge.Current())];
expEdge.Next();
}
expFace.Next();
}
// Draw the edges of theMap
for (Standard_Integer i = 1; i <= edgemap.Extent(); i++)
{
switch (faceCount[i])
{
case 0:
DrawEdge (TopoDS::Edge (edgemap (i)), FreeEdgeColor);
break;
case 1:
DrawEdge (TopoDS::Edge (edgemap (i)), BorderEdgeColor);
break;
default:
DrawEdge (TopoDS::Edge (edgemap (i)), SharedEdgeColor);
break;
}
}
}

形状的列表和图(Lists and Maps of Shapes)

TopTools 包包含使用 TopoDS 数据结构的工具。这是一个有着 TopoDSShape 类 的 TCollection 包的工具的一个实例。

  • TopTools_Array1OfShape,HArray1OfShape —— 有着 TopoDS_ShapeNCollection_Array1 的实例
  • TopTools_SequenceOfShape —— 有着 TopoDS_ShapeNCollection_Sequence 的实例
  • TopTools_MapOfShape —— NCollection_Map 的实例。允许形状集合的构造
  • TopTools_IndexdMapOfShape —— NCollection_IndexedMap 的实例。允许形状表和其他数据结构的构造。

使用一个 TopTools_Map,对于 Shapes 引用的集合可以被不重复的保持。下面的例子统计一个数据结构的数量作为 TShapes 的数量

#include <TopoDS_Iterator.hxx>
Standard_Integer Size (const TopoDS_Shape& aShape)
{
// This is a recursive method.
// The size of a shape is1 + the sizes of the subshapes.
Standard_Integer size = 1;
for (TopoDS_Iterator It (aShape); It.More(); It.Next())
{
size += Size (It.Value());
}
return size;
}

这个程序是不正确的,因为在数据结构中可能存在共享。

因此对于一个有着四条边的轮廓,其应该有 1个线框+4条边+4个顶点 结果就是 9,但是顶点是被两条边共享的,所以这个程序最后计算的结果为 13。我们的解决方案是将所有 Shapes 放入一个 Map 这样就避免了重复记数,代码如下:

#include <TopoDS_Iterator.hxx>
#include <TopTools_MapOfShape.hxx>
void MapShapes (const TopoDS_Shape& aShape,
TopTools_MapOfShape& aMap)
{
// This is a recursive auxiliary method. It stores all subShapes of aShape in a Map.
if (aMap.Add (aShape))
{
// Add returns True if aShape was not already in the Map.
for (TopoDS_Iterator It (aShape); It.More(); It.Next())
{
MapShapes (It.Value(), aMap);
}
}
}
Standard_Integer Size (const TopoDS_Shape& aShape)
{
// Store Shapes in a Mapand return the size.
TopTools_MapOfShape M;
MapShapes (aShape, M);
return M.Extent();
}

注意对于关于 Maps 的更多细节,请参考 TCollection 文档(Foundation Classes Reference Manual)。

下面的例子是更复杂的。使用一个 IndexedMap 去复制数据结构。被复制后是一个相同的数据结构,但是并不和原始数据结构共享东西。主要算法如下:

  • 在数据结构中的所有 Shapes 被放入一个 IndexedMap
  • Shapes 的一张表被创建,与此同时,map 接收拷贝
  • 使用辅助递归函数将数据结构从map拷贝到数组
**#include <TopoDS_Shape.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <TopTools_Array1OfShape.hxx>
#include <TopoDS_Location.hxx>
TopoDS_Shape Copy (const TopoDS_Shape& aShape,
const TopoDS_Builder& aBuilder)
{
// Copies the wholestructure of aShape using aBuilder.
// Stores all thesub-Shapes in an IndexedMap.
TopTools_IndexedMapOfShape theMap;
TopoDS_Iterator It;
TopLoc_Location Identity;
TopoDS_Shape S = aShape;
S.Location (Identity);
S.Orientation(TopAbs_FORWARD);
theMap.Add(S);
for (Standard_Integer i = 1; i <= theMap.Extent(); i++)
{
for (It.Initialize(theMap(i)); It.More(); It.Next())
{
S = It.Value();
S.Location(Identity);
S.Orientation (TopAbs_FORWARD);
theMap.Add (S);
}
}
}

在上面的例子中,索引 i 是 Map 中第一个没有被处理的物体。当 i 与 Map 的大小一致时,意味着所有Shapes都被处理了。处理包含将所有未在 Map 中的子物体插入 Map,它们被插入的索引是大于 i 的

注意 物体被插入前,将其局部参考坐标设为单位矩阵,朝向设为 FORWARD。只有底层的 TShape 是非常有利的。

// Create an array to store the copies.
TopTools_Array1OfShape theCopies (1, theMap.Extent());
// Use a recursivefunction to copy the first element.
void AuxiliaryCopy (Standard_Integer ,
const TopTools_IndexedMapOfShape& ,
TopTools_Array1OfShape& ,
const TopoDS_Builder& );
AuxiliaryCopy (1, theMap, theCopies, aBuilder);
// Get the result with the correct local reference and orientation.
S = theCopies (1);
S.Location (aShape.Location());
S.Orientation (aShape.Orientation());
return S;

下面是辅助函数,其将第 i 个元素从 map 拷贝到 table。这个方法检查是否物体已经被拷贝过了;如果没被拷贝,那么一个空的拷贝在table上执行,然后所有子元素的拷贝通过查找它们在map中的索引去插入。

void AuxiliaryCopy (Standard_Integer index,
const TopTools_IndexedMapOfShapes& sources,
TopTools_Array1OfShape& copies,
const TopoDS_Builder& aBuilder)
{
// If the copy is a null Shape the copy is not done.
if (copies[index].IsNull())
{
copies[index] = sources(index).EmptyCopied();
// Insert copies of the sub-shapes.
TopoDS_Shape S;
TopLoc_Location Identity;
for (TopoDS_Iterator It (sources (index)), It.More(), It.Next())
{
S = It.Value();
S.Location (Identity);
S.Orientation (TopAbs_FORWARD);
AuxiliaryCopy (sources.FindIndex (S), sources, copies, aBuilder);
S.Location (It.Value().Location());
S.Orientation (It.Value().Orientation());
aBuilder.Add (copies[index], S);
}
}
}

Wire Explorer
BRepTools_WireExplorer 类可以以连接顺序访问一个线框的所有边。

例如,在下图中的线框,我们想要以 {e1,e2,e3,e4,e5} 的顺序访问所有边。

TopExp_Explorer, 但是是以任意顺序恢复边

TopoDS_Wire W = ...;
BRepTools_WireExplorer Ex;
for (Ex.Init (W); Ex.More(); Ex.Next())
{
ProcessTheCurrentEdge (Ex.Current());
ProcessTheVertexConnectingTheCurrentEdgeToThePrevious
One (Ex.CurrentVertex());
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值