Opencascade源码学习之模型数据

这篇具有很好参考价值的文章主要介绍了Opencascade源码学习之模型数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


1、模型数据

模型数据提供数据结构,用于在 3D 模式下实现对象的边界表示 (BRep)。在 BRep 中,形状表示为拓扑中几何图形的聚合。几何形状被理解为形状的数学描述,例如曲线和曲面(简单或规范,贝塞尔,NURBS等)。拓扑是将几何对象绑定在一起的数据结构。

几何类型和实用程序为以下方面提供几何数据结构和服务:

  • 点、向量、曲线和曲面的描述:
    • 它们使用轴或坐标系在 3D 空间中的定位,以及
    • 它们的几何变换,通过应用平移、旋转、对称、缩放变换及其组合。
  • 通过插值和拟合创建参数化曲线和曲面;
  • 直接构造算法;
  • 将曲线和曲面转换为 NURBS 形式;
  • 计算二维和三维曲线上的点坐标;
  • 计算几何对象之间的极值。

拓扑定义简单几何实体之间的关系。形状是基本的拓扑实体,可以分为组件(子形状):

  • 顶点 – 对应于一个点的零维形状;
  • 边缘 – 对应于曲线的形状,每端都有一个顶点;
  • 线 – 由其顶点连接的一系列边;
  • 面 – 由导线边界的平面(2D)或曲面(3D)的一部分;
  • 壳 – 由其导线边界边缘连接的面的集合;
  • 实体 – 由壳限制的 3D 空间的有限封闭部分;
  • 复合实体 – 由壳边界面连接的实体集合;
  • 复合 – 任意类型的形状的集合。

复杂形状可以定义为简单实体的组件(复合)。3D 几何模型可以以 OCCT 原生 BREP 格式存储。

Geom

2、几何工具

几何实用程序提供以下服务:

  • 通过插值和拟合创建形状
  • 直接构造形状
  • 将曲线和曲面转换为 BSpline 曲线和曲面
  • 计算 2D 和 3D 曲线上的点坐标
  • 计算形状之间的极值。
1、插值和拟合

在建模中,通常需要将点拟合或插值为曲线和曲面。在插值中,当曲线或曲面通过所有点时,该过程完成;近似值,当它尽可能接近这些点时。

曲线和曲面拟合将 2D 和 3D 几何中使用的各种功能组合在一起,用于:

  • 使用 2D BSpline 或贝塞尔曲线插值一组 2D 点;
  • 使用 2D BSpline 或贝塞尔曲线拟合一组 2D 点;
  • 使用 3D BSpline 或贝塞尔曲线或 BSpline 曲面对一组 3D 点进行插值;
  • 使用 3D BSpline 或贝塞尔曲线或 BSpline 曲面对一组 3D 点的拟合。

您可以通过两种方式对拟合值进行编程:

  • 使用高级函数,旨在提供一种简单的方法,以最少的编程获得拟合值,
  • 使用低级函数,专为需要对拟合值进行更多控制的用户而设计。
1、分析一组点

GProp 包中的 PEquation 类允许分析点的集合或云,并验证它们在给定精度内是重合、共线还是共面。如果是,则算法计算点的平均点、平均线或点的平均平面。如果不是,则算法将计算包含所有点的最小框。

2、基本插值和近似

Geom2dAPIGeomAPI 软件包提供了简单的近似和插值方法,只需最少的编程

3、2D 插值

Geom2dAPI 包中的类插值允许构建受约束的 2D BSpline 曲线,该曲线由曲线通过的点表定义。如果需要,可以为表中的每个点给出切线的参数值和向量。

4、3D 插值

GeomAPI类插值包允许构建受约束的 3D BSpline 曲线,该曲线由曲线通过的点表定义。如果需要,可以为表中的每个点给出切线的参数值和向量。如图,从散点拟合 BSpline

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

此类可以按如下方式实例化:

GeomAPI_Interpolate Interp(Points); 

从这个对象,可以请求如下的BSpline曲线:

Handle(Geom_BSplineCurve) C = Interp.Curve(); 
5、2D 拟合

来自Geom2dAPI包的类PointsToBSpline允许构建2DBSpline曲线,该曲线近似于一组点。您必须定义曲线的最低和最高度数、其连续性和公差值。容差值用于检查点是否彼此不太接近,或者切向量是否不太小。生成的 BSpline 曲线将是 C2 或二度连续的,除非在曲线通过的点上定义了相切约束。在这种情况下,它将只是 C1 连续的。

6、3D 拟合

来自GeomAPI包的类PointsToBSpline允许构建3D BSpline曲线,该曲线近似于一组点。有必要定义曲线的最低和最高度,其连续性和公差。容差值用于检查点是否彼此不太接近,或者切向量是否太小。

生成的 BSpline 曲线将是 C2 或二阶连续的,除非在曲线通过的点上定义了相切约束。在这种情况下,它将只是 C1 连续的。此类实例化如下:

GeomAPI_PointsToBSpline 
Approx(Points,DegMin,DegMax,Continuity, Tol); 

从这个对象,可以请求如下的BSpline曲线:

Handle(Geom_BSplineCurve) K = Approx.Curve(); 
7、曲面拟合

GeomAPI包中的类 PointsToBSplineSurface 允许构建一个 BSpline 曲面,该曲面近似或插值一组点。

8、高级拟合

AppDefAppParCurves 包提供低级函数,允许对拟合值进行更多控制。

低级函数提供2个 API,其中包含以下功能:

  • 定义近似值的强制切线。这些切线有起源和末端。
  • 平行近似一组曲线以遵守相同的参数化。
  • 平滑近似。这是为了产生一条公平的曲线。

您还可以找到要计算的函数:

  • 包含一组点的最小框
  • 一组共面点、共线点或重合点的平均平面、直线或点。
9、多点约束的拟合

AppDef 软件包提供了低级工具,允许使用多个点约束将点组平行近似为贝塞尔曲线或 B 样条曲线。

提供以下低级服务:

  • 点约束数组的定义:

    MultiLine 类允许定义给定数量的多点约束,以便构建多线,多条线通过有序多点约束。如图

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

在此图像中:

  • PiQiRiSi 可以是 2D 或 3D 点。

  • 定义为一个组:PnQnRn、…Sn 形成多点约束。它们具有相同的通道、相切和曲率约束。

  • P1P2, …Pn,或QR,…或 S 系列表示要拟合的线。

  • 一组点约束的定义:

    类 MultiPointConstraint 允许定义多点约束并计算点集到多条曲线的近似值。

  • 从一组点计算贝塞尔曲线的近似值:

    类 Compute 允许将一组点近似到贝塞尔曲线

  • 从一组点计算BSpline曲线的近似值:

    类BSplineCompute允许将一组点近似到BSpline曲线。

  • 变分标准的定义:

类 TheVariational 允许使用最小二乘法结合变分准则(通常是每个约束点的权重)将近似曲线整流到给定数量的点。

10、通过参数或几何约束进行近似

AppParCurves 软件包提供了低级工具,允许将点组平行近似为具有参数或几何约束的贝塞尔曲线或 B 样条曲线,例如要求曲线通过给定点,或在特定点具有给定的相切或曲率。

使用的算法包括:

  • 最小二乘法
  • 搜索给定容差值内的最佳近似值。

提供以下低级服务:

  • 索引与对象的关联:

类 ConstraintCouple 允许您将索引关联到对象以使用 AppDef_TheVariational 计算流行曲线。

  • 贝塞尔曲线的一组近似的定义:

多曲线类允许定义由多条贝塞尔曲线组成的多线的近似值。

  • BSpline 曲线的一组近似值的定义:

MultiBSpCurve类允许定义由多条BSpline曲线组成的多线的近似值。

  • 定义构成一组点约束的点

