個人筆記|GIS的ear clipping算法

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

聲明:在本學(xué)習(xí)筆記的寫作過程中,沒有一只貓貓受到實際傷害甩骏。
(包括賽博貓貓在內(nèi))

引入

計算機(jī)圖形學(xué)的多邊形分解問題

簡單多邊形定義

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

簡單與復(fù)雜多邊形對比

左側(cè)多邊形為簡單多邊形拐袜。中間的多邊形的頂點(diǎn)1有兩條以上邊冯凹,不為簡單多邊形谎亩。右側(cè)多邊形中連接頂點(diǎn)1和頂點(diǎn)4的邊與其他邊在非頂點(diǎn)處相交,該多邊形不為簡單多邊形谈竿。

在一個簡單多邊形中,當(dāng)遍歷邊緣時摸吠,多邊形內(nèi)部的有限區(qū)域總處于遍歷方向同一側(cè)空凸。假設(shè)以逆時針方向遍歷例圖中的簡單多邊形邊緣,則多邊形內(nèi)部區(qū)域始終處于遍歷方向左側(cè)寸痢。

多邊形三角化算法

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

Ear Clipping算法

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

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

定義

貓貓耳朵

多邊形的一只貓貓耳朵是由三個相鄰頂點(diǎn)V_{i_0},V_{i_1},V_{i_2}構(gòu)成的三角形献烦,其中V_{i_1} 是三角形凸出的頂點(diǎn)滓窍,在該頂點(diǎn)處三角形的內(nèi)角角度小于\pi。作一條連接點(diǎn)V_{i_0},V_{i_2}的輔助線巩那,該線段完全位于多邊形內(nèi)部吏夯。這只貓貓耳朵只含有構(gòu)成耳朵的三個頂點(diǎn),不包含多邊形的其他頂點(diǎn)即横。在計算機(jī)幾何學(xué)術(shù)語里把連接點(diǎn)V_{i_0},V_{i_2}的輔助線叫做多邊形的一條對角線噪生,把頂點(diǎn)V_{i_1}叫做耳朵尖(貓貓的耳朵根根和耳朵尖尖,懂得都懂)东囚。一個三角形就是一只貓貓耳朵跺嗽,三角形的任意一個頂點(diǎn)都可以是耳朵尖尖。

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

咔耳朵算法

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

壞消息:難的步驟要來了

step1

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

step2

其次朦促,對頂點(diǎn)進(jìn)行迭代膝晾,分出各個不重疊的貓貓耳朵。對于每個頂點(diǎn)V_i和該頂點(diǎn)對應(yīng)的三角形<V_{i-1}, V_i, V_{i+1}>务冕,測試多邊形的其他頂點(diǎn)是否位于該三角形中血当。該索引對n取模,所以V_n = V_0V_{-1} = V_{n-1}禀忆。如果三角形內(nèi)不包含多邊形的其他頂點(diǎn) 臊旭,我們就喜提了一只貓貓耳朵!如果三角形內(nèi)至少含有多邊形的一個頂點(diǎn)箩退,它就不是貓貓耳朵离熏。在三角形包容測試中效率更高的三角化方法是只考慮反射點(diǎn)。反射點(diǎn)指由兩條邊構(gòu)成的角度大于\pi的內(nèi)部角的頂點(diǎn)戴涝。多邊形的數(shù)據(jù)結(jié)構(gòu)包含四個同時共用一個存儲數(shù)組的雙鏈表滋戳,而非動態(tài)分配和釋放內(nèi)存的標(biāo)準(zhǔn)列表數(shù)據(jù)結(jié)構(gòu)。使用循環(huán)鏈表存儲多邊形的所有頂點(diǎn)啥刻,線性表存儲凸頂點(diǎn)奸鸯,另一個線性表存儲反射點(diǎn),另一個循環(huán)鏈表存儲耳朵尖尖可帽。

step3

