Winding Rules 纏繞規(guī)則

在實現(xiàn)一個鏤空的效果時使套,發(fā)下路徑的方向病往,會影響最終實現(xiàn)的效果美尸,所以進一步研究了一下冤议。

填充路徑所包含的區(qū)域時,會通過纏繞規(guī)則來判斷需要填充的區(qū)域师坎。通過給定區(qū)域內(nèi)的任意一點到路徑外畫一條射線恕酸,根據(jù)與路徑的交叉數(shù)判斷點是否在區(qū)域內(nèi)。

纏繞規(guī)則:

  • NSNonZeroWindingRule:非零纏繞胯陋。射線從左到右每交叉路徑一次+1蕊温,從右到左每交叉一次-1袱箱。如果最終交叉數(shù)為0,則該點在路徑之外义矛;如果交叉數(shù)不為0发笔,則在路徑之內(nèi)。默認(rèn)纏繞規(guī)則凉翻。
  • NSEvenOddWindingRule:奇偶纏繞了讨。計算射線與路徑的交叉總數(shù),如果為偶數(shù)噪矛,則在路徑之外量蕊;如果為奇數(shù),則在路徑之內(nèi)艇挨,需要填充残炮。

填充操作適用于開放式路徑和閉合路徑。開放式路徑會從路徑的最后一個點到第一個點創(chuàng)建一個隱式的線(不渲染)缩滨,來閉合路徑势就。

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.
文檔中描述是從第一個點到最后一個點,但是根據(jù)分析與文檔上的圖以及實驗脉漏,圖與結(jié)果相同苞冯,但是描述錯誤,下面會詳細介紹侧巨。如果是我理解錯誤舅锄,懇請指出。

本文demo

閉合路徑

1. 非零纏繞:外邊框和內(nèi)邊框同一方向

    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];
winding_rules_1.png

內(nèi)部的點向外畫射線司忱,由于兩個貝塞爾曲線是同向皇忿,射線由右至左跨過路徑兩次,aRect 以內(nèi)的所有的點的射線交叉數(shù)只有兩種情況:0-1=-1坦仍,或者0-1-1=-2鳍烁。都不為0,所以內(nèi)部的點都在路徑之內(nèi)繁扎,需要渲染幔荒。

2. 非零纏繞:內(nèi)邊框與外邊框反向

// - (UIBezierPath *)bezierPathByReversingPath;  將路徑翻轉(zhuǎn)。
// 上面代碼只需要修改 bPath
UIBezierPath * bPath = [[UIBezierPath bezierPathWithRect:bRect] bezierPathByReversingPath];
winding_rules_2.png

分為兩種情況:

  • bPath 以內(nèi)的點的射線與路徑交叉只有一種:0+1-1=0梳玫,因此 bPath 內(nèi)部的點都在路徑最終路徑之外爹梁,bPath 以內(nèi)的點不需要渲染。
  • bPath 以外 aPath 以內(nèi)的點的射線與路徑交叉有兩種:0-1=-1提澎,或者0+1+1-1=1卫键。兩種情況都不為0,所以在路徑之內(nèi)虱朵,需要渲染莉炉。

奇偶纏繞規(guī)則

奇偶纏繞規(guī)則下钓账,與內(nèi)外路徑方向無影響。默認(rèn) fillRule 為非零絮宁,添加如下代碼梆暮。

shapeLayer.fillRule = kCAFillRuleEvenOdd;

只判斷射線與路徑的交叉,所以有兩種情況:

  • bRect內(nèi)部的點绍昂,射線與路徑的交叉有兩個啦粹,為偶數(shù),所以不在范圍內(nèi)窘游,不需要渲染唠椭。
  • bRect之外aRect以內(nèi),射線與路徑的交叉數(shù)可能為1或3忍饰,為奇數(shù)贪嫂,所以需要渲染。

開放式路徑

盜取蘋果文檔的圖來分析一下艾蓝,圖 c力崇、d 中的射線,按照從上到下從 左->右 命名為 p1,p2,p3赢织。

winding_rules_3.png

非零纏繞規(guī)則下 圖c:

  • p1 從 左->右 穿過隱式路徑亮靴,在從 左->右 穿過路徑,于置,0+1+1=2茧吊,在路徑之內(nèi),需要渲染八毯。
  • p2 先是從 左->右 穿過路徑搓侄,再從 右->左 穿過,0+1-1=0宪彩,不在路徑之內(nèi)休讳,不需要渲染讲婚。
  • p3 兩次從 左->右 穿過路徑尿孔,0+1+1=2,在路徑之內(nèi)筹麸,需要渲染活合。

這里分析一下隱式線的方向問題,修改一下 p2 的方向為垂直向上物赶。

  • 隱式線的方向是 start->end白指,首先從 右->左 穿過路徑,然后還是從 右->左 穿過隱式線酵紫,0-1-1=-2告嘲,不為0错维,應(yīng)該是屬于路徑之內(nèi),需要渲染的橄唬,與原結(jié)果沖突赋焕。
  • 隱式線的方向是 end->start,首先從 右->左 穿過路徑仰楚,然后從 左->右 穿過隱式線隆判,0-1+1=0,為0不在路徑內(nèi)僧界,不需要渲染侨嘀,與原結(jié)果相同。

奇偶纏繞規(guī)則下 圖d

  • p1 穿過隱式線和一次路徑捂襟,共兩次咬腕,偶數(shù),不在范圍內(nèi)笆豁,不會渲染郎汪。
  • p2和p3 穿過兩次路徑,共兩次闯狱,偶數(shù)煞赢,不在范圍內(nèi),不會渲染哄孤。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末照筑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子瘦陈,更是在濱河造成了極大的恐慌凝危,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晨逝,死亡現(xiàn)場離奇詭異蛾默,居然都是意外死亡,警方通過查閱死者的電腦和手機捉貌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門支鸡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人趁窃,你說我怎么就攤上這事牧挣。” “怎么了醒陆?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵瀑构,是天一觀的道長。 經(jīng)常有香客問我刨摩,道長寺晌,這世上最難降的妖魔是什么世吨? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮呻征,結(jié)果婚禮上另假,老公的妹妹穿的比我還像新娘。我一直安慰自己怕犁,他們只是感情好边篮,可當(dāng)我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著奏甫,像睡著了一般戈轿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上阵子,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天思杯,我揣著相機與錄音,去河邊找鬼挠进。 笑死色乾,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的领突。 我是一名探鬼主播暖璧,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼君旦!你這毒婦竟也來了澎办?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤金砍,失蹤者是張志新(化名)和其女友劉穎局蚀,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恕稠,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡琅绅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鹅巍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片千扶。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖昆著,靈堂內(nèi)的尸體忽然破棺而出县貌,到底是詐尸還是另有隱情术陶,我是刑警寧澤凑懂,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站梧宫,受9級特大地震影響接谨,放射性物質(zhì)發(fā)生泄漏摆碉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一脓豪、第九天 我趴在偏房一處隱蔽的房頂上張望巷帝。 院中可真熱鬧,春花似錦扫夜、人聲如沸楞泼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽堕阔。三九已至,卻和暖如春颗味,著一層夾襖步出監(jiān)牢的瞬間超陆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工浦马, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留时呀,地道東北人。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓晶默,卻偏偏與公主長得像谨娜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子磺陡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容