多点类允许定义构成线的 2D 或 3D 点组。

11、示例:如何根据切向拟合曲线

若要拟合曲线的切向,请执行以下步骤:

  1. 从要拟合的点集创建类型 AppDef_MultiPointConstraints 的对象,并使用方法 SetTang 设置相切向量。
  2. AppDef_MultiPointConstraint创建类型为AppDef_MultiLine 的对象。
  3. 使用 AppDef_BSplineCompute,它将实例化Approx_BSplineComputeLine来执行近似。
2、直接构造

GCEGCGCE2d 软件包中的直接构造方法提供了简化的算法来构建基本几何实体,例如直线、圆和曲线。它们补充了 gpGeomGeom2d 软件包提供的参考定义。

gceGCE2dGC 包实现的算法很简单:无需创建由高级位置约束定义的对象

例如,要使用 gp 包从点和半径构造圆,必须在创建圆之前构造轴 Ax2d。如果使用gce包,并且以Ox作为轴,则可以直接从点和半径创建圆。

另一个例子是类gce_MakeCirc提供了一个框架,用于定义圆的几何构造中遇到的八个问题并实现八个相关的构造算法。

创建(或实现)的对象是一种算法,可以参考以找出答案,特别是:

  • 它的结果,这是一个gp_Circ,以及
  • 它的地位。在这里,状态指示施工是否成功。

如果不成功,状态会给出失败的原因。

gp_Pnt P1 (0.,0.,0.);
gp_Pnt P2 (0.,10.,0.);
gp_Pnt P3 (10.,0.,0.);
gce_MakeCirc MC (P1,P2,P3);
if (MC.IsDone()) {
    const gp_Circ& C = MC.Value();
}

此外, gceGCE2dGC各有一个类。此类是包中所有类的根,这些类返回状态。返回的状态(成功构造或构造错误)由枚举gce_ErrorType描述。

请注意,构造几何变换的类不返回状态,因此不会从 Root 继承。

1、简单的几何实体

以下用于从 gp 包构建实体的算法由 gce 包提供。

  • 远处平行于另一条的 2D 线,
  • 平行于另一条穿过一个点的 2D 线,
  • 2D圆穿过两点,
  • 远处平行于另一个圆的 2D 圆,
  • 平行于另一个通过点的 2D 圆,
  • 2D圆穿过三点,
  • 从中心和半径开始的 2D 圆,
  • 从五个点开始的二维双曲线,
  • 从一个中心和两个顶点开始的二维双曲线,
  • 从五个点开始的二维椭圆,
  • 从一个中心和两个顶点的 2D 椭圆,
  • 三点二维抛物线,
  • 从中心和顶点的 2D 抛物线,
  • 平行于另一条线穿过一个点,
  • 线穿过两点,
  • 圆同轴到另一个通过一个点,
  • 在给定距离处同轴到另一个圆,
  • 圆穿过三点,
  • 圆的中心、半径和垂直于平面,
  • 圆及其轴(中心+法线),
  • 双曲线的中心和两个顶点,
  • 椭圆及其中心和两个顶点,
  • 平面穿过三点,
  • 平面从其正常,
  • 在给定距离处平行于另一个平面的平面,
  • 平行于另一个通过一个点的平面,
  • 从点数组平面,
  • 来自给定轴和给定半径的圆柱体,
  • 圆形底座的圆柱体,
  • 圆柱体从三个点,
  • 在给定距离处平行于另一个圆柱体的圆柱体,
  • 圆柱平行于通过一个点的另一个圆柱体,
  • 从四个点锥体,
  • 从给定轴和两个通过点开始的锥体,
  • 从两点(一个轴)和两个半径开始的圆锥体,
  • 在给定距离处平行于另一个锥体,
  • 圆锥平行于另一个穿过一个点的圆锥体,
  • 所有转换(旋转、平移、镜像、缩放转换等)。

gp 包中的每个类,如 Circ、Circ2d、Mirror、Mirror2d 等,都有对应的 MakeCirc、MakeCirc2d、MakeMirror、MakeMirror2d 等。GCE 包中的类。

可以使用 gce 包类创建一个点,然后质询它以恢复相应的 gp 对象。

gp_Pnt2d Point1,Point2; 
...
//Initialization of Point1 and Point2 
gce_MakeLin2d L = gce_MakeLin2d(Point1,Point2); 
if (L.Status() == gce_Done() ){ 
  gp_Lin2d l = L.Value(); 
}

如果您不确定参数是否可以在不引发异常的情况下创建 gp 对象,这将非常有用。在上述情况下,如果 Point1Point2 更接近 MakeLin2d 要求的容差值,则函数 Status 将返回枚举gce_ConfusedPoint。这告诉您为什么无法创建 gp 对象。如果您知道点 1 和点 2 之间的点由超过容差值的值分隔,则可以直接创建 gp 对象,如下所示:

gp_Lin2d l = gce_MakeLin2d(Point1,Point2);
2、由句柄操作的几何实体

GCGCE2d 包提供了用于从 GeomGeom2D 包构建实体的算法实现。它们实现与 gce 包相同的算法,并且还包含修剪曲面和曲线的算法。可以使用以下算法:

  • 修剪两点的圆弧,
  • 由两个参数修剪的圆弧,
  • 由一个点和一个参数修剪的圆弧,
  • 椭圆的弧线从修剪两点的椭圆,
  • 由两个参数修剪的椭圆的椭圆弧,
  • 椭圆的弧线从椭圆修剪一个点和一个参数,
  • 抛物线的弧线从抛物线修剪两点,
  • 抛物线的弧线来自由两个参数修剪的抛物线,
  • 抛物线的弧线从抛物线修剪一个点和一个参数,
  • 双曲线的弧线从双曲线修剪两点,
  • 由两个参数修剪的双曲线的双曲线弧,
  • 双曲线的弧线来自双曲线,由一个点和一个参数修剪,
  • 从两点开始分割一条线,
  • 从两个参数分割一条线,
  • 从一个点和一个参数开始的线段,
  • 从圆形底座和高度修剪的圆柱体,
  • 从三个点修剪圆柱体,
  • 从轴、半径和高度修剪圆柱体,
  • 从四个点修剪圆锥,
  • 从两个点(一个轴)和一个半径修剪圆锥,
  • 从两个同轴圆修剪圆锥。

GCE2d包中的每个类,如Circle,Ellipse,Mirror等,都有相应的MakeCircle,MakeEllipse,MakeMirror等来自 Geom2d 包的类。此外,类 MakeArcOfCircleGeom2d 返回一个类型为 TrimmedCurve 的对象。

GC 包中的每个类,如 Circle、Ellipse、Mirror 等,都有对应的 MakeCircle、MakeEllipse、MakeMirror 等来自 Geom* 包的类。以下类从 Geom 返回类型为 TrimmedCurve 的对象:

  • MakeArcOfCircle
  • MakeArcOfEllipse
  • MakeArcOfHyperbola
  • MakeArcOfParabola
  • MakeSegment
3、与BSpline之间的转换

与BSplines之间的转换组件有两个不同的目的:

  • 首先,它提供了一个均匀的公式,可用于描述任何曲线或表面。这对于为单个数据结构模型编写算法非常有用。BSpline 公式可用于表示由描述几何数据结构的组件(“基本几何类型”、“2D 几何类型”和“3D 几何类型”组件)提供的大多数基本几何对象。
  • 其次,它可用于将BSpline曲线或曲面划分为一系列曲线或曲面,从而提供更高程度的连续性。这对于编写算法非常有用,这些算法需要在应用它们的对象中具有特定程度的连续性。不连续性仅位于对象的边界上。

“与BSplines之间的转换”组件由三个包组成。

