occt_modeling_algos(一)——标准拓扑实体

news/2024/7/15 17:18:37 标签: 算法, 图论, OpenCascade, c++

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

在OCC中可以构建如下标准拓扑实体

文章目录

  • 顶点(Vertex)
  • 边(Edge)
    • 基础的边构造方法(Basic edge construction method)
    • 补充的边构造方法(Supplementary edge construction methods)
    • 其他的信息和错误状态(Other information and error status)
  • 2D边(Edge 2D)
  • 多边形(Polygon)
  • 面(Face)
    • 基础的面构建方法(Basic face construction method)
    • 补充的面构建方法(Supplementary face construction methods)
    • 错误状态(Error status)
  • 线框(Wire)
  • 壳(Shell)
  • 刚体(Solid)

这里对于标准拓扑实体的构建(construction)和修改(modification)有两个基类(root classes):

  • 滞后类(deferred class) BRepBuilderAPI_MakeShape 是所有用于构建形状的 BRepBuilderAPI 类的根类。它继承于 BRepBuilderAPI_Command 类,其提供了一个用于存储被构建形状的区域。
  • 滞后类(deferred class) BRepBuilderAPI_ModifyShape 被用作形状修改类的根类。它继承于 BRepBuilderAPI_MakeShape 且实现了用于追溯所有子形状历史的方法。

顶点(Vertex)

BRepBuilderAPI_MakeVertex 基于 gp 类下的一个三维点(3D point)创建一个新的顶点(vertex)。

gp_Pnt P(0,0,10);
TopoDS_Vertex V = BRepBuilderAPI_MakeVertex(P);

这个类总是创建一个新的顶点,且没有其他的方法。


边(Edge)

基础的边构造方法(Basic edge construction method)

使用 BRepBuilderAPI_MakeEdge 去从一条曲线与顶点去构建边。由一条曲线(curve),两个顶点(vertices)和两个参数(parameters)构建一条边的代码如下:

Handle(Geom_Curve) C = ...; // a curve
TopoDS_Vertex V1 = ...,V2 = ...; // two Vertices
Standard_Real p1 = ..., p2 = ...; // two parameters
TopoDS_Edge E = BRepBuilderAPI_MakeEdge(C,V1,V2,p1,p2);

这里的 C 是边的域(domain);V1 是第一个顶点,其面向(oriented) FORWARD; V2 是第二个顶点,其面向 REVERSED;p1p2 是关于顶点 V1V2 在曲线上的参数。默认容差(tolerance)与这条边有关。

下面是应用于参数的规则

曲线(curve)

  • 必须不是一个 Null Handle
  • 如果曲线是一个裁剪(trimmed)曲线,基(basis)曲线被使用

顶点(vertices)

  • 可以是 null shapes。当 V1V2 是 Null,边就在对应方向是开放(open)的,相应的参数 p1p2 必须是无穷的 (即 p1RealFirst(), p2RealLast())。
  • 如果它们有不同的三维位置,就必须是不同的顶点。如果它们有相同的三维位置,就必须是相同的顶点(当曲线是闭合时,会用到相同的顶点)。

参数(parameters)

  • 必须是递增的,且在曲线的有效参数域内,那就是说:
C->FirstParameter() <= p1 < p2 <= C->LastParameter()
  • 如果参数是递减的,那么顶点就会被交换,即 V2 变成 V1V1 变成 V2
  • 在一个周期曲线(periodic curve)上,通过增加或减少周期(period)去调整参数 p1p2,以获得在曲线参数域内的 p1 和 在范围 p1<p2<=p1+Period 范围内的 p2。所以在一条参数曲线上,p2 是有可能大于 p1 的,如下图所示。
  • 参数可以是无穷,但是相应的顶点必须是 Null
  • 顶点对应三维位置与曲线使用参数计算出的点的位置之间的距离必须小于默认精度

