簡介
在繪圖中, 我們經(jīng)常需要對路徑進行填充操作. 那么問題來了, 在一個路徑的覆蓋范圍內(nèi), 如何判斷哪些區(qū)域需要被填充, 哪些區(qū)域不需要被填充呢? 其實很簡單, 在你的 畫布
中設置一個點
, 判斷這個點是否在路徑覆蓋范圍內(nèi), 如果在路徑覆蓋的范圍內(nèi), 那么點
所在的封閉區(qū)域就是需要填充的區(qū)域(內(nèi)部點
), 否則(外部點
)則不需要填充. 這時候有的小伙伴可能會說: 我去, 你這不廢話么?
. 別急, 我來解釋解釋我為什么會說這句廢話, 往下看.
我想大家應該都聽說過 不自交
和 自相交
這兩種多邊形. 定義如下:
- 不自交: 一個多邊形, 僅頂點處連接, 而在
畫布
內(nèi)沒有其他的公共交點. - 自相交: 一個多邊形, 除了頂點連接外, 在
畫布
內(nèi)還有其他的公共交點.
這下大家明白了吧? 如果是一個不自交
的多邊形, 那很容易判斷一個點是否在這個多邊形路徑的覆蓋范圍內(nèi), 那么我們也就很容易知道哪部分是填充區(qū)域. 但是如果判斷一個點, 是否在自相交
多邊形內(nèi), 則需要用到一下兩種原則來進行判斷, 這兩種原則, 也就是傳說中的FillMode
.
- Even-Odd Rule: 基偶原則
- Nonzero Winding Number Rule: 非零環(huán)繞數(shù)原則
這倆破玩意兒從字面上看, 有點難理解, 不過別著急, 我來帶大家一一進行講解.
FileMode
Even-Odd Rule
奇偶原則: 從路徑覆蓋范圍內(nèi)的任意一點做一條射線(確保這條射線的長度要比路徑覆蓋范圍要大) , 如果與該射線相交的邊的數(shù)量為奇數(shù), 則該點是路徑的內(nèi)部點, 反之該點則是路徑的外部點. 舉個例子, 來看一張圖:
這么簡單的東西, 我就不多說了, 接著看另外一個填充模式.
Nonzero Winding Number Rule
非零環(huán)繞數(shù)原則: 在我們腦海中定義一個變量, 比如叫:count
, 然后從路徑覆蓋范圍內(nèi)的任意一點做一條射線(確保這條射線的長度要比路徑覆蓋范圍要大). 然后我們對每一條和該射線相交的路徑進行統(tǒng)計, 統(tǒng)計規(guī)則是這樣的: 當路徑是從右向左穿過射線的時候, count++
, 當路徑是從左向右穿過射線的時候, count--
. 當我們統(tǒng)計完所有相交的路徑后, 如果 count
不為0, 則該點是內(nèi)部點, 該點所在的封閉區(qū)域需要填充, 反之該點則是路徑的外部點. 舉個例子, 來看一張圖:
從圖中看的很清晰, 從左圖中的紅點開始, 繪制了一條射線, 圖中經(jīng)過了兩條路徑, 這兩條路徑的方向都是從左向右穿過射線的, 每經(jīng)過一條從左向右穿過射線的路徑, count
會減一, 那么最終count
為 -2
, 通過非零環(huán)繞數(shù)原則判定, 該點為內(nèi)部點
, 所以該點所在的區(qū)域進行了填充. 右圖射線同樣經(jīng)過了兩條路徑, 但是這兩條路徑的方向一個是從左向右穿過射線的, 另一個是從右向左穿過射線的,那么最終count
為0
, 通過非零環(huán)繞數(shù)原則判定, 該點為外部點
, 所以該點所在的區(qū)域不進行填充操作.
再來看一個例子, 如下圖:
從圖中看出, 藍色的射線經(jīng)過的三條路徑, 最終的結果count
為 1
, 所以藍色點所在的封閉區(qū)域是需要填充的.
OK, 就介紹這么多吧. 圖片都是自己一點一點畫的, 有點丑, 將就看哈!
Lemon龍說:
如果您在文章中看到了錯誤 或 誤導大家的地方, 請您幫我指出, 我會盡快更改
如果您有什么疑問或者不懂的地方, 請留言給我, 我會盡快回復您
如果您覺得本文對您有所幫助, 您的喜歡是對我最大的鼓勵
如果您有好的文章, 可以投稿給我, 讓更多的 iOS Developer 在簡書這個平臺能夠更快速的成長