1. 程式人生 > >計算幾何之凸包----Graham掃描法

計算幾何之凸包----Graham掃描法

計算幾何之凸包(convexHull)----Graham掃描法 關於凸包的嚴格定義,這裡不打算寫出來,大家可以自行Google或者百度,因為嚴格的數學定義反而不太好理解,用最通俗的話來解釋凸包:給定二維平面上的點集,凸包就是將最外層的點連線起來構成的凸多邊型,它能包含點集中所有的點。如圖所示(圖片來自wiki)
凸包最常見的應用是求平面上距離最遠的兩個點,一般有兩種演算法來計算包含n個點的點集的凸包。這種兩種演算法都是按逆時針方向的順序輸出凸包。第一種演算法就是接下來要介紹的Graham掃描法(Graham's scan),時間複雜度為O(nlgn)。第二種演算法是Jarvis步進法(Jarvis march),時間複雜度為O(nh),其中h為凸包頂點的個數。第二種演算法下次介紹,先介紹Graham掃描法(Graham's scan):
Graham掃描法主要用一個棧來解決凸包問題,點集Q中每個點都會進棧一次,不符合條件的點會被彈出,演算法終止時,棧中的點就是凸包的頂點(逆時針順序在邊界上)。該演算法具體步驟為: 先給出演算法導論中的演算法步驟:
下面是我自己理解的步驟: 1、先選出點集中y座標最小的點記為,

如果y座標相同則相同點中x座標最小的點

2、把按照極角(polar angle)從小到大排序(以  為極點),極角相同的點按照到的距離從小到大排序。 3、把壓入棧。 4、遍歷剩下的點,while迴圈把發現不是凸包頂點的點移除出去,因為當逆時針遍歷凸包時,我們應該在每個頂點向左轉。因此當while迴圈發現在一個頂點處沒有向左轉時,就把該頂點移除出去。至於如何判斷向左向右則是根據叉積來判斷,好吧,看來又出現了一個新概念,又要介紹下叉積。。。。其實對極角排序,也是根據叉積來判斷的。如下圖所示的向量
我們可以把叉積理解為由點(0,0),+=所構成的平行四邊形有向面積.

比較簡潔的定義是矩陣行列式:,若值為正,則相對原點來說,右側(順時針方向),值為負,左側(逆時針方向)。所以相對公共端點,可以計算叉積
如果叉積為正,右側。為負,左側。好吧。。。終於把叉積介紹完了,只能說畫圖寫公式真的很費時間,所以請尊重原創,真的不容易!!! 下面介紹如何用叉積確定向左轉還是向右轉,其實把上面的叉積介紹了下,也差不多了,因為凸包頂點必然都是向左轉,不能向右轉。簡答貼一段演算法導論中的介紹,腦補一下吧:

基本上把叉積介紹完了,回到尋找凸包上,把graham掃面的演算法也介紹了,這時候其實已經可以擼程式碼了,但是為了讓路過的同學更清晰明白演算法的執行過程,放個步驟圖:




看完步驟圖應該很清晰明瞭,希望能幫助大家。