下图展示了两种特殊情况,一条半无限(semi-infinite)的边和一条在周期曲线上的边


补充的边构造方法(Supplementary edge construction methods)

这里还有从基础的边构造方法衍生出的补充的边构造方法。

BRepBuilderAPI_MakeEdge 类提供方法,简化对之前方法的调用:

  • 参数可以被省略。可以通过将顶点映射到曲线计算得到。
  • 3维点(gp类的Pnt) 可以替代顶点作为参数。顶点(vertices)基于点(points)构建。当创建关联顶点时,给定顶点是有用的。
  • 如果参数被给出,顶点或点可以被省略。点通过曲线上的参数计算得到。
  • 顶点或点以及参数都可以被省略。此时,曲线的首尾参数将会被使用。

下面的五个方法是由基构建方法衍生而出:

Handle(Geom_Curve) C = ...; // a curve
TopoDS_Vertex V1 = ...,V2 = ...;// two Vertices
Standard_Real p1 = ..., p2 = ..;// two parameters
gp_Pnt P1 = ..., P2 = ...;// two points
TopoDS_Edge E;
// project the vertices on the curve
E = BRepBuilderAPI_MakeEdge(C,V1,V2);
// Make vertices from points
E = BRepBuilderAPI_MakeEdge(C,P1,P2,p1,p2);
// Make vertices from points and project them
E = BRepBuilderAPI_MakeEdge(C,P1,P2);
// Computes the points from the parameters
E = BRepBuilderAPI_MakeEdge(C,p1,p2);
// Make an edge from the whole curve
E = BRepBuilderAPI_MakeEdge(C);

六个方法(五个上面的加基础方法)也由 gp 包提供给曲线,以代替 Geom 的 Curve。方法源于Geom的相关曲线,然后以如下类的形式实现:

  • gp_Lin 创建一个 Geo_Line
  • gp_Elips 创建一个 Geom_Ellipse
  • gp_Hypr 创建一个 Geom_Hyperbola
  • gp_Parab 创建一个 Geom_Parabola

这里也有两种方法去由两个顶点或两个点构造边。这些方法假定曲线是一条直线;顶点或点必须有不同的位置。

TopoDS_Vertex V1 = ...,V2 = ...;// two Vertices
gp_Pnt P1 = ..., P2 = ...;// two points
TopoDS_Edge E;
// linear edge from two vertices
E = BRepBuilderAPI_MakeEdge(V1,V2);
// linear edge from two points
E = BRepBuilderAPI_MakeEdge(P1,P2);

其他的信息和错误状态(Other information and error status)

BRepBuilderAPI_MakeEdge 类可以提供额外的信息和返回一个错误状态。

如果 BRepBuilderAPI_MakeEdge 被用作一个类,它可以提供两个顶点。这在顶点没有以参数形式提供时是有用的,例如当边是由一条曲线和参数构建时。两个方法 Vertex1Vertex2 返回顶点。需要注意的是,如果边在某个方向的是开放的,那么返回的对应顶点可能是 null。

Error 方法返回 BRepBuilderAPI_EdgeError 枚举中的一项。当 IsDone 方法返回 False 时可以用于分析错误。其枚举有如下项:

  • EdgeDone —— 没有错误发生,IsDone 返回 True
  • PointProjectionFailed —— 没有提供参数,且由三维点映射到曲线失败。这种情况会在点到曲线的距离大于精度时产生。
  • ParameterOutOfRange —— 给定的参数不在 C->FirstParameter(), C->LastParameter() 范围内。
  • DifferentPointsOnClosedCurve —— 两个顶点或点有不同的位置,但曲线是闭合曲线。
  • PointWithInfiniteParameter —— 一个有限的坐标点却和一个无限的参数相关(可以看看Precision包关于无限值的定义)。
  • DifferentsPointAndParameter —— 三维点与曲线参数计算后的点的距离大于给定精度。
  • LineThroughIdenticPoints —— 两个相同的点被给定去定义一条线(一条没有曲线的边的构建),gp::Resolution 被用于测试混乱(confusion)。

