graham凸包演算法
⑴ 多邊形快速2D凸包演算法(Melkman's Algorithm)
直觀描述:Melkman's Algorithm - 快速2D凸包演算法Melkman的演算法是一種無需預先排序點的2D凸包計算方法,針對平面單連通多邊形。該演算法在1987年由Melkman提出,以簡化先前復雜演算法,如1983年Graham & Yao修正的Sklansky演算法。
演算法流程如下:
- 輸入多邊形S={P0, P1, ..., Pn}
- 使用雙端隊列存儲處理過的頂點形成凸包,記為Φk = {Dbot ... Dtop}
- 遍歷每個頂點Pk,檢查其相對於凸包的關系:
- 如果Pk在凸包內,不做操作
- 如果Pk在凸包外,刪除隊列中位於新凸包內部的點,然後將Pk分別添加到隊列首尾
演算法的時間復雜度為O(n),空間復雜度也是O(n)。每個頂點最多被添加到隊列兩端兩次,刪除操作最多一次,每次操作涉及常數時間的isLeft判斷。在最理想情況下,演算法僅需2n次測試和4次隊列操作。
以下是演算法的偽代碼示例:
盡管有其他演算法存在,但Melkman演算法因其簡潔性和效率,被認為不太可能被超越。
⑵ 計算幾何演算法快速入門(一):導言
歡迎踏入計算幾何的世界,這是一扇通向高效問題解決的大門,特別適合那些對數學、C++和數據結構有所掌握的你。我們的指南將圍繞Mark de Berg等大師的《計算幾何演算法與應用》展開,這里,我們不再局限於幾何的直觀,而是聚焦於演算法如何在實際問題中游刃有餘,比如在游戲引擎(Unity3D)、CAD/CAE/CAM(土木與機械設計)和GIS等領域大顯身手。
計算幾何的核心理念是,通過演算法處理幾何對象,盡管現實中的精度受限於浮點數的特性,但這並不妨礙我們用它來解決復雜問題。想像一下,二維凸包——這個最小的包含n個點的凸集合,就像用橡皮筋拉出的包圍圈,它揭示了計算幾何的核心邏輯。
讓我們深入探討幾個關鍵概念。首先,凸包問題:getPolygonByLines函數在構建多邊形時,可能會因為多餘的邊而出現錯誤。這要求演算法具備魯棒性,即使面對細微的誤差,也要盡可能生成接近真實凸包的多邊形。例如,遞增式演算法通過排序和逐個添加點,通過向量叉乘判斷點之間的關系,確保決策的准確性。
代碼示例:在判斷點的轉向時,我們有checkTurnRight函數,而在構建上凸包時,我們執行排序、添加點,並在遇到三點共線時執行剔除和轉向判斷。
對於下凸包,其求解過程與二維凸包相似,都是基於排序和掃描,時間復雜度取決於排序演算法的選擇。經典的遞增式演算法,如Andrew演算法(1979年Graham掃描的優化版本),以其簡潔高效而廣受歡迎,是學習計算幾何的絕佳起點。當然,還有其他演算法如數值穩定的、低時間復雜度的,甚至是高維擴展的,它們各有特色,適合根據實際需求進一步探索。
總的來說,計算幾何演算法不僅僅是一門技術,它是一把解開幾何問題的鑰匙,讓你在實際應用中游刃有餘。現在,你已經掌握了入門的要領,准備好了迎接挑戰,深入這個充滿無限可能的領域了嗎?
⑶ 凸包的發展歷史,急需,越詳細越好,謝謝!!!!
⒈對於一個集合D,D中任意有限個點的線性組合的全體稱為D的凸包。 ⒉對於一個集合D,所有包含D的凸集之交稱為D的凸包。 可以證明,上述兩種定義是等價的 概念
1 點集Q的凸包(convex hull)是指一個最小凸多邊形,滿足Q中的點或者在多邊形邊上或者在其內。右圖中由紅色線段表示的多邊形就是點集Q={p0,p1,...p12}的凸包。 2 一組平面上的點,求一個包含所有點的最小的凸多邊形,這就是凸包問題了。這可以形象地想成這樣:在地上放置一些不可移動的木樁,用一根繩子把他們盡量緊地圈起來,並且為凸邊形,這就是凸包了。編輯本段平面凸包求法常見求法
2.0 Graham's Scan法求解凸包問題
概念 凸包(Convex Hull)是一個計算幾何(圖形學)中的概念。用不嚴謹的話來講,給定二維平面上的點集,凸包就是將最外層的點連接起來構成的凸多邊型,它能包含點集中所有點的。嚴謹的定義和相關概念參見維基網路:凸包。 這個演算法是由數學大師葛立恆(Graham)發明的,他曾經是美國數學學會(AMS)主席、AT&T首席科學家以及國際雜技師協會(IJA)主席。(太汗了,這位大牛還會玩雜技~) 問題 給定平面上的二維點集,求解其凸包。 過程 ⒈ 在所有點中選取y坐標最小的一點H,當作基點。如果存在多個點的y坐標都為最小值,則選取x坐標最小的一點。坐標相同的點應排除。然後按照其它各點p和基點構成的向量<H,p>;與x軸的夾角進行排序,夾角由大至小進行順時針掃描,反之則進行逆時針掃描。實現中無需求得夾角,只需根據向量的內積公式求出向量的模即可。以下圖為例,基點為H,根據夾角由小至大排序後依次為H,K,C,D,L,F,G,E,I,B,A,J。下面進行逆時針掃描。 ⒉ 線段<H,K>;一定在凸包上,接著加入C。假設線段<K,C>;也在凸包上,因為就H,K,C三點而言,它們的凸包就是由此三點所組成。但是接下來加入D時會發現,線段<K,D>;才會在凸包上,所以將線段<K,C>;排除,C點不可能是凸包。 ⒊ 即當加入一點時,必須考慮到前面的線段是否會出現在凸包上。從基點開始,凸包上每條相臨的線段的旋轉方向應該一致,並與掃描的方向相反。如果發現新加的點使得新線段與上線段的旋轉方向發生變化,則可判定上一點必然不在凸包上。實現時可用向量叉積進行判斷,設新加入的點為pn + 1,上一點為pn,再上一點為pn - 1。順時針掃描時,如果向量<pn - 1,pn>;與<pn,pn + 1>;的叉積為正(逆時針掃描判斷是否為負),則將上一點刪除。刪除過程需要回溯,將之前所有叉積符號相反的點都刪除,然後將新點加入凸包。 在上圖中,加入K點時,由於線段<H,K>;相對於<H,C>;為順時針旋轉,所以C點不在凸包上,應該刪除,保留K點。接著加入D點,由於線段<K,D>;相對<H,K>;為逆時針旋轉,故D點保留。按照上述步驟進行掃描,直到點集中所有的點都遍例完成,即得到凸包。 復雜度 這個演算法可以直接在原數據上進行運算,因此空間復雜度為O⑴。但如果將凸包的結果存儲到另一數組中,則可能在代碼級別進行優化。由於在掃描凸包前要進行排序,因此時間復雜度至少為快速排序的O(nlgn)。後面的掃描過程復雜度為O(n),因此整個演算法的復雜度為O(nlgn)。 ⒉1凸包最常用的凸包演算法是Graham掃描法和Jarvis步進法。 對於一個有三個或以上點的點集Q,過程如下: 計算點集最右邊的點為凸包的頂點的起點,如上圖的P3點。 Do For i = 0 To 總頂點數 計算有向向量P3->Pi If 其餘頂點全部在有向向量P3->Pi的左側或右側,則Pi點為凸包的下一頂點 Pi點加入凸包列表 GoTo 1 End If Next Exit Do 1: Loop 此過程執行後,點按極角自動順時針或逆時針排序,只需要按任意兩點的次序就可以了。而左側或右側的判斷可以用前述的矢量點積性質實現。
特殊演算法
⒉2求凸包有很多方法,不過最適合OIer和ACMer的估計還是Graham's Scan這個方法了。它的大致方法是這樣的:首先,找到所有點中最左邊的(y坐標最小的),如果y坐標相同,找x坐標最小的;以這個點為基準求所有點的極角(atan2(y-y0,x-x0)),並按照極角對這些點排序,前述基準點在最前面,設這些點為P[0]..P[n-1];建立一個棧,初始時P[0]、P[1]、P[2]進棧,對於P[3..n-1]的每個點,若棧頂的兩個點與它不構成「向左轉」的關系,則將棧頂的點出棧,直至沒有點需要出棧以後將當前點進棧;所有點處理完之後棧中保存的點就是凸包了。 如何判斷A、B、C構成的關系不是向左轉呢?如果b-a與c-a的叉乘小於0就不是。a與b的叉乘就是a.x*b.y-a.y*b.x。 上面的這個Graham的實現比我原來按照USACO里的課文寫得簡單多了,主要是它通過簡單的預處理保證了P[0]、P[1]以及P[n-1]肯定是凸包里的點,這樣就可以避免在凸包「繞回來」的時候繁雜的處理。
中心法
先構造一個中心點,然後將它與各點連接起來,按斜率遞增的方法,求出凸包上部;再按斜率遞減的方法,求出凸包下部。
水平法
從最左邊的點開始,按斜率遞增的方法,求出凸包上部;再按斜率遞減的方法,求出凸包下部。水平法較中心法減少了斜率無限大的可能,減少了代碼的復雜度。編輯本段代碼例代碼一
(在編輯器中將"_ "(下劃線+空格)替換成兩個空格即可編譯; 注意要去掉開通的雙位元組中文空格,蛋疼的網路。)
⑷ 凸包平面凸包求法
在計算幾何中,凸包(Convex Hull)是一個重要概念,它是指二維平面上給定點集最外層的凸多邊形。Graham's Scan演算法是求解這個問題的經典方法,由數學家Graham發明,他同時也是多個學術組織的主席。(這位科學家才華橫溢,不僅在數學領域有建樹,還涉足雜技藝術。)
該演算法步驟如下:
- 首先,選擇所有點中y坐標最小的點H(如果有多解,選x坐標最小的),並排除坐標相同的點。然後對其他點與H構成的向量按照它們與x軸正方向的夾角(不需計算夾角,僅用向量模判斷)進行排序,從大到小(或從小到大)進行掃描。例如,如圖所示,經過排序後點的添加順序為H, K, C, D, L, F, G, E, I, B, A, J,接著進行逆時針(或順時針)掃描。
- 線段總是凸包的一部分,加入C後,可能需要調整。例如,盡管是凸包,但不是,因為加入D後,才是。當添加新點時,需要檢查是否改變之前線段的旋轉方向,若改變,則之前點可能不包含在凸包內,通過向量叉積判斷。
整個過程持續到所有點都遍歷完畢,即得到凸包。演算法的時間復雜度至少為O(n log n),空間復雜度為O(1)(直接在原數據上運算)。
除了Graham's Scan,還有Jarvis步進法和一些特殊演算法,如中心法和水平法,它們各有優劣。Graham's Scan因其簡潔性和對大部分點集的適用性,通常被認為是OIer和ACMer的最佳選擇。
⑸ chan綆楁硶鏄浠涔堟剰鎬濓紵
浠涔堟槸chan綆楁硶錛熺畝鍗曟潵璇達紝瀹冩槸涓縐嶈В鍐沖嚫鍖呴棶棰樼殑綆楁硶銆傚嚫鍖呴棶棰樻槸璁$畻涓緇勭偣鐨勬渶灝忓嚫鍖呯殑闂棰橈紝鑰宑han綆楁硶鍒欐槸鍦ㄨ$畻鍑稿寘鏃訛紝浼樺寲浼犵粺鐨凣raham綆楁硶鍜孞arvis綆楁硶鐨勬晥鐜囧拰鎴愭湰銆傞氳繃灝嗙偣鐨勯泦鍚堝垎鎴愬皬鐨勫瓙闆嗭紝騫跺埄鐢ㄩ儴鍒嗙粨鏋滄潵璁$畻鍑稿寘錛宑han綆楁硶鑳藉湪鏇寸煭鐨勬椂闂村唴瀹屾垚榪欓」浠誨姟銆
chan綆楁硶鐨勫師鐞嗘槸浠涔堬紵
chan綆楁硶鏄濡備綍璇嗗埆鍑稿寘鐨勶紵瀹冨熀浜庣敱涓や釜瀛愰棶棰樼粍鎴愮殑濂楄礬錛氭壘鍒扮偣闆嗙殑鏈灝忓嚫鍖咃紝騫跺皢鐐瑰垝鍒嗕負灝忛儴鍒嗐傞氳繃鎵懼埌姣忎釜瀛愰泦鐨勭Щ浜ょ偣錛宑han綆楁硶鑳藉熻$畻鍑烘暣涓鐐歸泦鐨勫嚫鍖呫傞殢鐫闂棰樼殑鍙樺緱鏇村姞澶嶆潅錛宑han綆楁硶鐨勮繍琛岄熷害浠嶇劧闈炲父楂橈紝榪欐槸鐢卞叾鍒涙柊鎬濈淮銆佸叿鏈夎嚜閫傚簲瑙e喅鏂規堝拰鍒嗚屾不涔嬬殑鏂規硶鎵鍐沖畾鐨勩
chan綆楁硶鍦ㄨ稿氶嗗煙閮芥湁騫挎硾鐨勫簲鐢ㄣ備緥濡傦紝瀹冨彲鐢ㄤ簬CAD杞浠朵腑鐨勫嚑浣曟暟鎹搴擄紝涔熷彲鐢ㄤ簬鍏ㄦ伅鎴愬儚鍜岀嚎鎬ц勫垝鐨勬ц兘浼樺寲銆俢han綆楁硶榪樻槸鍏朵粬綆楁硶鐨勫熀紜錛屽備駭鐢2D鍗婇忔槑瀵硅薄錛堝傞紶鏍囨寚閽堬級錛屼互鍙婃父鎴忓紑鍙戜腑鐨勭版挒媯嫻嬨傛棤璁虹敤浜庡摢縐嶅簲鐢錛宑han綆楁硶閮芥槸鍏堣繘涓旈珮鏁堢殑瑙e喅鏂規堬紝鍙浠ヤ負璁$畻鏈虹戝﹀拰紱繪暎鏁板﹂嗗煙鐨勫墠娌跨爺絀跺仛鍑洪噸瑕佽礎鐚銆