转换包提供了将以下内容转换为 BSpline 曲线或曲面的算法:

  • 基于 GP 包中的基本 2D 曲线(直线、圆形或圆锥)的有界曲线,
  • 基于GP包中的基本曲面(圆柱体,圆锥体,球体或圆环)的有界曲面,
  • 由极点定义的一系列相邻 2D 或 3D 贝塞尔曲线。

这些算法计算定义生成的BSpline曲线或曲面所需的数据。然后,可以直接在算法中使用这些基本数据(度数、周期特征、极点和权重、节点和多重性),或者可以通过调用类Geom2d_BSplineCurveGeom_BSplineCurveGeom_BSplineSurface 提供的适当构造函数来构造曲线或曲面。

Geom2dConvert软件包提供以下内容:

  • 一个全局函数,用于根据 Geom2d 包中的 2D 曲线从有界曲线构造 BSpline 曲线,
  • 一种分割算法,计算应切割 2D BSpline 曲线的点,以获得具有相同连续度的弧,
  • 用于构造由此拆分算法或其他类型的 BSpline 曲线分割创建的 BSpline 曲线的全局函数,
  • 一种将二维 BSpline 曲线转换为一系列相邻贝塞尔曲线的算法。

GeomConvert软件包还提供以下内容:

  • 一个全局函数,用于基于 Geom 包中的曲线从有界曲线构造 BSpline 曲线,
  • 一种分割算法,它计算应该切割BSpline曲线的点,以获得具有相同连续度的弧,
  • 全局函数,用于构建由此拆分算法或其他类型的 BSpline 曲线分割创建的 BSpline 曲线,
  • 一种算法,它将 BSpline 曲线转换为一系列相邻的贝塞尔曲线,
  • 一个全局函数,用于基于 Geom 包中的曲面从有界曲面构造 BSpline 曲面,
  • 一种分割算法,它确定应沿其切割 BSpline 曲面的曲线,以获得具有相同连续度的斑块,
  • 全局函数,用于构建由此拆分算法或其他类型的 BSpline 曲面分割创建的 BSpline 曲面,
  • 一种算法,它将 BSpline 曲面转换为一系列相邻的贝塞尔曲面,
  • 一种算法,它将相邻贝塞尔曲面的网格转换为 BSpline 曲面。
4、曲线上的点

曲线上的点组件包含高级函数,为计算 2D 或 3D 曲线上的点的复杂算法提供 API。

以下特征点存在于 3D 空间中的参数化曲线上:

  • 在曲线上等距分布的点,
  • 点沿曲线分布,弦相等,
  • 与曲线上的另一个点保持给定距离的点。

GCPnts 包提供了计算这些点的算法:

  • AbscissaPoint 计算曲线上的一个点,该点与曲线上的另一个点保持给定距离。
  • 均匀横坐标计算曲线上给定横坐标处的一组点。
  • 均匀挠度计算曲线与多边形之间最大恒定挠度处的一组点,该点由计算的点产生。
5、示例:可视化曲线。

让我们采用一个自适应曲线 C,即一个对象,它是包 Geom2d(在Adaptor_Curve2d曲线的情况下)或包 Geom 的 3D 曲线(在Adaptor_Curve曲线的情况下)提供的服务与计算算法在曲线上所需的服务之间的接口。调整曲线按以下方式创建:

2D案例 :

Handle(Geom2d_Curve) mycurve = ... ; 
Geom2dAdaptor_Curve C (mycurve) ; 

3D案例 :

Handle(Geom_Curve) mycurve = ... ; 
GeomAdaptor_Curve C (mycurve) ; 

然后使用以下对象构造算法:

GCPnts_UniformDeflection myAlgo () ; 
Standard_Real Deflection = ... ; 
myAlgo.Initialize ( C , Deflection ) ; 
if ( myAlgo.IsDone() ) 
{
  Standard_Integer nbr = myAlgo.NbPoints() ; 
  Standard_Real param ; 
   for ( Standard_Integer i = 1 ; i <= nbr ; i++ ) 
  { 
    param = myAlgo.Parameter (i) ; 
    ...
  } 
}
6、极值

用于计算 2D 和 3D 中点、曲线和表面之间最小距离的类由 GeomAPI 和 Geom2dAPI 包提供。

这些包计算以下各项之间的距离极值:

  • 点和曲线,
  • 点和表面,
  • 两条曲线,
  • 曲线和曲面,
  • 两个表面。
7、点和曲线/曲面之间的极值

GeomAPI_ProjectPointOnCurve类允许计算点和曲线之间的所有极值。极值是与曲线正交的线段的长度。GeomAPI_ProjectPointOnSurface类允许计算点和表面之间的所有极值。极值是与表面正交的线段的长度。这些类使用“投影”标准进行优化。

8、曲线之间的极值

Geom2dAPI_ExtremaCurveCurve类允许计算两条二维几何曲线之间的所有最小距离。GeomAPI_ExtremaCurveCurve类允许计算两条 3D 几何曲线之间的所有最小距离。这些类使用欧几里得距离作为优化标准。

9、曲线和曲面之间的极值

GeomAPI_ExtremaCurveSurface类允许计算 3D 曲线和曲面之间的一个极值。极值是与曲线和曲面正交的线段的长度。此类使用“投影”条件进行优化。

10、曲面之间的极值

GeomAPI_ExtremaSurfaceSurface 类允许计算两个表面之间的一个最小距离和一个最大距离。此类使用欧几里得距离计算最小值,并使用“投影”条件计算最大值。

3、2D 几何图形

Geom2d 包定义 2dspace 中的几何对象。所有几何图元都经过 STEP 处理。对象通过引用进行处理。

特别是,Geom2d包提供了以下类:

  • 点、向量和曲线的描述,
  • 它们使用坐标系在平面中的定位,
  • 它们的几何变换,通过应用平移、旋转、对称、缩放变换及其组合。

以下对象可用:

  • 笛卡尔点,
  • 向量
  • 方向
  • 带量级的矢量,
  • 曲线
  • 线
  • 圆锥:圆、椭圆、双曲线、抛物线、
  • 圆角曲线:修剪曲线、NURBS曲线、贝塞尔曲线、
  • 偏移曲线。

在创建几何对象之前,有必要确定如何处理对象。Geom2d 包提供的对象按引用而不是按值处理。复制实例会复制句柄,而不是对象,以便对一个实例的更改反映在每次出现时。如果需要一组对象实例而不是单个对象实例,则可以使用 TColGeom2d 包。该软件包为Geom2d软件包中的曲线提供了一维数组和序列的标准和常用实例化。所有对象都有两个版本:

  • 通过引用和处理
  • 按值处理。

Geom2d曲线的关键特征是它们是参数化的。每个类都提供函数来处理曲线的参数方程,特别是计算曲线上参数 u 的点和此时 1、2…、N 阶的导数向量。

作为参数化的结果,Geom2d曲线是自然定向的。

参数化和方向将基本Geom2d曲线与gp包提供的等效曲线区分开来。Geom2d包提供了转换功能,可以将Geom2d对象转换为gp对象,反之亦然。

此外, Geom2d包提供了更复杂的曲线,包括贝塞尔曲线,BSpline曲线,修剪曲线和偏移曲线。

Geom2d 对象根据多个级别的继承结构进行组织。

因此,椭圆(特定类Geom2d_Ellipse)也是圆锥曲线,继承自抽象类Geom2d_Conic,而贝塞尔曲线(具体类Geom2d_BezierCurve)也是有界曲线,继承自抽象类Geom2d_BoundedCurve;这两个例子也是曲线(抽象类Geom2d_Curve)。曲线、点和矢量继承自抽象类 Geom2d_Geometry该类描述了 Geom2d 包中任何几何对象的通用属性。