當(dāng)完成對存儲反射點(diǎn)和耳朵尖尖的數(shù)據(jù)列表初始化后娄涩,就可以一只接一只地咔掉貓貓耳朵了!若V_i是已經(jīng)被咔掉的貓貓耳朵映跟,那么與其相鄰的頂點(diǎn)V_{i-1}和頂點(diǎn)V_{i+1}的邊的參數(shù)隨之變化钝满。若一相鄰頂點(diǎn)是凸出點(diǎn),則其仍是凸出點(diǎn)申窘。若一相鄰頂點(diǎn)是耳朵弯蚜,在移除V_i后它可能就不再是耳朵了。若為反射點(diǎn)剃法,則可能變?yōu)橥钩鳇c(diǎn)或耳朵碎捺。在移除V_i后,若存在一凸出的相鄰頂點(diǎn),則必須通過遍歷反射點(diǎn)和測試三角形內(nèi)是否包含點(diǎn)來驗證該相鄰頂點(diǎn)是否為耳朵收厨。整個過程的復(fù)雜度是O(n^2)

算法示例

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

初始的簡單多邊形

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

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

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

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

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

咔掉第一個三角形

V_3相鄰的頂點(diǎn)V_2初始時是反射點(diǎn)雁竞,咔掉T_0后仍是反射點(diǎn)。與V_3相鄰的頂點(diǎn)V_4初始時是耳朵尖尖拧额,咔掉T_0后仍是耳朵尖尖碑诉。可知反射點(diǎn)列表R維持原狀侥锦,但耳朵尖尖列表變?yōu)?img class="math-inline" src="https://math.jianshu.com/math?formula=E%20%3D%20%5C%7B4%2C6%2C9%5C%7D" alt="E = \{4,6,9\}" mathimg="1">进栽。

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

② 然后把頂點(diǎn)4對應(yīng)的耳朵咔掉,可得三角化后的又一個三角形T_1 = <2, 4, 5>恭垦。

咔掉第二個三角形

V_4相鄰的頂點(diǎn)V_2初始時是反射點(diǎn)快毛,咔掉T_0后仍是反射點(diǎn)。與V_4相鄰的頂點(diǎn)V_5初始時是反射點(diǎn)番挺,咔掉T_1后變成了凸出點(diǎn)唠帝,經(jīng)過測試后確定為耳朵尖尖,故從反射點(diǎn)列表中移除V_5玄柏,反射點(diǎn)列表變?yōu)?img class="math-inline" src="https://math.jianshu.com/math?formula=R%20%3D%20%5C%7B2%2C7%2C8%5C%7D" alt="R = \{2,7,8\}" mathimg="1">襟衰。但耳朵尖尖列表變?yōu)?img class="math-inline" src="https://math.jianshu.com/math?formula=E%20%3D%20%5C%7B4%2C6%2C9%5C%7D" alt="E = \{4,6,9\}" mathimg="1">。

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

如此重復(fù)直到將多邊形全部三角化禁荸,得到三角形
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>

分解后的多邊形

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末右蒲,一起剝皮案震驚了整個濱河市阀湿,隨后出現(xiàn)的幾起案子赶熟,更是在濱河造成了極大的恐慌,老刑警劉巖陷嘴,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件映砖,死亡現(xiàn)場離奇詭異,居然都是意外死亡灾挨,警方通過查閱死者的電腦和手機(jī)邑退,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來劳澄,“玉大人地技,你說我怎么就攤上這事∶氚危” “怎么了莫矗?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我作谚,道長三娩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任妹懒,我火速辦了婚禮雀监,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘眨唬。我一直安慰自己会前,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布单绑。 她就那樣靜靜地躺著回官,像睡著了一般。 火紅的嫁衣襯著肌膚如雪搂橙。 梳的紋絲不亂的頭發(fā)上歉提,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機(jī)與錄音区转,去河邊找鬼苔巨。 笑死,一個胖子當(dāng)著我的面吹牛废离,可吹牛的內(nèi)容都是我干的侄泽。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼蜻韭,長吁一口氣:“原來是場噩夢啊……” “哼悼尾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起肖方,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤闺魏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后俯画,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體析桥,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年艰垂,在試婚紗的時候發(fā)現(xiàn)自己被綠了泡仗。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡猜憎,死狀恐怖娩怎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情胰柑,我是刑警寧澤截亦,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布辣辫,位于F島的核電站,受9級特大地震影響魁巩,放射性物質(zhì)發(fā)生泄漏急灭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一谷遂、第九天 我趴在偏房一處隱蔽的房頂上張望葬馋。 院中可真熱鬧,春花似錦肾扰、人聲如沸畴嘶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窗悯。三九已至,卻和暖如春偷拔,著一層夾襖步出監(jiān)牢的瞬間蒋院,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工莲绰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留欺旧,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓蛤签,卻偏偏與公主長得像辞友,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子震肮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

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