Graham 掃瞄法找凸包 convexHull

2022-04-09 13:21:21 字數 2957 閱讀 7510

通俗的話來解釋凸包:給定二維平面上的點集,凸包就是將最外層的點連線起來構成的凸多邊型,它能包含點集中所有的點

由最底的一點 \(p_1\) 開始(如果有多個這樣的點,那麼選擇最左邊的),計算它跟其他各點的連線和 x 軸正向的角度,按小至大將這些點排序,稱它們的對應點為 \(p_,p_,...,p_\)。這裡的時間複雜度可達 \(o(n \log )\)

以下圖為例,基點為h,根據夾角由小至大排序後依次為h,k,c,d,l,f,g,e,i,b,a,j。下面進行逆時針掃瞄。

3. 線段一定在凸包上,接著加入c。假設線段也在凸包上,因為就h,k,c三點而言,它們的凸包就是由此三點所組成。但是接下來加入d時會發現,線段才會在凸包上,所以將線段排除,c點不在是凸包上。

4. 即當加入一點時,必須考慮到前面的線段是否會出現在凸包上。從基點開始,凸包上每條相臨的線段的旋轉方向應該一致。如果發現新加的點使得新線段與上線段的旋轉方向發生變化,則可判定上一點必然不在凸包上。實現時可用向量叉積進行判斷,設新加入的點為 \(p_\),上一點為 \(p_n\),再上一點為 \(p_\)。順時針掃瞄時,如果向量 \(\) 與 \(\) 的叉積為正,則將上一點刪除。

graham掃瞄法主要用乙個\(\color\)來解決凸包問題,點集 q 中每個點都會進棧一次,不符合條件的點會被彈出,演算法終止時,棧中的點就是凸包的頂點(逆時針順序在邊界上)。該演算法具體步驟為

由於選擇第乙個基點時, 選擇的是 y 座標最小且最靠左的點, 所以極角取值範圍 [0, 180), 我們關心的是極角的相對大小, 而不用求角度具體大小(雖然可以通過 \(\cos(\theta)\) 在 [0, 180)遞減性質 來求實際角度大小), 所以極角排序可以通過向量叉積來做. 如果 \(p_1 \times p_2\) 向量叉積為正, 則 \(p_2\) 在 \(p_1\) 逆時針放心, 那麼 \(p_2\) 與 x 正方向夾角比 \(p_1\) 大

有向量 \(p1\) 和 \(p2\), 我們可以把叉積理解為由點 \((0,0)\), \(\vec p_1\), \(\vec p_2\) 和 \(\vec p_1+ \vec p_2\) 所構成的平行四邊形有向面積.

二維平面點叉乘行列式:

\[\vec p_1 \times \vec p_2 = \begin

\vec i & \vec j & \vec k \\

a_x & a_y & 0\\

b_x & b_y & 0\\

\end = (a_xb_y-a_yb_x)\space \vec k\]

相對座標原點,若 \(\vec p_1 \times \vec p_2\)值為正,\(\vec p_2\) 在 \(\vec p_1\) 逆時針方向,若值為負,\(\vec p_2\) 在 \(\vec p_1\) 順時針方向。相對公共端點 \(\vec p_0\),叉積計算為

\[(\vec p_1 - \vec p_0) \times (\vec p_2 - \vec p_0) = (x_1 - x_0) \times (y_2 - y_0) - (x_2 - x_0) \times (y_1 - y_0)

\]乙個簡單的確定滿足 「右手定則」 向量叉積的方向的方法是這樣的:若座標系是滿足右手定則的,當右手的四指從 \(\vec a\) 以不超過 180 度的轉角轉向 \(\vec b\) 時,豎起的大拇指指向是 \(\vec c\) 的方向.

}參考:

凸包(Graham掃瞄法構建)

ps 我的媽呀,心態 好像也不太難,看各種模板看的雲裡霧裡的,真的還是自己動手敲來的好,幾乎沒多久就懂的差不多了。乙個本該寒假就該掌握的知識,居然熬了我幾個小時。這一次還是很好的了解了凸包,以前看群裡學長們說,覺得好高大上,好難的樣子,仔細了解後發現其實也沒有想象中的那麼恐怖 凸包基本概念 這就是乙...

凸包問題 Graham掃瞄法

凸包點集q的凸包 convex hull 是指乙個最小凸多邊形,滿足q中的點或者在多邊形邊上或者在其內。右圖中由紅色線段表示的多邊形就是點集q 的凸包。頂點個數n 1 排序 在點集q中找最左下方的點p0,就是x座標和y座標都最小的點,其餘的點計算它們的極座標幅角,以幅角的非降序順序來排序,如果有幅角...

尋找凸包的graham 掃瞄法

1,點集q的凸包 convex hull 是指乙個最小凸多邊形,滿足q中的點或者在多邊形邊上或者在其內。2,凸包最常用的凸包演算法是graham掃瞄法和jarvis步進法。3,graham掃瞄法 首先,找到所有點中最左邊的 y座標最小的 如果y座標相同,找x座標最小的.以這個點為基準求所有點的極角 ...