这种继承结构是开放的,可以描述从Geom2d包中提供的对象继承的新对象,前提是它们尊重要从中继承的类的行为。

最后, Geom2d对象可以在更复杂的数据结构中共享。例如,这就是为什么它们在拓扑数据结构中使用的原因。

Geom2d软件包使用GP软件包的服务来:

  • 实现初等代数微积分和基本解析几何,
  • 描述可应用于Geom2d对象的几何变换,
  • 描述Geom2d对象的基本数据结构。

但是,Geom2d包本质上提供数据结构而不是算法。您可以参考GCE2d软件包来查找更多针对Geom2d对象的进化构造算法。

4、3D 几何图形

Geom 包定义 3D 空间中的几何对象,并包含所有基本的几何转换,例如标识、旋转、平移、镜像、缩放转换、转换组合等。以及取决于几何对象的参考定义的特殊功能(例如,在 B 样条曲线上添加控制点、修改曲线等)。所有几何图元都经过 STEP 处理。

特别是,它为以下对象提供了类:

  • 点、向量、曲线和曲面的描述,
  • 它们使用轴或坐标系在 3D 空间中的定位,以及
  • 它们的几何变换,通过应用平移、旋转、对称、缩放变换及其组合。

以下对象可用:

  • 笛卡尔点
  • 向量
  • 方向
  • 具有量级的矢量
  • 曲线
  • 线
  • 圆锥:圆、椭圆、双曲线、抛物线
  • 偏移曲线
  • 基本表面:平面、圆柱体、圆锥体、球体、圆环
  • 有界曲线:修剪曲线、NURBS 曲线、贝塞尔曲线
  • 有界曲面:矩形修剪曲面、NURBS 曲面、贝塞尔曲面
  • 扫掠面:线性挤压面、旋转面
  • 偏移曲面。

几何曲线和曲面的关键特征是它们是参数化的。每个类都提供函数来处理曲线或曲面的参数方程,特别是计算:

  • 曲线上参数 u 的点,或
  • 曲面上的参数点 (U, V)。连同 1、2、…N在这一点上。

由于这种参数化,几何曲线或曲面是自然定向的。

参数化和方向将基本几何曲线和曲面与 gp 包中具有相同(或相似)名称的类区分开来。Geom 包还提供了转换函数,用于将 Geom 对象转换为 gp 对象,反之亦然,如果可以进行这种转换。

此外, Geom 软件包提供更复杂的曲线和曲面,包括:

  • 贝塞尔和BSpline曲线和曲面,
  • 扫掠曲面,例如旋转曲面和线性挤压曲面,
  • 修剪的曲线和曲面,以及
  • 偏移曲线和曲面。

几何对象根据继承结构在多个级别上进行组织。因此,球体(具体类 Geom_SphericalSurface)也是基本曲面,继承自抽象类Geom_ElementarySurface,而贝塞尔曲面(具体类 Geom_BezierSurface)也是有界曲面,继承自抽象类Geom_BoundedSurface;这两个示例也是曲面(抽象类 Geom_Surface)。曲线、点和矢量继承自抽象类 Geom_Geometry该类描述了 Geom 包中任何几何对象的通用属性。

这种继承结构是开放的,可以描述从 Geom 包中提供的对象继承的新对象,前提是它们尊重要从中继承的类的行为。

最后,Geom 对象可以在更复杂的数据结构中共享。例如,这就是为什么它们在拓扑数据结构中使用的原因。

如果需要一组对象实例而不是单个对象实例,则可以使用 TColGeom 包。此包提供 Geom 包中曲线的一维和二维数组和序列的实例化。所有对象都有两个版本:

  • 通过引用和处理
  • 按值处理。

Geom 软件包使用 gp 软件包的服务来:

  • 实现初等代数微积分和基本解析几何,
  • 描述可应用于几何对象的几何变换,
  • 描述 Geom 对象的基本数据结构。

但是,Geom 包本质上提供数据结构,而不是算法。

您可以参考 GC 包来查找 Geom 对象的更多改进构造算法。

5、拓扑

OCCT拓扑允许访问和操作对象的数据,而无需处理其2D或3D表示。OCCT 几何根据坐标或参数值提供对象的描述,而拓扑则描述参数空间中对象的数据结构。这些描述使用此空间中的位置和部分限制。

拓扑库允许您构建纯拓扑数据结构。拓扑定义简单几何实体之间的关系。通过这种方式,您可以将复杂形状建模为简单实体的程序集。由于内置的非流形(或混合维)功能,您可以混合构建模型:

  • 0D 实体,如点;
  • 1D实体,如曲线;
  • 2D 实体,例如表面;
  • 3D 实体,例如体积。

例如,可以表示由多个不同实体组成的单个对象,其中包含连接到或未连接到外部边界的嵌入曲线和曲面。

抽象拓扑数据结构描述了一个基本实体——形状,它可以分为以下组件拓扑:

  • 顶点 – 对应于几何中点的零维形状;
  • 边缘 – 对应于曲线的形状,由每个末端的顶点绑定;
  • 线 – 由其顶点连接的一系列边;
  • 面 – 由闭合导线边界的平面(在 2D 几何中)或曲面(在 3D 几何中)的一部分;
  • 壳 – 由其导线边界的某些边缘连接的面的集合;
  • 实体 – 由壳绑定的 3D 空间的一部分;
  • 复合固体 – 固体的集合。

导线和实体可以是无限的,也可以是封闭的。

具有 3D 基础几何图形的面也可以指近似于下层曲面的连接三角形的集合。曲面可以未定义,只留下由三角形表示的面。如果是这样,则模型是纯多面体的。

拓扑定义了简单几何实体之间的关系,因此可以将这些几何实体链接在一起以表示复杂的形状。

摘要拓扑由六个包提供。前三个包描述了开放级联技术中使用的拓扑数据结构:

  • TopAbs 软件包为拓扑驱动的应用程序提供通用资源。它包含用于描述基本拓扑概念的枚举:拓扑形状、方向和状态。它还提供了管理这些枚举的方法。
  • TopLoc 软件包提供用于处理 3D 局部坐标系的资源: Datum3DLocationDatum3D 描述基本坐标系,而位置包含一系列基本坐标系。
  • TopoDS 包描述了用于建模和构建纯拓扑数据结构的类。

三个附加包提供了访问和操作此抽象拓扑的工具:

  • TopTools 包提供了用于拓扑数据结构的基本工具。
  • TopExp包提供了一些类来探索和操作TopoDS包中描述的拓扑数据结构。
  • BRepTools 包提供了用于探索、操作、读取和写入 BRep 数据结构的类。这些更复杂的数据结构将拓扑描述与其他几何信息相结合,并包括用于评估同一对象(例如点)的不同可能表示的等价性的规则。
1、形状内容

TopAbs 包提供了描述拓扑的基本概念和处理这些枚举的方法的一般枚举。它不包含任何类。此包已与拓扑的其余部分分开,因为它包含的概念足够通用,可供所有拓扑工具使用。这样可以避免通过保持独立于建模资源来重新定义枚举。***TopAbs***软件包定义了三个概念:

  • 类型 TopAbs_ShapeEnum;
  • 方向TopAbs_Orientation ;
  • 状态StateTopAbs_State;
1、拓扑类型

TopAbs包含TopAbs_ShapeEnum枚举,其中列出了不同的拓扑类型:

  • 复合 – 一组任何类型的拓扑对象。
  • 复合固体 – 复合固体是由它们的面连接的一组实体。它将WIRE和SHELL的概念扩展到固体。
  • 固体 – 受外壳限制的空间的一部分。它是三维的。
  • 壳 – 一组由边缘连接的面。外壳可以是打开的,也可以是关闭的。
  • 面 – 在 2D 中,它是平面的一部分;在 3D 中,它是表面的一部分。其几何形状受轮廓约束(修剪)。它是二维的。
  • 线 – 一组由顶点连接的边。它可以是开放或闭合轮廓,具体取决于边是否链接。
  • 边 – 对应于约束曲线的拓扑元素。边通常受顶点限制。它有一个维度。
  • 顶点 – 对应于点的拓扑元素。它的维度为零。
  • 形状 – 涵盖上述所有内容的通用术语。

