多边形的OFFSET算法概述

来源:互联网 发布:如何锻炼pc肌肉知乎 编辑:程序博客网 时间:2024/06/13 15:13

多边形的OFFSET,是几何计算中的基本而又复杂的问题。本文将基于作者多年的编程实践,对此做个概述。

本文考虑的多边形是简单闭合的(不含自交),但可以有洞,即对应一个有效的连通区域,约定其边界走向符合右手法则。

该区域的外边界简称为外圈,洞的边界为内圈,外圈和内圈的走向相反。不必区分内外的情形下,简称为圈。


一. 基本想法
    先考虑单个圈的OFFSET;
    得到内圈和各个外圈的OFFSET之后,再进行BOOL运算获得最终的OFFSET结果。

    值得注意的OFFSET的两个基本事实:
1.单圈向内OFFSET
    可能产生多个相隔离的单连通子区域,但不会产生洞;
    OFFSET距离太大时,区域会消失!
2.单圈向外OFFSET
    可能产生洞,OFFSET结果为一个多连通区域;但区域不可能消失!


二. OFFSET涉及到的算法
1.多边形求交算法
      圈的OFFSET过程中的后处理以及BOOL运算,都依赖于求交算法。
      文献中sweep line被认为是多边形求交的有效算法,但编码复杂。作者发现,简单的两两线段求交算法具有更好的时间性能表现,这印证了简单的代码具有更好的执行效率(注:也可能是作者测试的多边形点数不够大)。

2.多边形的BOOL运算
      推荐采用BOOST POLYGON库提供的BOOL算法,稳定高效。


三. 圈的OFFSET算法
1.得到初始OFFSET(简记为OFFSET0):
1).光滑分段;
2).各光滑段的OFFSET;
3).前后两段OFFSET的连接---考虑保角优先还是圆弧过渡
        圆弧过渡是简单而统一的方法,但会引入很多短的多边形线段;另一方面,保角的要求也是很自然的,比如很情况下希望矩形的OFFSET仍为矩形,即OFFSET至少应该保直角。
        综合这两方面的考虑,OFFSET应该再引入一个保角参数。如果OFFSET距离为fdis,则保角参数表示OFFSET角点处允许的最大OFFSET距离fdismax。在保直角的情形下,fdismax= |fdis|*sqrt(2)。
        这一步得到的OFFSET0应该是闭合的。

2.计算OFFSET0的自交分割,得到OFFSET  
      如果OFFSET0没有自交,则不必进行分割处理,OFFSET0本身作为一段;
      有自交的情况,按自交点在OFFSET0轮廓上的参数进行排序,这样OFFSET0被分割成很多段。
      要逐段进行OFFSET合法性测试(考虑和原始圈的内外关系,和原始圈的最近距离),保留合法的段。再把这些合法段连接成为若干个闭合的圈,并进行合理的定向重组(参考上述OFFSET的两个基本事实)。

注: 关于OFFSET合法性测试,下面的一篇论文值得参考
      A pair-wise offset algorithm for 2D point-sequence curve. CAD-31(1999)。


四. BOOST POLYGON库提供的BOOL运算和OFFSET算法

      参见:http://www.boost.org/doc/libs/1_46_1/libs/polygon/doc/index.htm
      BOOST POLYGON库的调用和CGAL相比,算是很方便的了。该库进行了充分的测试,稳定性好值得推荐使用。
      其BOOL运算非常稳定(内部是基于sweep line求交算法),时间性能也够好。
      其OFFSET算法支持圆弧过渡和保角两种方案,但不支持上述保角参数。本人发现圆弧过渡的执行效率远比保角差,而且在VC++中采用圆弧过渡的情形下,Release版编译的代码执行效率还行,但在debug编译下的代码非常非常慢。

五. 多边形的 Minkowski-Sum

      多边形OFFSET的精确定义基于多边形和圆盘的Minkowski-Sum,BOOST 和 CGAL都是这么做的。这方面的最新进展,参见下面的论文:

      http://masc.cs.gmu.edu/wiki/ReducedConvolution

 

原创粉丝点击