下面的例子创建一个中心在维度H,L的原点的矩形,且有半径为R的圆角。边和点都被保存在数组 theEdgestheVertices 中。我们使用类 Array1OfShape(即不是边或顶点的数组)。看下图:

#include <BRepBuilderAPI_MakeEdge.hxx>
#include <TopoDS_Shape.hxx>
#include <gp_Circ.hxx>
#include <gp.hxx>
#include <TopoDS_Wire.hxx>
#include <TopTools_Array1OfShape.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
// Use MakeArc method to make an edge and two vertices
void MakeArc(Standard_Real x,Standard_Real y,
Standard_Real R,
Standard_Real ang,
TopoDS_Shape& E,
TopoDS_Shape& V1,
TopoDS_Shape& V2)
{
gp_Ax2 Origin = gp::XOY();
gp_Vec Offset(x, y, 0.);
Origin.Translate(Offset);
BRepBuilderAPI_MakeEdge
ME(gp_Circ(Origin,R), ang, ang+PI/2);
E = ME;
V1 = ME.Vertex1();
V2 = ME.Vertex2();
}
TopoDS_Wire MakeFilletedRectangle(const Standard_Real H,
const Standard_Real L,
const Standard_Real R)
{
TopTools_Array1OfShape theEdges(1,8);
TopTools_Array1OfShape theVertices(1,8);
// First create the circular edges and the vertices
// using the MakeArc function described above.
void MakeArc(Standard_Real, Standard_Real,
Standard_Real, Standard_Real,
TopoDS_Shape&, TopoDS_Shape&, TopoDS_Shape&);
Standard_Real x = L/2 - R, y = H/2 - R;
MakeArc(x,-y,R,3.*PI/2.,theEdges(2),theVertices(2),
theVertices(3));
MakeArc(x,y,R,0.,theEdges(4),theVertices(4),
theVertices(5));
MakeArc(-x,y,R,PI/2.,theEdges(6),theVertices(6),
theVertices(7));
MakeArc(-x,-y,R,PI,theEdges(8),theVertices(8),
theVertices(1));
// Create the linear edges
for (Standard_Integer i = 1; i <= 7; i += 2)
{
theEdges(i) = BRepBuilderAPI_MakeEdge
(TopoDS::Vertex(theVertices(i)),TopoDS::Vertex
(theVertices(i+1)));
}
// Create the wire using the BRepBuilderAPI_MakeWire
BRepBuilderAPI_MakeWire MW;
for (i = 1; i <= 8; i++)
{
MW.Add(TopoDS::Edge(theEdges(i)));
}
return MW.Wire();
}

2D边(Edge 2D)

使用 BRepBuilderAPI_MakeEdge2d 类去在一个工作平面基于2d曲线构建边。工作平面(working plane)是 BRepBuilderAPI 包的一个默认值(可以看看 Plane 方法)。

BRepBuilderAPI_MakeEdge2d 类是与 BRepBuilderAPI_MakeEdge 严格相似的,区别是它使用 gpGeom2d 的2D几何而不是3D几何。


多边形(Polygon)

BRepBuilderAPI_MakePolygon 类被用于基于顶点或点构建多边形线框。在 BRepBuilderAPI_MakeEdge 里点是被自动改变为顶点。

BRepBuilderAPI_MakePolygon 的基础使用是通过使用 Add 方法增加顶点或点来创建一个线框(wire)。无论何时,当前线框都是能被提取(extracted)的。close 方法被用于关闭当前线框。在下面的例子中,一个闭合线框基于一个点数组创建。