拓扑模型可以被视为具有邻接关系的对象图。在 2D 或 3D 空间中对零件进行建模时,它必须属于 ShapeEnum 枚举中列出的类别之一。TopAbspackage列出了所有对象,可以在任何模型中找到。它不能扩展,但可以使用子集。例如,实体的概念在2D中是无用的。

枚举项按从最复杂到最简单的顺序显示,因为对象在其描述中可以包含更简单的对象。例如,面参照其导线、边和顶点。

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

2、方向

方向的概念由TopAbs_Orientation枚举表示。方向是在各种建模者中发现的方向感的广义概念。当形状限制几何域时,将使用此方法;并且与边界概念密切相关。这三种情况如下:

  • 受顶点限制的曲线。
  • 受边缘限制的曲面。
  • 受面限制空间。

在每种情况下,用作更高维几何域边界的拓扑形式定义了两个局部区域,其中一个被任意视为默认区域

对于受顶点限制的曲线,默认区域是参数大于顶点的点集。也就是说,它是顶点之后的曲线部分,沿着曲线的自然方向。

对于受边限制的曲面,缺省区域位于边的左侧,遵循其自然方向。更准确地说,它是法向向量到曲面的向量积和与曲线相切的向量所指向的区域。

对于受面限制的空间,默认区域位于曲面法线的负侧。

基于此默认区域,方向允许定义要保留的区域,称为内部材料。内部有四个方向。

取向 描述
向前 内部是默认区域。
内部是与默认区域互补的区域。
内部 内部包括两个地区。边界位于材料内部。例如,实体内的曲面。
外部 内陆不包括这两个地区。边界位于材料之外。例如,线框模型中的边。

四个方向如图:

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

方向的概念是一个非常笼统的概念,它可以用于出现区域或边界的任何上下文。因此,例如,在描述边和轮廓的交点时,不仅可以描述相交的顶点,还可以描述边如何与轮廓相交,将其视为边界。因此,边将分为两个区域:外部和内部,交点将是边界。因此,方向可以与交点顶点相关联,如下图所示:

取向 协会
向前 进入
退出
内部 从内部触摸
外部 从外面触摸

交点的四个方向:

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

除了方向枚举外,TopAbs 包还定义了四种方法:

3、状态

TopAbs_State枚举描述了一个顶点或一组顶点相对于某个区域的位置。有四个术语:

位置 描述
重点是内部。
重点是外部。
该点位于边界上(在公差范围内)。
未知 该点的状态是不确定的。

引入了 UNKNOWN 术语,因为此枚举通常用于表示计算的结果,计算结果可能会失败。当无法知道一个点是在内部还是外部时,可以使用此术语,例如明线或面。

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

State 枚举还可用于指定对象的各个部分。下图显示了与面相交的边部分。如图所示,状态指定边与面相交的部分

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

4、形状位置

局部坐标系可视为以下任一选项:

  • 具有原点和三个正交向量的右手三面体。gp_Ax2包对应于此定义。
  • 行列式的变换,允许在局部和全局参考帧之间变换坐标。这对应于gp_Trsf

TopLoc 软件包区分了两个概念:

  • TopLoc_Datum3D类提供基本参考坐标,由右手正交轴系统或右手酉变换表示。
  • TopLoc_Location类提供由基本参考坐标组成的复合参考坐标。它是一个标记,由对基本标记的引用链组成。存储生成的累积转换是为了避免重新计算整个列表的转换总和。

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

如果两个参考坐标由相同顺序的相同基本坐标组成,则它们相等。没有数值比较。因此,如果两个坐标不是从相同的基本坐标构建的,则它们可以对应于相同的变换,而不会相等。

例如,考虑三个基本坐标:R1、R2、R3 复合坐标为: C1 = R1 * R2, C2 = R2 * R3,C3 = C1 * R3,C4 = R1 * C2

注意:C3 和 C4 相等,因为它们都是 R1 * R2 * R3。

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

6、坐标变换

TopLoc_Datum3D类表示基本坐标的变化。必须共享此类更改,以便此类继承自Standard_Transient。坐标由变换gp_Trsfpackage表示。此转换没有比例因子。

1、操作形状和子形状

TopoDS软件包描述了具有以下特征的拓扑数据结构:

  • 引用既没有方向也没有位置的抽象形状。
  • 通过工具类访问数据结构。

如上所述,OCCT 拓扑描述了参数空间中对象的数据结构。这些描述使用此空间的某些部分的本地化和限制。可以用这些术语描述的形状类型是顶点、面和形状。顶点是根据参数空间中的定位来定义的,面和形状是根据该空间的限制来定义的。

OCCT拓扑描述还允许将这些术语中定义的简单形状组合成集合。例如,一组边形成一根导线;一组面形成一个壳,一组实体形成复合实体(开放式级联技术中的 CompSolid)。您还可以将任一类型的形状组合成化合物。最后,您可以为形状指定方向和位置。

按从顶点到复合实体的复杂程度顺序列出形状,导致我们将数据结构的概念作为如何将形状分解为一组更简单形状的知识。这实际上是 TopoDS 软件包的目的。

形状的模型是可共享的数据结构,因为它可以由其他形状使用。(一条边可以由实体的多个面使用)。可共享的数据结构通过引用处理。当简单参照不足时,将添加两条信息:方向和局部坐标参照。

  • 方向指示如何在边界中使用引用的形状(来自 TopAbs 的方向)。
  • 局部参考坐标(来自 TopLoc 的位置)允许在与其定义不同的位置引用形状。

***TopoDS_TShape***类是所有形状说明的根。它包含一个形状列表。如有必要,继承***TopoDS_TShape***的类可以携带几何域的描述(例如,与 TVertex 关联的几何点)。***TopoDS_TShape***是形状在其定义参考框架中的描述。此类由引用操作。

***TopoDS_Shape***类描述对形状的引用。它包含对底层抽象形状、方向和局部参考坐标的引用。此类由值操作,因此无法共享。

表示基础抽象形状的类永远不会直接引用。TopoDS_Shape类始终用于引用它。

特定于每个形状的信息(几何支持)始终通过继承添加到从***TopoDS_TShape***派生的类中。下图显示了由边连接的两个面形成的壳的示例。

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

在上图中,外壳由底层形状 TS 描述,面由 TF1 和 TF2 描述。从 TE1 到 TE7 有 7 条边,从 TV1 到 TV6 有 6 条顶点。

导线 TW1 参照从 TE1 到 TE4 的边;TW2 引用从 TE4 到 TE7。

边按如下方式引用顶点:
T E 1 ( T V 1 , T V 4 ) 、 T E 2 ( T V 1 , T V 2 ) 、 T E 3 ( T V 2 , T V 3 ) 、 T E 4 ( T V 3 , T V 4 ) 、 T E 5 ( T V 4 , T V 5 ) 、 T E 6 ( T 5 , T V 6 ) 、 T E 7 ( T V 3 , T V 6 ) TE1(TV1,TV4)、TE2(TV1,TV2)、TE3(TV2,TV3)、\\TE4(TV3,TV4)、TE5(TV4,TV5)、TE6(T5,TV6)、TE7(TV3,TV6) TE1(TV1TV4)TE2(TV1TV2)TE3(TV2TV3)TE4(TV3TV4)TE5(TV4TV5)TE6(T5TV6)TE7(TV3TV6)
请注意,此数据结构不包含任何反向引用。所有引用都从更复杂的基础形状转到不太复杂的形状。稍后将介绍用于访问信息的技术。数据结构尽可能紧凑。子对象可以在不同对象之间共享。

