Open CASCADE 高级曲面——N边曲面

问题来源

CAM(计算机辅助制造)路径规划

在CAM软件中规划加工路径时,在粗加工阶段一般追求加工路径尽可能平滑高效,减少不必要的刀路弯折、跳刀。而当零件上存在的孔、槽等凹陷特征时,可能出现在粗加工阶段不必要的局部细小刀路,影响加工效率。如下图所示:
在这里插入图片描述

在精加工阶段,当零件上有孔、槽特征时,同样会出现不必要的跳刀,而当刀路连续运行时,加工效率更高。如以下图所示,蓝色的切削刀路被孔洞截断,进而出现较多红色的跳刀:
在这里插入图片描述

针对该问题,一个解决方向是,向刀具路径规划算法提出极高的要求——在路径规划阶段即可自动跳过此类特征。但该要求往往过于苛刻,甚至成为一个难以完备解决的难题。而另一个方向则是将此类凹陷的洞特征“补平”——即应用CAD的补面技术构造补洞面片,补洞后,将得到如下刀路:
在这里插入图片描述

“补”一个由N个边界围成的区域(Filling n-sided regions)是CAD领域的一个经典问题,针对由两条边界(2-sided)、三条边界(3-sided)、四条边界(4-sided)以及由N条边界(N-sided)围成的区域填充问题,已有充分的技术研究相关研究,并且已在商业三维建模引擎实现,例如ACIS中的Cover。

N边域解决方法

对于单个拓扑面上的N边域这一简单场景,可以直接基于拓扑关系填充或删除N边域(Open CASCADE 获取面的内外环线)。

而复杂场景下的N边域填充主要有以下三种方法:

  1. 细分方法(Subdivision)
    通过递归细分初始多边形 P 0 P_0 P0,即由 P i − 1 P_{i-1} Pi1求解 P i P_i Pi,到近似生成光滑曲面。处理N边孔洞时,需解决非四边形面的填充问题。
  2. 多面片法(Multiple Patches)
    将N边域分割为三角形或四边形子区域,用标准曲面片填充,但需确保内部光滑性,其中解决子区域之间的连续性问题是一个挑战,如保持 C 1 , G 2 C^1, G^2 C1,G2连续。
  3. 单面片法(Single Patches)
    直接使用单一曲面片填充N边域,避免多面片的光顺性问题,但面临非矩形参数域和形状控制的挑战。这种方法一般也叫做N边曲面(N-Sided Surface)

如何进一步地定义N边曲面 N-Sided Surface?

N边曲面是一个由N条彼此相连的边界( E 0 , E 1 , E 2 , . . . , E n − 1 E_0, E_1, E_2, ..., E_{n-1} E0,E1,E2,...,En1)围成的、可通过指定点或边并满足连续性要求约束地单张曲面,指定的约束条件可以是:

  1. 约束:指定空间一个,使N边面通过该点。进一步地,当点位于某曲面上时,可以约束通过该曲面上的 G 0 G^0 G0)、与曲面上该相切( G 1 G^1 G1)、与曲面上该曲率半径相等( G 2 G^2 G2);
  2. 非边界约束:指定空间上的一条,使得N边曲面通过该边,并满足连续性要求;
  3. 边界约束:当属于相邻面的边界时,可以添加与相邻面的 G 0 / G 1 / G 2 G^0/G^1/G^2 G0/G1/G2连续性约束。

本文尝试通过Open CASCADE算法尝试构造N边曲面。

Open CASCADE 实现N边面

BRepFill_Filling 是 OCC 中实现N边曲面的接口,属于拓扑层面的算法,其底层核心求解算法由GeomPlate模块提供。GeomPlate模块提供用于构建板状(plate)曲面的高级曲面建模技术,除了可应用于N边曲面的生成之外,还可以用于过渡圆角曲面的构造。

这里不深入涉及GeomPlate底层数学原理,仅简要介绍一下BRepFill_Filling在应用层面的基本逻辑。

整体运行流程

BRepFill_Filling本质上是构造一个约束NURBS曲面,约束类型可分为点约束、边约束。
算法整体运行过程如下图所示:

建立拓扑
1. 边界约束
面上边
计算
2. 非边界约束
面上边
3. 点约束
面上点
4. 自由面
连接约束边界的缝隙
约束求解: 边界 + 非边界 + 点
薄板曲面逼近
拓扑曲面

关键算法

连接约束边界的缝隙

自由面的作用是辅助构造边界约束中不完整的边界,不是约束的一部分。当边界约束的边界不封闭时,将以自由面为基础,在边界缝隙处构造一段曲线来缝合边界。如下图所示,红色表示约束边界、绿色则是根据自由面构造的缝合曲线段:
缝合边界

约束求解: 边界 + 非边界 + 点

对边界/非边界约束、点/线约束进行前处理,构造为Plate_Plate约束数据,并进行求解。

约束求解
求解
不满足
满足
增加约束曲线采样点数
检查误差
将曲线离散点根据连续性要求
转换为可求解约束
离散约束曲线
Plate_Plate
将点约束根据连续性要求
转换为可求解约束
求解
根据所有约束
基于最大流量方法构造初始曲面/平面
将点、线约束投影至初始平面上
对约束线按弧长均匀采样
确定各约束线初始采样点数
在参数域内求约束线的交点
GeomPlate_Surface

其中,构造初始平面目的是为了接下来在平面上(或参数域内)处理点/线约束,初始曲面也可以由外部提供。算法构造的初始平面如下图灰色面所示:
在这里插入图片描述
从这里可以看推测,由于后续步骤包括约束边界向初始平面进行投影等操作,当投影所得多边形存在自相交时,算法将难以继续执行。即构造N边面时所选定的边界至少在某个投影方向上不存在自相交。

