Clipper库 基础类型和填充规则

裁剪类型(ClipType)

1
2
3
4
CT_INTERSECTION = 0
CT_UNION = 1
CT_DIFFERENCE = 2
CT_XOR = 3
  • 交集,AND (intersection) :主体和裁剪多边形相交的区域。
  • 并集,OR (union) - 主体和裁剪多边形两者合并的区域。
  • 非/差,NOT (difference) - 裁剪多边形以外主体的区域。
  • 异或,XOR (exclusive or) - 主体和裁剪多边形两者相交以外的区域。

image-20221218092444226

image-20221218093353310

ClipType 的用法:

在使用 Clipper 对象对多边形进行裁剪时,可以通过在执行方法 Execute 中传入 ClipType 参数指定裁剪(布尔运算)类型。

Clipper.Execute 方法描述如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def Execute(self, *args, **kwargs):
"""
Performs the clipping operation and returns a list of paths.

Keyword arguments:
clip_type -- type of the clipping operation
subj_fill_type -- fill rule of subject paths
clip_fill_type -- fill rule of clip paths

Returns:
list of resulting paths

Raises:
ClipperException -- operation did not succeed
"""
pass

闭合类型(EndType)

1
2
3
4
5
ET_CLOSEDPOLYGON = 0
ET_CLOSEDLINE = 1
ET_OPENBUTT = 2
ET_OPENSQUARE = 3
ET_OPENROUND = 4
  • etClosedPolygon: 末端根据JoinType的值连接,填充路径使用多边形。
  • etClosedLine: 末端根据JoinType的值连接,填充路径使用多线段。
  • etOpenButt: 末端为直角,且没有延伸。
  • etOpenSquare: 末端为直角,并且向路径外延伸一部分。
  • etOpenRound: 末端为圆角,并且向路径外延伸一部分。
  • etOpenSingle: 在一个方向上偏移一个开放路径,计划在未来更新。(我在Python下用的6.2.1版本还没有。)

image-20221218094605442

EndType 参数只在 ClipperOffset.AddPathClipperOffset.AddPaths 中用到,用于规定偏置轮廓的闭合方式。

连接类型(JoinType)

1
2
3
JT_MITER = 2
JT_ROUND = 1
JT_SQUARE = 0

image-20221218095018604

  • jtMiter:斜角衔接。对一些窄角度,向外偏置可能会产生非常长的“尖峰”。

    image-20221218095529324

    因此我们需要设置 ClippOffset.MiterLimit 属性用来指定原始顶点将被偏移的最大距离(以 delta 的倍数),即在距离原始顶点 delta 倍数的距离上,将斜边截断成倒方角(这样就变成和 jtSquare 一样的连接效果了)。

  • jtRound: 圆弧衔接。将所有斜边角进行到圆角处理。我们知道圆角其实是由倒角近似形成的,所以Clipper库引入ClipperOffset.ArcTolerance 属性(圆弧精度)指定了近似处理弧线时可接受的最大不精确性(“公差”)。

    image-20221218100844645

    ArcTolerance 默认值为0.25,说明qd(倒角偏离真实圆弧的最大距离)不超过0.25。我们可以发现,qd越小,整个近似圆弧越光滑,代价就是我们需要插入更多的顶点。

  • jtSquare: 矩形衔接。将所有斜边角进行倒角 C1×delta

感觉和数控技术中刀具偏置路径连接差不多。

其中提到的 delta 是在 ClipperOffset.Execute 方法中传入的参数。

1
2
3
4
5
6
7
8
9
10
11
12
def Execute(self, *args, **kwargs): # real signature unknown
"""
Performs the offset operation and returns a list of offset paths.

Keyword arguments:
delta -- amount to which the supplied paths will be offset - negative delta shrinks polygons,
positive delta expands them.

Returns:
list of offset paths
"""
pass

裁剪填充类型(PolyFillType) - 填充规则

1
2
3
4
PFT_EVENODD = 0
PFT_NEGATIVE = 3
PFT_NONZERO = 1
PFT_POSITIVE = 2

填充规则(fill rule)用于判断在封闭图形中,哪些区域是内部,哪些区域是外部(如’孔‘)。Clipper库支持4个填充规则:

  • Even-Odd(奇偶)
  • Non-Zero(非零)
  • Positive(正)
  • Negative(负)

我认为下面这张图比官方描述更加易于理解。我们赋予每个多边形子区域一个绕数。根据多边形的方向和一条外部到内部的射线来计算区域的绕数。

image-20221218103400376

图源自:《计算机辅助制造实践——Python实现三维打印路径规划》P163。

填充规则描述如下:

  • 奇偶填充 : 奇数子区域填充,偶数子区域不填充。

    奇偶填充最简单,不需要借助绕数。奇偶填充规定:和射线相交的第奇数个轮廓内部区域是填充区域,第偶数个轮廓内部区域是非填充区域。适用于多边形本身和多边形之间不存在自相交的情况。

  • 非零填充:所有绕数非零的区域都填充。

  • 正填充:所有绕数 >0的区域都填充。

  • 负填充:所有绕数 < 0的区域都填充。

目前使用最广泛的填充规则是奇偶和非零填充。

PolyFillType 的用法:

在使用 Clipper 对象对多边形进行裁剪时,可以通过在执行方法 Execute 中传入 PolyFillType 指定 subj_fill_type (主体多边形的填充规则)和 clip_fill_type (裁剪多边形的填充规则)参数。

裁剪属性(PolyType)

1
2
PT_CLIP = 1
PT_SUBJECT = 0

裁剪属性有2个:

  • 主体多边形(ptSubject ):被裁剪多边形,也就是主体多边形。
  • 裁剪多边形(ptClip ):裁剪多边形,使用此多边形裁剪主体多边形。

PolyType 的用法:

在使用 Clipper 对象对多边形进行裁剪时,可以通过在执行方法 AddPaths 中传入 PolyType 指定传入的多边形(paths)的裁剪属性 poly_type(即是裁剪对象还是被裁剪对象)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def AddPaths(self, *args, **kwargs): # real signature unknown
"""
Add a list of paths.

Keyword arguments:
paths -- paths to be added
poly_type -- type of added paths - subject or clip
closed -- True if added paths are closed, False if open

Returns:
True -- all or some paths are valid for clipping and were added

Raises:
ClipperException -- all paths are invalid for clipping
"""
pass