两个非常相似的对象(可能是同一对象的两个版本)可能共享相同的子对象。在数据结构中使用本地坐标允许共享重复子结构的描述。

紧凑的数据结构避免了与复制操作相关的信息的丢失,复制操作通常用于创建对象的新版本或应用坐标更改。

下图显示了包含两个版本的实体的数据结构。第二个版本展示了一系列在不同位置钻孔的相同孔。数据结构紧凑,但保留了有关子元素的所有信息。

TSh2 到底层面 TFcyl 的三个参照具有关联的局部坐标系,这些坐标系对应于孔的连续位置。

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

7、继承TopoDS_Shape类

TopoDS 基于类*TopoDS_Shape*和定义其底层形状的类。这有一定的优点,但主要缺点是这些类太笼统了。它们可以表示的不同形状不会键入它们(顶点、边缘等),因此不可能引入检查以避免不连贯,例如在边缘中插入面。

TopoDS 包提供两组类,一组继承基础形状,既没有方向也没有位置,另一组继承*TopoDS_Shape*,它们表示 TopAbs 包中列举的标准拓扑形状。

以下类继承形状:TopoDS_Vertex、TopoDS_Edge、TopoDS_Wire、TopoDS_Face、TopoDS_Shell、TopoDS_Solid、TopoDS_CompSolid 和*TopoDS_Compound*。尽管名称与继承自**TopoDS_TShape**的名称相似,但它们的使用方式却存在很大差异。

*TopoDS_Shape类和从它继承的类是操作拓扑对象的自然手段。TopoDS_TShape类是隐藏的。TopoDS_TShape描述没有方向的原始局部坐标系中的类。TopoDS_Shape是对具有方向和局部引用的TopoDS_TShape*的引用。

*TopoDS_TShape类被推迟;TopoDS_Shape*类不是。使用 TopoDS_Shape 类允许在不知道拓扑对象类型的情况下操作拓扑对象。它是一种通用形式。纯拓扑算法通常使用 TopoDS_Shape 类。

TopoDS_TShape类是通过引用操作的;按值TopoDS_Shape类。TopoDS_Shape只不过是用方向和局部坐标增强的参考。分享TopoDS_Shapes是没有意义的。重要的是共享基础TopoDS_TShapes。参数中的赋值或段落不会复制数据结构:这只会创建引用相同*TopoDS_TShape的新TopoDS_Shapes*。

尽管继承*TopoDS_TShape的类用于添加额外信息,但不应在从TopoDS_Shape继承的类中添加额外的字段。从TopoDS_Shape继承的类仅用于专用化引用,以便从静态类型控制(由编译器执行)中受益。例如,对于编译器来说,接收参数TopoDS_Face的例程比接收TopoDS_Shape*的例程更精确。派生除 TopoDS 中的类之外的其他类是没有意义的。对拓扑数据结构的所有引用都是使用 TopoDS 中定义的 Shape 类及其继承者进行的。

TopoDS_Shape 类继承的类没有构造函数,否则类型控件将通过隐式强制转换消失(C++ 的特征)。TopoDS 包提供了用于在这些子类之一中强制转换 *TopoDS_Shape*类对象的包方法,并具有类型验证。

下面的示例演示一个例程,该例程接收 TopoDS_Shape 类型的参数,然后将其放入变量 V 中(如果它是顶点)或调用方法 ProcessEdge(如果它是边)。

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

*TopExp软件包提供了用于探索TopoDS*软件包描述的数据结构的工具。探索拓扑结构意味着查找给定类型的所有子对象,例如,查找实体的所有面。

TopExp 包提供了类*TopExp_Explorer*来查找给定类型的所有子对象。资源管理器是用以下内容构建的:

  • 要探索的形状。
  • 要找到的形状类型,例如 VERTEX、EDGE,但不允许使用的 SHAPE 除外。
  • 要避免的形状的类型。例如壳牌、边缘。默认情况下,此类型为 SHAPE。此默认值表示对探索没有限制。

资源管理器访问整个结构,以便查找所请求类型的形状未包含在要避免的类型中。下面的示例显示了如何查找形状 S 中的所有面:

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

查找所有不在边中的顶点

for (Ex.Init(S,TopAbs_VERTEX,TopAbs_EDGE); ...) 

查找 SHELL 中的所有面,然后查找不在 SHELL 中的所有面:

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 ina shell. 
    ProcessFace(Ex1.Current()); 
  }
}

资源管理器假定对象仅包含相同或较低类型的对象。例如,如果搜索面,则不会查看导线、边或顶点以查看它们是否包含面。

TopExp包中的MapShapes方法允许填充映射。如果多次引用某个对象,则使用 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(); 
  }
}

在下面的示例中,对象的所有面和所有边都是按照以下规则绘制的:

  • 面由具有FaceIsoIso颜色NbIso等参数线网络表示。
  • 边缘以颜色绘制,该颜色指示共享边缘的面数:
    • 自由边颜色,用于不属于面(即线框元素)的边。
    • 属于单个面的边的边框边缘颜色
    • 共享边颜色,表示属于多个面的边。
  • DrawEdgeDrawFaceIso 方法也可用于显示单个边缘和面。

执行以下步骤:

  1. 将边存储在映射中,并并行创建一个整数数组,以计算共享边的面数。此数组初始化为零。
  2. 探索面孔。绘制每个面。
  3. 探索边缘并为每个边缘增加数组中面的计数器。
  4. 从边映射中,使用与面数相对应的颜色绘制每条边。
void DrawShape ( const TopoDS_Shape& aShape, 
const Standard_Integer nbIsos, 
const Color FaceIsocolor, 
const Color FreeEdgeColor, 
const Color BorderEdgeColor, 
const Color SharedEdgeColor) 
{ 
  // Store the edges in aMap. 
  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 
  Standard_Integer i; 
  for (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; 
    }
  } 
} 
形状的列表和映射

TopTools 软件包包含用于利用 TopoDS 数据结构的工具。它是 TCollection 包中工具的实例化,其中包含 TopoDS 的 Shape 类。

  • TopTools_Array1OfShape,HArray1OfShape – 用*TopoDS_Shape实例化NCollection_Array1*。
  • TopTools_SequenceOfShape – 使用*TopoDS_Shape实例化NCollection_Sequence*。
  • TopTools_MapOfShape - *NCollection_Map*的实例化。允许构造形状集。
  • TopTools_IndexedMapOfShape - *NCollection_IndexedMap*的实例化。允许构造形状表和其他数据结构。

使用TopTools_Map,可以保留一组对形状的引用而不会重复。以下示例将数据结构的大小计为多个 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. 
  TopoDS_Iterator It; 
  Standard_Integer size = 1; 
  for (It.Initialize(aShape);It.More();It.Next()) { 
    size += Size(It.Value()); 
  } 
  return size; 
} 

如果数据结构中有共享,则此程序不正确。

因此,对于四条边的轮廓,它应该计算 1 根导线 + 4 条边 +4 个顶点,结果为 9,但由于每个顶点由两条边共享,该程序将返回 13。一种解决方案是将所有形状放在映射中,以避免对它们进行两次计数,如以下示例所示:

