個人筆記|GIS的ear clipping算法

對論文Triangulation by Ear Clipping 的理解
不涉及帶孔洞的多邊形及多邊形迭代
問就是功能不需要

聲明:在本學習筆記的寫作過程中,沒有一只貓貓受到實際傷害。
(包括賽博貓貓在內)

引入

計算機圖形學的多邊形分解問題

簡單多邊形定義

定義一個簡單多邊形為由從V_0V_{n-1}n個點組成的有序序列。兩相鄰頂點之間以邊<V_i,V_{i+1}>,0\leq i\leq n-2相連,且起點和終點之間以邊<V_{n-1},V_0>相連。簡單多邊形的每個頂點有且僅有兩條邊,簡單多邊形的任意兩條邊僅在頂點處相交。簡單多邊形和復雜多邊形的對比如圖所示

簡單與復雜多邊形對比

左側多邊形為簡單多邊形。中間的多邊形的頂點1有兩條以上邊,不為簡單多邊形。右側多邊形中連接頂點1和頂點4的邊與其他邊在非頂點處相交,該多邊形不為簡單多邊形。

在一個簡單多邊形中,當遍歷邊緣時,多邊形內部的有限區域總處于遍歷方向同一側。假設以逆時針方向遍歷例圖中的簡單多邊形邊緣,則多邊形內部區域始終處于遍歷方向左側。

多邊形三角化算法

將簡單多邊形分解為多個三角形的過程叫做多邊形三角化。對具有n個頂點的任意多邊形進行三角化分解都會得到n-2個三角形。在諸多算法中復雜度為O(n^2)的ear clipping算法算是最簡單又好用的一個,其他復雜度更低的算法也存在,不過會比ear clipping更難實現。

Ear Clipping算法

下文用貓耳朵指代ear 用咔耳朵算法指代ear clipping)

我覺得論文作者也會贊同的 除了貓奴還有誰會看到三角形就想到尖尖耳朵呢)

定義

貓貓耳朵

多邊形的一只貓貓耳朵是由三個相鄰頂點V_{i_0},V_{i_1},V_{i_2}構成的三角形,其中V_{i_1} 是三角形凸出的頂點,在該頂點處三角形的內角角度小于\pi。作一條連接點V_{i_0},V_{i_2}的輔助線,該線段完全位于多邊形內部。這只貓貓耳朵只含有構成耳朵的三個頂點,不包含多邊形的其他頂點。在計算機幾何學術語里把連接點V_{i_0},V_{i_2}的輔助線叫做多邊形的一條對角線,把頂點V_{i_1}叫做耳朵尖(貓貓的耳朵根根和耳朵尖尖,懂得都懂)。一個三角形就是一只貓貓耳朵,三角形的任意一個頂點都可以是耳朵尖尖。

有四條邊及以上的多邊形擁有至少兩只不重疊的耳朵,這就提供給我們一個遞歸實現多邊形三角化的思路。若在含有n\geq 4個頂點的多邊形內確定并移除一個三角形,移除后的多邊形具有n-1個頂點。重復該過程,即是復雜度為O(n^3)的三角化算法。

咔耳朵算法

好消息:咔耳朵算法的復雜度可以降到O(n^2)

壞消息:難的步驟要來了

step1

首先,將多邊形以雙鏈表形式存儲,以便快速咔掉耳朵尖尖。這個步驟的復雜度是O(n)

step2

其次,對頂點進行迭代,分出各個不重疊的貓貓耳朵。對于每個頂點V_i和該頂點對應的三角形<V_{i-1}, V_i, V_{i+1}>,測試多邊形的其他頂點是否位于該三角形中。該索引對n取模,所以V_n = V_0V_{-1} = V_{n-1}。如果三角形內不包含多邊形的其他頂點 ,我們就喜提了一只貓貓耳朵!如果三角形內至少含有多邊形的一個頂點,它就不是貓貓耳朵。在三角形包容測試中效率更高的三角化方法是只考慮反射點。反射點指由兩條邊構成的角度大于\pi的內部角的頂點。多邊形的數據結構包含四個同時共用一個存儲數組的雙鏈表,而非動態分配和釋放內存的標準列表數據結構。使用循環鏈表存儲多邊形的所有頂點,線性表存儲凸頂點,另一個線性表存儲反射點,另一個循環鏈表存儲耳朵尖尖。

step3

當完成對存儲反射點和耳朵尖尖的數據列表初始化后,就可以一只接一只地咔掉貓貓耳朵了!若V_i是已經被咔掉的貓貓耳朵,那么與其相鄰的頂點V_{i-1}和頂點V_{i+1}的邊的參數隨之變化。若一相鄰頂點是凸出點,則其仍是凸出點。若一相鄰頂點是耳朵,在移除V_i后它可能就不再是耳朵了。若為反射點,則可能變為凸出點或耳朵。在移除V_i后,若存在一凸出的相鄰頂點,則必須通過遍歷反射點和測試三角形內是否包含點來驗證該相鄰頂點是否為耳朵。整個過程的復雜度是O(n^2)

算法示例

以第一張圖的簡單多邊形為例

初始的簡單多邊形

凸出頂點的初始列表為C = \{0,1,3,4,6,9\}

反射頂點的初始列表為R = \{2,5,7,8\}

耳朵尖尖的初始列表為E = \{3,4,6,9\}(再復習一遍,耳朵尖尖=這個點是凸出點+和這個點相鄰的兩個點的連線完全在多邊形內部)

凸出點 C = \{0,1,3,4,6,9\}
反射點 R = \{2,5,7,8\}
耳朵尖尖 E = \{3,4,6,9\}
三角形 暫無

① 把耳朵尖尖3對應的貓貓耳朵咔掉,那么三角化咔出來的第一個三角形就是T_0 = <2,3,4>

咔掉第一個三角形

V_3相鄰的頂點V_2初始時是反射點,咔掉T_0后仍是反射點。與V_3相鄰的頂點V_4初始時是耳朵尖尖,咔掉T_0后仍是耳朵尖尖。可知反射點列表R維持原狀,但耳朵尖尖列表變為E = \{4,6,9\}

凸出點 C = \{0,1,4,6,9\}
反射點 R = \{2,5,7,8\}
耳朵尖尖 E = \{4,6,9\}
三角形 T_0=<2,3,4>

② 然后把頂點4對應的耳朵咔掉,可得三角化后的又一個三角形T_1 = <2, 4, 5>

咔掉第二個三角形

V_4相鄰的頂點V_2初始時是反射點,咔掉T_0后仍是反射點。與V_4相鄰的頂點V_5初始時是反射點,咔掉T_1后變成了凸出點,經過測試后確定為耳朵尖尖,故從反射點列表中移除V_5,反射點列表變為R = \{2,7,8\}。但耳朵尖尖列表變為E = \{4,6,9\}

凸出點 C = \{0,1,5,6,9\}
反射點 R = \{2,7,8\}
耳朵尖尖 E = \{4,6,9\}
三角形 T_0=<2,3,4>,T_1=<2,4,5>

如此重復直到將多邊形全部三角化,得到三角形
T_0=<2,3,4>,T_1=<2,4,5>,T_2=<2,5,6>,T_3=<2,6,7>,T_4=<8,9,0>,T_5=<8,0,1>,T_6=<1,2,7>,T_7=<7,8,1>

分解后的多邊形

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容