转载请注明原文链接:https://blog.youkuaiyun.com/Mechanicoder/article/details/129227386
1. 简介
BRepOffsetAPI_MakeOffset 算法仅对平面线(TopoDS_Wire)有效。
OCC官方在2022年11月3日发布 7.7.0 正式版,其中一个更新为:偏置算法提供新的、采用近似的算法,将含样条曲线的轮廓转换为仅含线段和圆弧的轮廓,以提高算法稳定性。可概括为样条简化。
New option in BRepOffsetAPI_MakeOffset - approximation of input contours by
ones consisting of 2D circular arcs and 2D linear segments only, it provides
more stable work of 2D offset algorithm.
虽然是局部算法优化,但若明显提高算法稳定性,还是喜人的。在以往对该算法的使用中,确实发现对样条曲线偏置能力较弱,未能正确处理偏置线自相交的问题,如下图所示,上方和左下角存在两处明显的自相交:

图1. 自相交问题
本文将对OCC此处算法升级一探究竟。
2. 源码分析
2.1. 算法改进内容
对比 OCC7.6 和 OCC7.7 源码文件,主要有两处修改,第一处是新增的一个选项接口——设置一个标志位,允许将输入轮廓转化为仅有线段和圆弧构成的轮廓(简单轮廓),如下:
//! Set approximation flag
//! for convertion input contours into ones consisting of
//! 2D circular arcs and 2D linear segments only.
Standard_EXPORT void SetApprox (const Standard_Boolean ToApprox);
第二处是新增一个静态方法,将面的原始轮廓转化为仅有线段和圆弧构成的轮廓(简单轮廓),允许指定转角误差,转换后得到一个新的面,如下:
//! Converts each wire of the face into contour consisting only of
//! arcs and segments. New 3D curves are built too.
Standard_EXPORT static TopoDS_Face ConvertFace (const TopoDS_Face& theFace,
const Standard_Real theAngleTolerance);
对比仅有的这两处修改,显然选项接口 SetApprox 仅起到开关作用,无法设置转角误差,疑似接口设计上的一个小缺陷。进一步查看源代码,发现转角误差被硬编码在算法中为0.1,如下第11行:
void BRepOffsetAPI_MakeOffset::Perform(const Standard_Real Offset,
const Standard_Real Alt)
{
StdFail_NotDone_Raise_if ( !myIsInitialized,
"BRepOffsetAPI_MakeOffset : Perform without Init");
try
{
if (myIsToApprox)
{
Standard_Real aTol = 0.1;
if (myFace.IsNull())
{
TopoDS_Face aFace;
Standard_Boolean OnlyPlane = Standard_True;
TopTools_ListIteratorOfListOfShape anItl (myWires);
2.2. 算法关键流程
关于此次优化内容,梳理算法关键流程如下:

线偏置算法关键流程
算法整体采用离散近似求解的思想,将样条等曲线离散为线段和圆弧。这一关键的离散过程由算法BRepAlgo::ConvertWire 完成:即将线(TopoDS_Wire)按指定转角误差转换为由线段和圆弧构成的新的线。当然,如果线已经仅有线段和圆弧构成,则不发生任何实质性计算。注意该算法不是OCC 7.7.0 升级新增算法。
3. 算法测试
测试模型包括简单多边形、由线段和圆弧构成的简单轮廓以及由样条曲线构成的样条轮廓,如下图所示。(模型由CrownCAD在线设计,并导出为STEP文件,原始模型链接):

测试偏置模型
3.1. 简单多边形

简单多边形

简单多边形

简单多边形
以上简单多边形测试,在OCC7.6、OCC7.7两个本本均可得到正确无误的结果。
3.2. 简单轮廓

简单轮廓
含圆弧的简单轮廓,同样可在两个版本上得到正确无误的结果。
对如下图所示的U型简单轮廓,存在一点异常。下图中圆弧半径9,向内偏置距离为-9时正确结果应该是退化的一条直线,而测例中仅得到一半直线。

简单轮廓——U型
该异常也可能是因线的显示精度不高导致,本文未作进一步深究。
3.3. 样条轮廓

样条轮廓——未开启样条简化
如上图测试,观察鼠标划过之处,向内偏置出现一处因自相交处理失败得异常结果;向外偏置时存在两处异常。
开启样条简化后,仅仅在小距离偏置时可得到与样条简化前相同的结果,随着距离增大,将无法得到任何结果(算法抛出异常,未完成),如下图所示。

样条轮廓——开启”样条简化“后偏置
测试结果:此次OCC7.7新增样条简化功能并未获得预期的结果。
4. 现存局限性
当前算法仅支持对单轮廓进行偏置,即无法很好处理含有孔的轮廓区域,如下图所示:

纯线段构成的内、外环轮廓
该测例中内、外环仅由线段构成,尚未能完美处理自相交问题,部分处理正确、部分处理错误,可见自相交处理算法的复杂程度。
再看其他处理存在缺陷的例子。

内外环简单轮廓偏置
经过以上验证,该算法的可靠性还需要进一步改进。另外,轮廓线偏置算法一般是基于中轴线算法,而OCC算法原理为何,还需深究。
欢迎使用该算法、对此感兴趣的同学可一起交流,本文源代码地址本文源代码。
参考资料
1. 官方博客: https://dev.opencascade.org/content/open-cascade-platform-components-are-updated-occt-770
2. 用户文档: https://dev.opencascade.org/doc/refman/html/class_b_rep_offset_a_p_i___make_offset.html
转载请注明原文链接:https://blog.youkuaiyun.com/Mechanicoder/article/details/129227386