#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. 
    TopoDS_Iterator It; 
    for (It.Initialize(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();
}

注意有关映射的更多详细信息,请参阅 TCollection 文档(基础类参考手册)。

下面的示例更加雄心勃勃,并编写了一个使用 IndexedMap 复制数据结构的程序。副本的结构相同,但与原件没有任何共同之处。主要算法如下:

  • 结构中的所有形状都放入索引映射中。
  • 与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; 
  Standard_Integer i; 
  TopoDS_Shape S; 
  TopLoc_Location Identity; 
  S = aShape; 
  S.Location(Identity); 
  S.Orientation(TopAbs_FORWARD); 
  theMap.Add(S); 
  for (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 中插入所有子对象,如果它们尚未在 Map 中,则以大于 i 的索引插入它们。

请注意,插入的对象带有设置为标识的本地引用和 FORWARD 方向。只有底层的 TShape 才引起极大的兴趣。

//Create an array to store the copies. 
TopTools_Array1OfShapetheCopies(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 thecorrect local reference and orientation. 
S = theCopies(1); 
S.Location(aShape.Location()); 
S.Orientation(aShape.Orientation()); 
return S; 

下面是辅助函数,它将秩 i 的元素从映射复制到表中。此方法检查对象是否已复制;如果未复制,则在表中执行空副本,并通过在映射中找到其排名来插入所有子元素的副本。

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_Iterator It; 
    TopoDS_Shape S; 
    TopLoc_Location Identity; 
    for(It.Initialize(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);
    }
  }
}

线浏览器

*BRepTools_WireExplorer*类可以按其连接顺序访问导线的边缘。

例如,在图像中的导线中,我们希望按 {e1, e2, e3,e4, e5} 的顺序恢复边缘:

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

但是,*TopExp_Explorer*以任何顺序恢复线路。

TopoDS_Wire W = ...; 
BRepTools_WireExplorer Ex; 
for(Ex.Init(W); Ex.More(); Ex.Next()) { 
  ProcessTheCurrentEdge(Ex.Current()); 
  ProcessTheVertexConnectingTheCurrentEdgeToThePrevious 
  One(Ex.CurrentVertex()); 
} 

8、形状的属性

1、形状的局部属性

BRepLProp 包提供形状的局部属性组件,该组件包含计算 BRep 模型中边和面上的各种局部属性的算法。

可以查询的本地属性包括:

  • 对于支持边的曲线上的参数 u 点:
    • 重点,
    • 导数向量,最高三度,
    • 切向量,
    • 正常,
    • 曲率和曲率中心;
  • 对于支撑面的曲面上的参数点 (u, v):
    • 重点,
    • 导数向量,最高二阶,
    • U和V等参数曲线的切向量,
    • 法向量,
    • 最小或最大曲率,以及相应的曲率方向;
  • 支撑边的曲线的连续程度,该边由另外两条边在其交汇点处串联构建。

分析的边和面被描述为 BRepAdaptor 曲线和曲面,它们为形状提供用于描述其几何支撑的界面。局部属性的基点由曲线上的 u 参数值或曲面上的 (u, v) 参数值定义。

2、曲线和曲面的局部属性

“曲线和曲面的局部属性”组件提供了用于计算几何曲线(在 2D 或 3D 空间中)或曲面上的各种局部属性的算法。它由以下部分组成:

  • Geom2dLProp 包,允许计算 2D 曲线上参数点的导数和切向量(法向和曲率);
  • GeomLProp 软件包,可在 3D 曲线和曲面上提供局部属性
  • LProp 包,提供用于表征 2D 曲线上特定点的枚举。

曲线可以是*Geom_Curve曲线(在 3D 空间中)或Geom2d_Curve曲线(在平面中)。曲面是Geom_Surface*曲面。计算局部属性的点由曲线上的 u 参数值和曲面上的 (u,v) 参数值定义。

可以查询上述点的相同局部属性,还可以查询 2D 曲线:

  • 对应于最小或最大曲率的点;
  • 拐点。
示例:如何检查表面凹陷

要检查曲面的凹度,请执行以下操作:

  1. 对曲面进行采样并计算每个点的高斯曲率。
  2. 如果曲率值改变符号,则根据视点的不同,表面是凹的还是凸的。
  3. 要计算高斯曲率,请使用 GeomLProp 中的类 SLprops,该类实例化了 LProp 中的泛型类 SLProps,并使用 GaussianCurvature 方法。
3、曲线和曲面的连续性

GeomAbs_Shape枚举中介绍了曲线和曲面支持的连续性类型。

在曲线方面,支持以下类型的连续性(见下图):

  • C0 (GeomAbs_C0) - 参数连续性。它与 G0(几何连续性)相同,因此最后一个不是由单独的变量表示的。
  • G1 (GeomAbs_G1) - 左侧和右侧的切向量是平行的。
  • C1 (GeomAbs_C1) - 表示一阶导数的连续性。
  • G2 (GeomAbs_G2) - 除了 G1 连续性外,左右的曲率中心是相同的。
  • C2 (GeomAbs_C2) - 所有导数直到二阶的连续性。
  • C3 (GeomAbs_C3) - 所有导数直到三阶的连续性。
  • CN (GeomAbs_CN) - 所有导数直到第 N 阶的连续性(连续性的无限阶数)。

*注意:*几何连续性(G1、G2)意味着曲线可以重新参数化以具有参数化(C1、C2)连续性。

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

支持以下类型的表面连续性:

  • C0 (GeomAbs_C0) - 参数连续性(表面没有不连续性的点或曲线)。
  • G1 (GeomAbs_G1) - 曲面在每个点上都有单个切平面。
  • C1 (GeomAbs_C1) - 表示一阶导数的连续性。
  • G2 (GeomAbs_G2) - 除了 G1 连续性外,主曲率和方向也是连续的。
  • C2 (GeomAbs_C2) - 所有导数直到二阶的连续性。
  • C3 (GeomAbs_C3) - 所有导数直到三阶的连续性。
  • CN (GeomAbs_CN) - 所有导数直到第 N 阶的连续性(连续性的无限阶数)。

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

对于单个曲面,两个曲面的连接(见上图)仅定义其在每个交点中的连续性。连接的平滑度是相交曲线上连续性的最小值。

4、共享边的规律性

边的规则性是共享此边的两个面连接的平滑度。换句话说,规则性是边上每个点的连接面之间的最小连续性。

边缘的规律性可以通过BRep_Builder::Continuity方法设置。要获得规律性,请使用BRep_Tool::Continuity方法。

Fillet 这样的一些算法通过自己的算法设置生成的边的规律性。另一方面,其他一些算法(如布尔运算、形状修复等)不设置规律性。如果需要在形状上正确设置规则性,则可以使用方法BRepLib::EncodeRegularity。它计算并为形状的所有边缘设置正确的值。

规则性标志被以下高级算法广泛使用:倒角、拔模角度、隐藏线去除、糊盒机。

5、形状的全局属性

形状的全局属性组件提供用于计算 3D 空间中复合几何系统的全局属性的算法,以及用于查询计算结果的框架。

为系统计算的全局属性是:

  • 质量
  • 质量中心,
  • 惯性矩阵,
  • 关于轴的力矩,
  • 绕轴回转半径,
  • 惯性的主要属性,如主轴、主弯矩和主回转半径。

几何系统通常定义为形状。根据分析它们的方式,这些形状将提供以下属性:

  • 从形状边缘诱导的线条,
  • 从形状的表面感应的表面,或
  • 体积由形状限定的实体诱导。

可以将几个系统的全局属性组合在一起,以给出由所有单个系统的总和组成的系统的全局属性。

“形状的全局属性”组件由以下部分组成:

  • 用于计算形状全局属性的七个函数:一个函数用于线条,两个函数用于表面,四个函数用于体积。函数的选择取决于用于计算的输入参数和算法(BRepGProp 全局函数),
  • 用于计算一组点的全局属性的框架(GProp_PGProps),
  • 一个通用框架,用于将几个更基本框架保留的全局属性组合在一起,并提供一个通用编程接口来查询计算的全局属性。

GeomLPropGeom2dLProp 软件包提供计算曲线和曲面局部属性的算法

曲线(对于一个参数)具有以下局部属性:

  • 导数
  • 切线
  • 正常
  • 曲率
  • 曲率中心。

曲面(对于两个参数 U 和 V)具有以下局部属性:

  • 你和 V) 的衍生品)
  • 切线(U 和 V)
  • 正常
  • 最大曲率
  • 最小曲率
  • 曲率的主要方向
  • 平均曲率
  • 高斯曲率

