Convex Hull
Divide-and-conquer
Merge
將大問題分解成小問題,最後進行合併。
Common Kernel
和歸併排序一樣,我們將點分成兩個子集,分別求凸包,問題就變成了如何將兩個凸包合併。
如何將兩個凸包處理成星形多邊形
?
爲了找到Star-shape-polygon
,我們要找到兩個多邊形相交的公共的點,那麼兩個多邊形相交會出現什麼情況呢?
如上圖所示,如,是比較理想的情況,我們很容易找到公共點,對於,找到公共點的可能就會小很多。
更壞的情況,例如,我們甚至無法找到兩個凸包的公共點,那麼如何處理呢?
Interior
對於一個凸包來說,我們如何找到一個點使得這個點在凸包的內部呢?
我們可以選擇凸包上任意三個點,選擇這三個點組成的三角形的重心即可,計算複雜度爲常數時間。
那麼我們現在判斷選出的內點是否在另一個凸包的內部,如果是:
可以發現兩個凸包分別對於內點成一個環形的有序序列(圖中黃色和藍色的直線),則問題變成了經典的環形歸併。歸併之後再次進行Graham-Scan即可。
那麼如何判斷所選內點是否在另一個多邊形內部呢?
In-Convex-polygon-Test。但凸包是動態的,所以要用n次To-Left-Test:
幸運的是,次TLT並不會影響整體算法的複雜度,因爲我們可以將這次操作都可以納入Merge的過程中。
Exterior
接下來我們討論下一種情況,所選內點落在另一個子凸包的外側。
如圖所示,我們可以找出圖中 兩個切點,找到 兩個線段。同理,線段在總凸包中沒有貢獻。
那麼我們可以得到了一個環形有序序列和一個線性有序序列,進行歸併,再次Graham-Scan。
Divide-and-conquer (2)
Preprocessing
歸併算法我們可以看到,有些過於複雜。對於兩個圖包:
如果他們沿着水平方向是可分割的,彼此獨立,那麼合併就非常的簡單。
將點集中的座標按x軸排序,取中點分割即可,那麼我們關注的就是兩個凸包中的兩對點。
Common Tangents
找到兩個凸包的公切線(Common Tangents)。那麼如何找這兩個凸包的公切線呢?問題可能很複雜:
我們從和開始:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qGCTI8Y5-1584153950700)(C:\Users\szx74\Desktop\Blog\計算幾何\image-20200314100712514.png)]
先將兩個點連起來,那麼恩麼找到這兩個點呢?我們在從最開始從下向上歸併的過程中,記下每個凸包的即可。
接下來我們思考連接了之後的動作。
對於每次固定的,找到最優的右側的,使得兩側的點都在它的同一側,這樣我們就得到了局部最優的,那麼我們反觀之前固定的,同樣的方法找到局部最優的,再反觀,反覆進行,直到保證兩個點都爲最優,既兩個點的臨點皆再他們的同一側,這樣我們就找到了一條切線。時間複雜度爲。