#include <TopoDS_Wire.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <TColgp_Array1OfPnt.hxx>
TopoDS_Wire ClosedPolygon(const TColgp_Array1OfPnt& Points)
{
BRepBuilderAPI_MakePolygon MP;
for(Standard_Integer i=Points.Lower();i=Points.Upper();i++)
{
MP.Add(Points(i));
}
MP.Close();
return MP;
}

对于2,3或者4个点或顶点,提供了快捷的方式(short-cuts)。这些方法都有一个Boolean的last参数去告知是否多边形是封闭的。默认值是 False

两个例子:

  • 由三个顶点构建一个闭合三角形的例子:
TopoDS_Wire W = BRepBuilderAPI_MakePolygon(V1,V2,V3,Standard_True);
  • 由四个点构建一个开放的多边形
TopoDS_Wire W = BRepBuilderAPI_MakePolygon(P1,P2,P3,P4);

BRepBuilderAPI_MakePolygon 类包含一个当前线框。当前线框可以在任意时刻提取,构造为一个更长的线框。在每个点插入之后,类保存最后创建的边和点,可以通过 Edge,FirstVertexLastVertex方法返回。

当被添加的点或顶点在之前的线框中由相同的位置,它不会被添加到当前线框,而是使最后创建的边变成NUll。Added 方法可以被使用去测试这种情况。MakePolygon 类不会抛出任何异常。如果没有顶点被添加,Wire 是 Null。如果两个顶点在相同位置,没有边会被创建。


面(Face)

使用 BRepBuilderAPI_MakeFace 类基于一个曲面(surface)和线框(wires)创建一个面。一个隐式曲面由一个曲面和可选的参数值构建。线框可以被添加到曲面。一个平面可以基于一个线框构建。一个错误状态会在面构建完之后返回。

基础的面构建方法(Basic face construction method)

一个面可以由一个曲面(surface)和四个决定UV空间限制的参数构建。参数是可选的,如果它们被省略,曲面的自然边界就被使用。使用线框的话会有多达四条边和顶点被创建。当参数是无穷时,没有边被创建。

Handle(Geom_Surface) S = ...; // a surface
Standard_Real umin,umax,vmin,vmax; // parameters
TopoDS_Face F = BRepBuilderAPI_MakeFace(S,umin,umax,vmin,vmax);


为了基于一个曲面的自然边界构建一个面,参数是不需要的:

Handle(Geom_Surface) S = ...; // a surface
TopoDS_Face F = BRepBuilderAPI_MakeFace(S);

在参数方面的限制是与BRepBuilderAPI_MakeEdge相似的:

  • umin,umax(vmin,vmax)必须在曲面的范围内,且必须是递增的。
  • 在一个 U(V) 周期曲面,uminumax(vmin,vmax)是被调整的。
  • umin,umax,vmin,vmax可以是无限的。这表示在对应方向将会没有边。

补充的面构建方法(Supplementary face construction methods)

对于所有 gp 包的曲面,两个基础构建(基于一个曲面和基于一个曲面和参数)被实现,由 Geom 转换为相应的 Surface。

gp package surfaceGeom package surface
gp_PlnGeom_Plane
gp_CylinderGeom_CylindricalSurface
gp_Conecreates aGeom_ConicalSurface
gp_SphereGeom_SphericalSurface
gp_TorusGeom_ToroidalSurface

一旦一个面被创建,可以使用 Add 方法添加一个线框。例如,下面的代码创建一个圆柱曲面,然后添加一个线框。

gp_Cylinder C = ..; // a cylinder
TopoDS_Wire W = ...;// a wire
BRepBuilderAPI_MakeFace MF(C);
MF.Add(W);
TopoDS_Face F = MF;

对于一个面可以添加多个线框,只要它们没有互相交叉且只在曲面定义一个区域。(注意这并没有被检查)。

对于一个线框,一个简单的语法被提供去基于曲面(surface)和线框(wire)构建面(face)。上面的线可以写为:

TopoDS_Face F = BRepBuilderAPI_MakeFace(C,W);