可以使用以下方法:

  • CLProps – 计算曲线的局部属性(切线、曲率、法线);
  • CurAndInf2d – 计算 2d 曲线的最大和最小曲率以及拐点;
  • SLProps – 计算曲面的局部属性(切线、法线和曲率)。
  • 连续性 – 计算两条曲线交界处的规律性。

请注意,B样条曲线和曲面是可以接受的,但它们不会被切割成所需连续性的碎片。这是全球连续性,这是可见的。

6、曲线和曲面适配器

一些开放级联技术通用算法理论上可以适用于多种类型的曲线或曲面。

为此,他们只需通过接口获取分析曲线或曲面所需的服务,以便获得单个 API,无论曲线或曲面的类型如何。这些接口称为适配器。

例如, Adaptor3d_Curve是一个抽象类,它通过使用任何 3D 曲线的算法提供所需的服务。

GeomAdaptor软件包提供接口:

  • 在几何曲线上;
  • 在位于几何曲面上的曲线上;
  • 在几何表面上;

Geom2dAdaptor软件包提供接口:

  • Geom2d 曲线上。

BRep适配器封装提供接口:

  • 在面上
  • 在边缘上

编写对几何对象进行操作的算法时,请使用 Adaptor3d(或 Adaptor2d)对象。

因此,如果您为该对象提供派生自 Adaptor3d 或 Adaptor2d 的接口,则可以将该算法用于任何类型的对象。这些接口易于使用:只需从Geom2d曲线创建自适应曲线或曲面,然后将此自适应曲线用作算法的参数。这需要它。

9、边界框

边界框用于许多 OCCT 算法。最常见的用途是作为过滤器,避免检查形状对之间的过多干涉(检查边界框之间的干涉比形状之间的干涉要简单得多,如果它们不干涉,那么搜索相应形状之间的干涉就没有意义)。通常,边界框可以分为两种主要类型:

  • 轴对齐边界框 (AABB) 是其边平行于世界坐标系 (WCS) 轴的框;
  • 定向 BndBox (OBB) 在其自己的坐标系中定义,可以相对于 WCS 旋转.事实上, AABB是OBB的一个特定案例.

下图说明了使用OBB比AABB更好的示例。

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

此图中的 AABB 受到干扰。因此,许多OCCT算法会花费大量时间来干扰形状。然而, 如果我们检查没有干扰的 OBB, 那么就不需要搜索形状之间的干涉.此时,创建和分析 OBB 比使用 AABB 的类比运算花费的时间要多得多.

此图中的 AABB 受到干扰。因此,许多OCCT算法会花费大量时间来干扰形状。然而, 如果我们检查没有干扰的 OBB, 那么就不需要搜索形状之间的干涉.此时,创建和分析 OBB 比使用 AABB 的类比运算花费的时间要多得多.

  • IsVoid 指示边界框是否为空(未初始化)。
  • SetVoid 清除现有的边界框。
  • Enlarge(…) 扩大当前边界框。
  • Add(…) 根据需要扩展边界框,以包括作为参数传递的对象(点、形状等)。
  • IsOut(…) 根据需要扩展边界框,以包括作为参数传递的对象(点、形状等)。

BRepBndLib 类包含从形状创建边界框(AABBOBB)的方法。

一些使用OBB的算法的简要说明
从一组点创建OBB

该算法在Thomas Larsson和Linus Källberg(FastOBBs.pdf)的“紧拟合导向边界框的快速计算”中进行了描述。它包括以下步骤:
(待更新…)

从一组点创建最佳OBB

为了从点集创建最佳OBB使用与上述相同的算法,但对逻辑进行了一些简化并增加了计算时间.为了获得最佳的OBB, 有必要检查所有可能的轴, 这些轴可以由极点创建.由于极值点仅对初始轴有效,因此有必要在每个轴上投影整组点。这种方法通常提供更紧密的OBB但性能较低.该算法的复杂性仍然是线性的,并且使用BVH作为点集,它是 O ( N + C ∗ l o g ( N ) ) O(N + C * log(N)) O(N+Clog(N))

以下是使用125K节点集的模型的最佳和非最佳OBB示例:

opencascade 源码,OCC,算法,c++,3d,图形渲染,数据结构

在这种情况下,非最佳 OBB 的计算需要 0.007 秒, 最佳 - 0.1 秒, 这大约慢了 14 倍.这样的性能与通过PCA方法为这种形状创建OBB相当 (见下文) 大约需要 0.17 秒.

最优OBB的计算由BRepBndLib::AddOBB方法中与PCA算法相同的IsOptimal标志控制。

这些算法在 Bnd_OBB::ReBuild(…) 方法中实现。

基于惯性轴创建OBB

该算法包含以下步骤:

  1. 计算三个惯性轴, 这将是 OBB 的轴.
  2. 根据项目 1 中的轴将源对象 TopoDS_Shape 转换为局部坐标系。
  3. 为在项目 2 中获得的形状创建 AABB。
  4. 计算 AABB 的中心及其半维。
  5. 将中心转换为 WCS。
  6. 创建 OBB 使用中心, 轴和半尺寸.
IsOut 方法为一个点
  1. 将点投影到每个轴。
  2. 检查投影参数的绝对值是否大于对应的半维。在这种情况下,IsOut 方法将返回 TRUE。
IsOut 方法为另一个OBB

根据“定向边界框的分离轴定理” ,需要检查15个分隔轴:框的6个轴和9个是它们的交叉乘积。
分析轴的算法l如下:

(待更新…)

如果OBB在至少一个轴(15)方面没有受到干扰,那么它们根本不会受到干扰.

Add 方法 为点或其他边界框

创建一个新的 OBB基于源点和给定边界框的所有顶点.

添加形状

方法 *BRepBndLib::AddOBB( … )*允许从复杂对象 TopoDS_Shape 创建边界框。此方法使用从点集创建OBB和基于惯性轴创建OBB部分中描述的算法。

如果形状的外壳可以由其中包含的一组点表示,则使用第一种算法。也就是说,只有以下元素是点集的来源:

  • 三角测量节点;
  • Poly_Polygon3D节点;
  • 位于平面中的线性 3D 曲线的边顶点;
  • 具有线性 3D 曲线的边顶点,如果源形状不包含更复杂的拓扑结构(例如,源形状是边的复合);
  • 顶点,如果源形状不包含更复杂的拓扑结构(例如,源形状是顶点的复合)。

如果无法提取所需的点集,则基于惯性轴创建OBB部分中的算法用于OBB创建.

包* BRepBndLib* 包含用于创建形状的 AABB 的方法 BRepBndLib::Add(…)BRepBndLib::AddClose(…) 和 BRepBndLib::AddOptimal(…)*。文章来源地址https://www.toymoban.com/news/detail-654492.html

OBB创建算法的局限性.
  1. 从点集创建OBB部分中描述的算法比基于惯性轴创建OBB部分中的算法工作得更好(找到表面积较小的结果OBB)和更快的算法。然而, (一般来说) 两种算法返回的结果并不总是最优的 (即有时存在另一个表面积较小的 OBB).此外, 第一种方法不允许计算具有复杂几何形状的 OBB.
  2. 目前, OBB创建算法仅适用于3D空间中的对象.

到了这里,关于Opencascade源码学习之模型数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包