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 shape
、orientation
、state
。它也提供了管理这些枚举类型的方法。TopLoc
包给处理3D局部坐标系统提供了资源:Datum3D
和Location
。Datum3D
描述了一个基础的坐标系统,而Location
包含了一系列基础坐标系统。TopoDS
包描述了建模和构建纯拓扑的数据结构的类。
三个额外的包提供了工具区访问和操作这个抽象拓扑:
TopTools
包提供了基础工具用于拓扑数据结构TopExp
包提供了类去查找和操作描述于TopoDS包中的拓扑数据结构BRepTools
包提供了查找、操作、读取和写入BRep数据结构。这些更复杂的数据结构将拓扑描述和额外的几何信息进行组合,然后包含评估相同物体不同可能表征相同性的规则,例如,一个点。
文章目录
- 形状内容(Shape content)
- 拓扑类型(Topological types)
- 朝向(Orientation)
- 状态(State)
- 形状位置(Shape Location)
- 操作形状和子形状(Manipulating shapes and sub-shapes)
- 拓扑数据结构的查找(Exploration of Topological Data Structures)
- 形状的列表和图(Lists and Maps of Shapes)
形状内容(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;
注意 C3
和 C4
是相同的,因为它们都是 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
描述,面通过 TF1
和 TF2
描述。这里还有从 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_Shape
,TopDS_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_TShape
s是重要的。对参数的分配或传递不会复制数据结构:这只会创建新的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 组成的网格表示
- 边以暗示共享这条边数量的颜色进行绘制
- FreeEdgeColor 的边,就是不属于任意一个面(即线框元素)
- BorderEdgeColor 的边,表示属于一个单一的面
- SharedEdgeColor 的边,表示属于不止一个面
DrawEdge
和DrawFaceIso
方法对于显示特有的边和面
如下步骤被执行:
- 将边存进一个
Map
然后并行构建一个整形数组去记录共享这条边的面数。这个数组被初始化为0 - 查找每个面。每个面都被绘制。
- 查找边,对于每个边,在数组中增加面的计数
- 对于边的
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
数据结构的工具。这是一个有着 TopoDS
的 Shape
类 的 TCollection
包的工具的一个实例。
TopTools_Array1OfShape
,HArray1OfShape
—— 有着TopoDS_Shape
的NCollection_Array1
的实例TopTools_SequenceOfShape
—— 有着TopoDS_Shape
的NCollection_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());
}
相关文章:
occt_modeling_data(一)——拓扑
下面是我基于opencascade英文文档中关于occt_modeling_data中Topology部分进行的翻译,英文好的还是建议直接看文档,部分我不肯定的地方我会附上英文原句。如发现有错误欢迎评论区留言。 OCCT Topolog允许用户访问和操纵物体的数据,且不需要处…...
【AcWing】蓝桥杯备赛-深度优先搜索-dfs(3)
目录 写在前面: 题目:93. 递归实现组合型枚举 - AcWing题库 读题: 输入格式: 输出格式: 数据范围: 输入样例: 输出样例: 解题思路: 代码: AC &…...
宇宙最强-GPT-4 横空出世:最先进、更安全、更有用
文章目录前言一、准确性提升1.创造力2.视觉输入3.更长的上下文二、相比于ChatGPT有哪些提升1.GPT-4 的高级推理能力超越了 ChatGPT2.GPT-4 在多种测试考试中均优于 ChatGPT。三、研究团队在GPT-4模型都做了哪些改善1.遵循 GPT、GPT-2 和 GPT-3 的研究路径2.我们花了 6 个月的时…...
HashMap的实际开发使用
目 录 前言 一、HashMap是什么? 二、使用步骤 1.解析一下它实现的原理 编辑 2.实际开发使用 总结 前言 本章,只是大概记录一下hashMap的简单使用方法,以及理清一下hashMap的put方法的原理,以及get方法的原理。 一、Has…...
OpenCV入门(十三)快速学会OpenCV 12 图像梯度
OpenCV入门(十三)快速学会OpenCV 12 图像梯度1.Sobel算子1.1 计算x1.2 计算y1.3 计算xy2.Scharr算子2.1 计算x2.2 计算y2.3 计算xy3.Laplacian算子4.总结图像梯度计算的是图像变化的速度。对于图像的边缘部分,其灰度值变化较大,梯…...
软考:常见小题目计算题
01采购合同的类型采购合同主要包括总价类合同、成本补偿类合同、工料合同三大类合同。1、总价类合同此类合同为既定产品、服务或成果的采购设定一个总价。这种合同应在已明确定义需求,且不会出现重大范围变更的情况下使用。包括:(1࿰…...
【Linux】进程的程序替换
文章目录1. 程序替换1.创建子进程的目的是什么?2.了解程序是如何进行替换的3. 程序替换的基本原理当创建进程的时候,先有进程数据结构,还是先加载代码和数据?程序替换是整体替换,不是局部替换execl 返回值4. 替换函数1…...
【C++】模板(上)
文章目录1、泛型编程2、函数模板函数模板的实例化模板参数的匹配原则3、 类模板类模板的实例化1、泛型编程 void Swap(int& left, int& right) {int temp left;left right;right temp; } void Swap(double& left, double& right) {double temp left;left …...
express框架利用formidable上传图片
express框架,在上传图片功能方面,用formidable里面的incomingform功能,很方便。很多功能都已经封装好了,非常好用,简单,不需要写更深层次的代码了。确实不错。 下面是我自己跟着黑马教程的博客系统的部分&…...
测试背锅侠?入职软件测试后大d佬给我丢了这个bug分类分析,至今受益匪浅......
目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 刚成为入职…...
STM32 OTA应用开发——通过内置DFU实现USB升级(方式1)
STM32 OTA应用开发——通过内置DFU实现USB升级(方式1) 目录STM32 OTA应用开发——通过内置DFU实现USB升级(方式1)前言1 硬件介绍2 环境搭建2.1 Keil uVsion2.2 zadig2.3 STM32CubeProgrammer2.4 安装USB驱动3 OTA升级结束语前言 …...
基于MFC的JavaScript进行网页数据交互
目录 前言 一、创建html对话框工程 二、使用步骤 1.引入JavaScript接口代码 2.重写相关接口 3.在html网页中添加C/C调用的接口 4.在MFC工程中添加调用接口 5.设置确认按键触发调用 6.运行结果 总结 前言 如何快速的进行MFC开发,这里我介绍一种JavaScript与C/C交互的…...
AUTOSAR-Fee
Fee模块 全称Flash EEPROM Emulation Module,属于ECU抽象层 Fee模块本身是脱离硬件的,但是Fee模块可能会引用的Fls模块定制API,所以只能算半抽象. FEE模块应从设备特定的寻址方案和分段中抽象出来,并为上层提供虚拟寻址方案和分段(virtual addressing scheme and segment…...
Linux基本命令——操作演示
Linux基本命令——操作演示Linux的目录结构Linux命令入门目录切换相关命令(cd/pwd)相对路径、绝对路径和特殊路径符创建目录命令(mkdir)文件操作命令part1 (touch、cat、more)文件操作命令part2 (cp、mv、rm)查找命令 …...
【Linux】目录和文件的权限
Linux中的权限有什么作用Linux权限管理文件访问者的分类文件类型和访问权限(事物属性)**文件权限值的表示方法**文件访问权限的相关设置方法chmodchownchgrpumaskumask使用 sudo分配权限目录的权限Linux中的权限有什么作用 Linux下有两种用户࿱…...
Unity 优化之Player Setting
Quality SettingPixel Light Count 使用前向渲染时最大像素光源数。也是性能关键。数量越大消耗越多。Texture Quality:贴图质量,可以选择Half Res,这样速度会更快,但是贴图质量会轻微下降。Anisotropic Textures 纹理各向异形Ant…...
Qt——通过一个简单的程序例程熟悉使用Qt Creator软件进行项目搭建的基本流程(新建项目、项目的文件组成、修改ui文件、编译运行与调试)
【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来! 《项目案例分享》 《极客DIY开源分享》 《嵌入式通用开发实战》 《C++语言开发基础总结》 《从0到1学习嵌入式Linux开发》 《QT开发实战》 《Android开发实战》...
Linux 如何使用 git | 新建仓库 | git 三板斧
文章目录 专栏导读 一、如何安装 git 二、注册码云账号 三、新建仓库 配置仓库信息 四、克隆远端仓库到本地 五、git 三板斧 1. 三板斧第一招:git add 2. 三板斧第二招:git commit 解决首次 git commit 失败的问题 配置机器信息 3. 三…...
3.springcloud微服务架构搭建 之 《springboot自动装配ribbon》
1.springcloud微服务架构搭建 之 《springboot自动装配Redis》 2.springcloud微服务架构搭建 之 《springboot集成nacos注册中心》 ribbon工作原理自己网上百度,说的都很详细 目录 1.项目引入openfeign和ribbon配置 2.新建lilock-ribbon-spring-boot-starter 3…...
【一】进程到底是个啥?
1. 什么是进程 进程(process):一个运行起来的程序,就是进程!,我们可以在任务管理中看到进程。 进程是操作系统进行资源分配的基本单位 2. 进程的管理 所谓的进程管理,其实就是分为两步&…...
[蓝桥杯] 双指针、BFS和DFS与图论问题
文章目录 一、日志统计 1、1 题目描述 1、2 题解关键思路与解答 二、献给阿尔吉侬的花束 2、1 题目描述 2、2 题解关键思路与解答 三、红与黑 3、1 题目描述 3、2 题解关键思路与解答 3、2、1 dfs题解代码 3、2、2 bfs题解答案 四、交换瓶子 4、1 题目描述 4、2 题解关键思路与…...
编译原理陈火旺版第四章课后题答案
下面答案仅供参考! 1.考虑下面文法G1: (1) 消去 Q 的左递归。然后,对每个非终结符,写岀不带回溯的递归子程序。 (2) 经改写后的文法是否是LL(1)的?给出它的预测分析表。 2.对下面的文法G: P→(E)lalblΛ (1)计算这个文法的每个非…...
【LeetCode】剑指 Offer(25)
目录 题目:剑指 Offer 49. 丑数 - 力扣(Leetcode) 题目的接口: 解题思路: 代码: 过啦!!! 写在最后: 题目:剑指 Offer 49. 丑数 - 力扣&…...
【数据结构】链表OJ
Yan-英杰的主页 悟已往之不谏 知来者之可追 目录 编辑 编辑二、分享:OJ调试技巧 编辑三、链表的中间结点 编辑四、链表中倒数第k个结点 一、移除链表元素 示例 1: 输入:head [1,2,6,3,4,5,6], val 6 输出:[1,2,3,4,…...
电子工程师必须掌握的硬件测试仪器,你确定你都掌握了?
目录示波器示例1:测量示波器自带的标准方波信号输出表笔认识屏幕刻度认识波形上下/左右移动上下/左右刻度参数调整通道1的功能界面捕获信号设置Menu菜单触发方式触发电平Cursor按钮捕捉波形HLEP按钮参考资料频谱分析仪器信号发生器示波器 示例1:测量示波…...
高速PCB设计指南系列(四)
第二篇 抗干扰3(部分) 3 提高敏感器件的抗干扰性能 提高敏感器件的抗干扰性能是指从敏感器件这边考虑尽量减少对干扰噪声 的拾取,以及从不正常状态尽快恢复的方法。 提高敏感器件抗干扰性能的常用措施如下: (1&…...
ODrive入门配置
目录一、驱动板说明二、安装python三、安装odrivetool四、接线五、zadig设置SimpleFOC、ODrive和VESC教程链接汇总:请点击一、驱动板说明 ODrive 硬件版本:V3.6-56V, 工作电压:12V-56V, 工作电流:60A ODri…...
快速测试两台服务器间的网速(ChatGPT回复)
如何使用iperf3测试从远程服务器下载文件速度 在进行网络性能测试时,了解服务器之间的带宽和延迟是非常重要的。iperf3是一种用于测量网络性能的工具,可以帮助我们测试从远程服务器下载文件的速度。本文将介绍如何在本地计算机上使用iperf3测试从远程服…...
彻底搞懂nodejs事件循环
nodejs是单线程执行的,同时它又是基于事件驱动的非阻塞IO编程模型。这就使得我们不用等待异步操作结果返回,就可以继续往下执行代码。当异步事件触发之后,就会通知主线程,主线程执行相应事件的回调。 以上是众所周知的内容。今天…...
Linux基础命令大全(下)
♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的绽放࿰…...
海淀网站建设枣庄/友情链接网自动收录
这是个奇葩的问题,我也是奇葩的研究了好几天,最后发现,哈,原来是这个原因,在此记录下曲折的心路历程接口Content-Type没有,body用的是postman中的raw数据,格式是text程序如下:import…...
厦门网站建设公司排名/合肥网站优化
一.html <canvas id"clock" width"500" height"500" >你的浏览器不支持canvas</canvas>二.css canvas{background: #000; }三.js <script>/*难点1:怎样把时刻线绘制出来难点2: 时间指针的旋转角度秒:3…...
网站一定也做数据库吗/外链网站是什么
首先一句话解释一下new:new 可以实现一个对象继承构造函数的属性以及方法 举个例子: function Parent(name,age){this.name name;this.age age; }Parent.prototype.sayName function(){console.log(my name is ${this.name}) }let child new Parent(…...
vps建站教程/搜索量查询百度指数
题意是说第一行字符串能否由第二行字符串经过“替代”和“位置转换”后得到。 做题时,实际上只统计两个字符串的各字符出现的“次数”是否相同即可(不必计较这相同次数是否字符也相同)。 算法思想如下: 1)读入两行字符…...
做行政关注什么类型的网站/西安seo按天收费
为什么80%的码农都做不了架构师?>>> 日期:2012-4-16 来源:GBin1.com 互联网拥有很多免费的工具和应用,几乎可以帮助你实现任何你需要的UI组件和设计,大家还记得上周我们介绍的纯CSS实现的气泡式提示文章吗…...
哪个网站做漂流瓶任务/百度投放广告联系谁
3d相关软件有很多,涉及到各行各业,各个领域,从电影行业,游戏行业,医疗行业,到工业领域,包含机械行业,制造行业,科研行业,等等,其中工业行业又细分…...