一个面上的边必须有一个参数曲线描述。如果这里对于面上线框的边没有参数曲线,它通过映射进行计算。此外,计算只可能用于平面。

一个平面可以仅由一个线框创建,只要这个线框顶一个平面。例如,为了基于点集创建一个平面,你可以使用 BRepBuilderAPI_MakePolygonBRepBuilderAPI_MakeFace.

#include <TopoDS_Face.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
TopoDS_Face PolygonalFace(const TColgp_Array1OfPnt& thePnts)
{
BRepBuilderAPI_MakePolygon MP;
for(Standard_Integer i=thePnts.Lower();
i<=thePnts.Upper(); i++)
{
MP.Add(thePnts(i));
}
MP.Close();
TopoDS_Face F = BRepBuilderAPI_MakeFace(MP.Wire());
return F;
}

还可以使用 MakeFace 去从一个存在的面拷贝一份,然后添加新的线框。例如,下面的代码给一个面添加一个新的线框。

TopoDS_Face F = ...; // a face
TopoDS_Wire W = ...; // a wire
F = BRepBuilderAPI_MakeFace(F,W);

为了添加多余一个线框,一个BRepBuilderAPI_MakeFace类的实例可以被构建,基于面、第一个线框和被插入的新线框,使用 Add 方法。


错误状态(Error status)

Error 方法返回一个错误状态,这是 BRepBuilderAPI_FaceError 枚举中的一项,

  • FaceDone —— 没有错误产生
  • NoFace —— 没有初始化算法;一个空的构造器被使用。
  • NotPlanar —— 没有给定曲面,且线框不是平面。
  • CurveProjectionFailed —— 对于一条边,没有曲线能在参数空间内找到。
  • ParametersOutOfRange —— 参数 umin,umax,vmin,vmax超出曲面边界

线框(Wire)

线框是一个复合形状,其构建不仅基于一个几何,也基于边的集合。BRepBuilderAPI_MakeWire类可以基于一个或更多边或连接新边到一个现存的线框中去构建一个线框。

多达四个边可以被直接使用,例如:

TopoDS_Wire W = BRepBuilderAPI_MakeWire(E1,E2,E3,E4);

对于一个更高或未知数量的边,Add方法必须被使用;例如,基于形状数组(边数组)构建一个线框。