约束求解后得到的GeomPlate_Surface是一个参数化曲面,还需进一步逼近为NURBS曲面。

薄板曲面逼近

逼近算法AdvApp2Var_ApproxAFunc2Var以分段多项式逼近的方式,将约束求解所得薄板曲面GeomPlate_Surface转换为NURBS曲面Geom_BSplineSurface

GeomPlate_MakeApprox
Convert_GridPolynomialToPoles
AdvApp2Var_ApproxAFunc2Var
GeomPlate_Surface
Geom_BSplineSurface
(N边曲面结果)
多项式曲面网格
细分、逼近
数据结构
network(Result)
patchSequence
patch
patch[u0->u1, v0->v1]
patch...
uSequence
u0
u1
u...
vSequence
v0
v1
v...
framework(Constraints)
bag
node
u0v0
u0v1
u1v0
u1v2
u...v...
uStripe
viso0
viso1
viso...
vStripe
uiso0
uiso1
uiso...

拓扑构造

逼近时,求解区域会适当大于输入的约束边界。构造拓扑面时,基于输入边界线在N边面上构造新的边界。效果如下图所示:
在这里插入图片描述
这里所谓新的边界是相对于N边面而言的,即在输入Edge的基础上,新增构造了一条位于N边面上的边界曲线BRep_CurveOnSurface,串联所有的边界曲线即可确定N边曲面的外环。

应该注意,虽然在约束求解时,算法可自动缝补输入边界的缝隙。但在构造最终拓扑面时,并未恰当的处理缝隙的问题,当输入的约束边界不封闭,将得到拓扑异常的结果。因此,应仔细检查,确保输入边界是封闭的。

关于拓扑边界的概念可参考如下示意图(其中2D curve P2可视为新构造的边界),详细可参考OCC关方文档
在这里插入图片描述
由于N边面新构造边界来源于输入边界,二者存在天然的拓扑联系(具有相同的TopoDS_TShape),因此后续可以轻松将N边曲面与输入边界所在曲面进行缝合。

运行效果

边界约束

以若干条相连边作为N边曲面的边界、与边所在的曲面保持 G 0 / G 1 / G 2 G^0/G^1/G^2 G0/G1/G2连续性要求。如下图所示,相同的边界(图中红色线框)、选择不同的相邻面,设置连续性为 G 1 G^1 G1,得到不同的N边曲面:
在这里插入图片描述

点约束(空间任意)

以空间中任意一点作为点约束,使得N边曲面通过指定点。如下图所示,不同位置的点所得到的N边曲面:
在这里插入图片描述

点约束(曲面上的点)

以曲面上一点为约束,使得N边曲面与点所在曲面保持 G 0 / G 1 / G 2 G^0/G^1/G^2 G0/G1/G2连续,如下图所示,:
在这里插入图片描述
鼠标所指曲面上的点与N边曲面分别为 G 0 / G 1 / G 2 G^0/G^1/G^2 G0/G1/G2连续。

曲面变形

通过空间点约束,实现曲面通过点变形,如下图所示:
在这里插入图片描述

曲面桥接

在两个面之间构造光滑衔接的过渡曲面

示例代码

const std::vector<TopoDS_Shape>& bnd_edges = ...;
BRepFill_Filling fill;
// 边界约束
for (size_t i = 1; i < bnd_edges.size(); i += 2)
{
    TopoDS_Shape edge = bnd_edges[i - 1];
    TopoDS_Shape face = bnd_edges[i];
    if (TopAbs_EDGE == edge.ShapeType() && TopAbs_FACE == face.ShapeType())
    {
        // nothing to do
    }
    else if (TopAbs_EDGE == face.ShapeType() && TopAbs_FACE == edge.ShapeType())
    {
        std::swap(edge, face);
    }
    else
    {
        continue;
    }
    fill.Add(TopoDS::Edge(edge), TopoDS::Face(face), GeomAbs_G1);
}
// 非边界约束
const std::vector<TopoDS_Shape>& free_edges = ...;
for (const auto& fe : free_edges)
{
    if (TopAbs_EDGE != fe.ShapeType())
    {
        continue;
    }
    TopoDS_Edge e = TopoDS::Edge(fe);
    fill.Add(e, GeomAbs_G1, false);
}

// 面上点约束
const std::vector<TopoDS_Shape>& faces = ...;
for (const auto& fe : faces)
{
    if (TopAbs_FACE != fe.ShapeType())
    {
        continue;
    }
    TopoDS_Face f = TopoDS::Face(fe);
    Handle(Geom_Surface) surf = BRep_Tool::Surface(f);
    if (!surf)
    {
        continue;
    }
    const double u = ...;
    const double v = ...;
    GeomAbs_Shape con;
    switch (...)
    {
    case 0: con = GeomAbs_C0; break;
    case 1: con = GeomAbs_G1; break;
    case 2: con = GeomAbs_G2; break;
    default: con = GeomAbs_G1; break;
    }
    fill.Add(u, v, f, con);
    break;
}
// 自由点约束
gp_Pnt pnt = ...;
fill.Add(pnt);
fill.Build();
if (!fill.IsDone())
{
    // "N边面构造错误:Build 异常";
}
TopoDS_Face result_face = fill.Face();
...

原文链接:https://blog.youkuaiyun.com/Mechanicoder/article/details/145809854

参考资料

  1. UG/NX 曲面建模「N边曲面」命令简介
  2. Surface modeling. Part6
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值