iOS开发之常用技术点QiShare文章汇总iOS 杂货铺

iOS Winding Rules 缠绕规则

2019-01-03  本文已影响58人  QiShare

级别: ★★☆☆☆
标签:「iOS」「layer」「贝塞尔」
作者: 忆思梦
审校: QiShare团队

前言:之前在QiQRCode中:在实现一个镂空的效果时,发现路径的方向会影响最终实现的效果,所以进一步研究了一下。

填充路径所包含的区域时,会通过缠绕规则来判断需要填充的区域。通过给定区域内的任意一点到路径外画一条射线,根据与路径的交叉数判断点是否在区域内。

缠绕规则:

填充操作适用于开放式路径和闭合路径。开放式路径会从路径的最后一个点到第一个点创建一个隐式的线(不渲染),来闭合路径。

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CocoaDrawingGuide/Paths/Paths.html#//apple_ref/doc/uid/TP40003290-CH206-BAJIJJGD 中的 Winding Rules中:
When you fill a partial subpath, NSBezierPath closes it for you automatically by creating an implicit (non-rendered) line from the first to the last point of the subpath.
文档中描述是从第一个点到最后一个点,但是根据分析与文档上的图以及实验,图与结果相同,但是描述错误,下面会详细介绍。如果是我理解错误,恳请指出。

本文demo

闭合路径

1. 非零缠绕:外边框和内边框同一方向

CGRect aRect = CGRectMake(100, 100, 200, 200);
UIBezierPath * aPath = [UIBezierPath bezierPathWithRect:aRect];
CGRect bRect = CGRectInset(aRect, 50, 50);
UIBezierPath * bPath = [UIBezierPath bezierPathWithRect:bRect];
    
[aPath appendPath:bPath];
    
CAShapeLayer * shapeLayer = [CAShapeLayer layer];
shapeLayer.path = aPath.CGPath;
shapeLayer.fillColor = [UIColor yellowColor].CGColor;
    
[self.view.layer addSublayer:shapeLayer];

内部的点向外画射线,由于两个贝塞尔曲线是同向,射线由右至左跨过路径两次,aRect 以内的所有的点的射线交叉数只有两种情况:0-1=-1,或者0-1-1=-2。都不为0,所以内部的点都在路径之内,需要渲染。

2. 非零缠绕:内边框与外边框反向

// - (UIBezierPath *)bezierPathByReversingPath;  将路径翻转。
// 上面代码只需要修改 bPath
UIBezierPath * bPath = [[UIBezierPath bezierPathWithRect:bRect] bezierPathByReversingPath];

分为两种情况:

奇偶缠绕规则

奇偶缠绕规则下,与内外路径方向无影响。默认 fillRule 为非零,添加如下代码。

shapeLayer.fillRule = kCAFillRuleEvenOdd;

只判断射线与路径的交叉,所以有两种情况:


开放式路径

盗取苹果文档的图来分析一下,图 c、d 中的射线,按照从上到下从 左->右 命名为 p1,p2,p3。

非零缠绕规则下 图c:

这里分析一下隐式线的方向问题,修改一下 p2 的方向为垂直向上。

  • 隐式线的方向是 start->end,首先从 右->左 穿过路径,然后还是从 右->左 穿过隐式线,0-1-1=-2,不为0,应该是属于路径之内,需要渲染的,与原结果冲突。
  • 隐式线的方向是 end->start,首先从 右->左 穿过路径,然后从 左->右 穿过隐式线,0-1+1=0,为0不在路径内,不需要渲染,与原结果相同。

奇偶缠绕规则下 图d:


小编微信:可加并拉入《QiShare技术交流群》。

关注我们的途径有:
QiShare(简书)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公众号)

推荐文章:
iOS 签名机制
iOS 扫描二维码/条形码
iOS 了解Xcode Bitcode
iOS 重绘之drawRect
奇舞周刊

上一篇下一篇

猜你喜欢

热点阅读