TopTools_Array1OfShapes theEdges;
BRepBuilderAPI_MakeWire MW;
for (Standard_Integer i = theEdge.Lower();
i <= theEdges.Upper(); i++)
MW.Add(TopoDS::Edge(theEdges(i));
TopoDS_Wire W = MW;

类可以使用一个线框构建。一个线框也能被添加。在下面这个例子中,线框所有的边都被添加。下面是组合两个线框的例子:

#include <TopoDS_Wire.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
TopoDS_Wire MergeWires (const TopoDS_Wire& W1,
const TopoDS_Wire& W2)
{
BRepBuilderAPI_MakeWire MW(W1);
MW.Add(W2);
return MW;
}

BRepBuilderAPI_MakeWire 类将边连接到线框。当一个新的边被添加,如果它的顶点之一被线框共享,那么它就被认为是连接到线框。如果这里没有共享的顶点,算法寻找边上的一个顶点和线框的一个顶点,它们位于相同的位置(顶点的容差被用于测试是否它们有相同的位置)。如果这样一对顶点被找到,边被复制,其顶点被替换为线框中的顶点。边的所有顶点都可以交换为线框中的顶点。如果没有连接被找到,线框被认为是不连接的。这是一个错误。

BRepBuilderAPI_MakeWire 类可以返回最后被添加到线框中(Edge方法)。这条边可能与原始边,如果被拷贝的话。

Error 方向返回 BRepBuilderAPI_WireError 枚举中的一项:

  • WireDone —— 没有错误产生
  • EmptyWire —— 没有初始化算法;一个空构造器被使用
  • DisconnectedWire —— 最后被添加的边没有连接到线框
  • NonManifoldWire —— 想看有奇异点

壳(Shell)

壳是一个复合形状,其构建不仅基于几何,也基于面的集合。使用 BRepBuilderAPI_MakeShell 类去基于面集构建一个Shell。每个面拥有连续性是必要的。这就是为什么一个起始曲面被分解为多个面。


刚体(Solid)

刚体是一个复合形状,其构建不仅基于几何,也基于壳的集合。使用 BRepBuilderAPI_MakeSolid 类去基于壳的集合构建一个刚体。这个类的使用与 MakeWire 类的使用相似:壳以MakeWire中边添加的线框中的类似方式添加到刚体中。


http://www.niftyadmin.cn/n/147448.html

相关文章

STM32的小打小闹(标准库)

STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器。这里以STM32C8T6为例子。通过标准库入门STM32的GPIO输入输出、EXTI外部中断、TIM定时器中断、TIM输出比较、TIM输入捕获、ADC数模转换、DMA、USART收发数据、I2C通讯、SPI通讯。根据b站江科大b站江科大视以及相关资料总结…

Linux timeout 命令

Linux 里有个命令叫 timeout&#xff0c;它可以控制一个进程的最大执行时间&#xff0c;超时就会被 这个命令主动终结。 源码&#xff1a;https://github.com/coreutils/coreutils/blob/master/src/timeout.c 用法&#xff1a;timeout 30 ./a.out a.out 程序最长可以执行 30s…

win11如何录屏幕视频和声音?教你三招录屏方法

大部分人在使用的电脑的时候&#xff0c;因为不常用到录屏功能所以根本就不知道原来Windows电脑中是有自带的录屏工具的&#xff01;今天小编就给大家介绍下Windows自带录屏工具&#xff0c;win11如何录屏幕视频和声音&#xff1f;一起来看一下吧&#xff01; 一、Windows自带录…

JUC并发编程共享模型之管程(三)(下)

4.8 wait notify 根据前面很清楚了&#xff0c;关于为什么需要wait 因为如果一个线程被调用&#xff0c;但是不符合运行条件&#xff0c;需要让他将锁释放&#xff0c;继续去等待&#xff0c;等待他的运行条件满足在不满足运行条件的情况下&#xff0c;我们不能给他重新放回E…

设置Android Spinner下拉框三角标位置靠右居中

文章目录小结问题及解决参考小结 Android Spinner下拉框一般会有一个向下的三角标&#xff0c;本文记录了如何将这个三角标设置位置靠最右&#xff0c;并居中&#xff0c;使用固定高度。 问题及解决 这里想要达到的效果是在Android Spinner下拉框设置一个外边缘框&#xff0…

linux驱动概念学习笔记

文章目录1, 什么是用户空间和内核空间?2, 为什么要区分用户空间和内核空间?3, 如何从用户空间进入内核空间?4, 设备号的具体意义是什么?5, printk对打印消息的分类有哪些?6, 如何修改printk的打印等级?7,linux内核编程中怎么创建线程?8,linux驱动开发中i2c的开发流程.9,…

网络编程UDP TCP

定义:关注底层数据的传输 区分网页编程:关注上层应用 端口号:区分软件 2个字节 0~65535表示端口号 同一协议下端口号不能冲突 8000以下称为预留端口号,建议之间设置端口号为8000以上 常见的端口号: 80:http 8080:tomcat 3306:mysql 1521:oracle InetSocketAddress:此类实现IP套…

一文吃透什么是低代码开发?

一、简单介绍低代码 低代码是一种可视化软件开发方法&#xff0c;通过最少的编码更快地交付应用程序。图形用户界面和拖放功能使开发过程的各个方面自动化&#xff0c;消除了对传统计算机编程方法的依赖。 低代码平台使应用程序开发更加自主化&#xff0c;特别是对于没有编码经…