CGPath复制lineJoin和miterLimit没有明显影响

2024-02-18

我正在使用偏移 CGPath复制(strokingWithWidth:lineCap:lineJoin:miterLimit:transform‌​:) https://developer.apple.com/reference/coregraphics/cgpath/2427133-copy。问题是偏移路径引入了各种锯齿线,这些锯齿线似乎是斜接连接的结果。改变miterLimit为 0 没有任何效果,并且使用斜角线连接也没有什么区别。

在此图像中,有原始路径(在应用之前strokingWithWidth)、使用斜角连接的偏移路径和使用斜角连接的偏移路径。为什么使用斜角连接没有任何影响?

使用斜接的代码(请注意,使用CGLineJoin.round产生相同的结果):

let pathOffset = path.copy(strokingWithWidth: 4.0, 
                           lineCap: CGLineCap.butt,
                           lineJoin: CGLineJoin.miter,
                           miterLimit: 20.0)

context.saveGState()

context.setStrokeColor(UIColor.red.cgColor)
context.addPath(pathOffset)
context.strokePath()

context.restoreGState()

使用斜角的代码:

let pathOffset = path.copy(strokingWithWidth: 4.0, 
                           lineCap: CGLineCap.butt,
                           lineJoin: CGLineJoin.bevel,
                           miterLimit: 0.0)

context.saveGState()

context.setStrokeColor(UIColor.red.cgColor)
context.addPath(pathOffset)
context.strokePath()

context.restoreGState()

这是一条由两条线段组成的路径:

如果我用线宽为 30 的斜角连接来描画它,效果如下:

如果我使用相同的参数制作路径的描边副本,则描边副本将如下所示:

注意到那里的三角形了吗?出现这种情况是因为 Core Graphics 以简单的方式创建描边副本:它沿着原始路径的每个段进行追踪,创建偏移 15 个点的复制段。它用直线连接每个复制的段(因为我指定了斜角连接)。在慢动作中,复制操作如下所示:

因此,在接头的内侧,我们得到一个三角形,在外侧,我们得到平坦的斜角。

当 Core Graphics 描画原始路径时,该三角形是无害的,因为 Core Graphics 使用非零缠绕规则 https://en.wikipedia.org/wiki/Nonzero-rule来填充描边。但是,当您抚摸描边副本时,三角形就会变得可见。

现在,如果我缩小制作描边副本时使用的线宽,三角形就会变小。然后,如果我增加用于绘制描边副本的线宽,并使用斜接连接绘制描边副本,则三角形实际上最终看起来像是被填充的:

现在,假设我用一条很短的线连接的两个关节替换原始路径中的单个关节,在底部创建一个(非常小的)平点:

当我制作这条路径的描边副本时,该副本具有two内部三角形,如果我抚摸抚摸过的副本,它看起来像这样:

这就是当你制作路径的描边副本时那些奇怪的星形形状的来源:非常短的线段创建重叠的三角形。

请注意,我制作的副本是bevel加入。在制作副本时使用斜接连接也会创建隐藏的三角形,因为连接的选择只会影响outside关节处,而不是关节内部。

然而选择加盟does抚摸抚摸副本时很重要,因为使用斜接会使星星变大。看这个文件 https://www.w3.org/TR/svg-strokes/#LineJoin很好地说明了连接样式对锐角外观的影响程度。

因此,斜接使三角形的点伸出很远,这使得重叠的三角形看起来像星星。如果我使用斜角连接来描画描边副本,则结果如下:

星星在这里几乎看不见,因为三角形是用钝角绘制的。

如果内部三角形对您来说不可接受,您将必须编写自己的函数(或在互联网上找到一个函数)来制作没有三角形的路径的描边副本,或者从副本中消除三角形。

如果您的路径完全由平坦线段组成,最简单的解决方案可能是使用现有的多边形裁剪库。应用于描边副本的“联合”操作应该消除内部三角形。例如,请参阅此答案。 https://stackoverflow.com/a/23621812/77567请注意,这些库往往是用 C++ 编写的,因此您可能必须编写一些 Objective-C++ 代码,因为 Swift 无法直接调用 C++ 代码。

如果您想知道我是如何生成这个答案的图形的,我是使用这个斯威夫特游乐场 https://gist.github.com/mayoff/0a50fb7e7bf1ae2469b8cc83df4fcc60.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CGPath复制lineJoin和miterLimit没有明显影响 的相关文章

随机推荐