凸包演算法 一 簡介

2021-05-23 09:01:38 字數 2087 閱讀 2246

凸包(convex hull)

引言歡迎光臨本網頁。在這個網頁中,你可以學習到計算幾何(computational geometry)中的「凸包」(convex hull)概念,以及求凸包的基本原理。你亦可試用本人編寫的用來求凸包的應用程式。

甚麼是凸包?

在了解凸包之前,須先認識何謂「凸多邊形」(convex polygon)。從直觀上說,乙個凸多邊形就是沒有任何凹陷位的多邊形。我們在低年級數學所學習的三角形、正方形、長方形、平行四邊形、正五邊形、正六邊形等等,都是凸多邊形的例子。但是以下這個「凸」字形卻並非凸多邊形,因為箭頭指著的地方實際是乙個凹陷位。

可是上述這一定義很不嚴密,究竟何謂「凹陷位」?實在難以說清楚。因此在數學上,凸多邊形有另乙個嚴格的定義。假設我們在乙個多邊形上(包括多邊形的邊界及邊界圍封的範圍)任意取兩點並以一條線段鏈結該兩點,如果線段上的每一點均在該多邊形上,那麼我們便說這個多邊形是凸的。根據以上定義,我們便可判斷「凸」字形的確不是凸的。例如,在下圖中,鏈結a、b兩點的線段有一部分並不在該多邊形上。

認識了凸多邊形後,我們便可了解何謂凸包。給定平面上的乙個(有限)點集(即一組點),這個點集的凸包就是包含點集中所有點的最小面積的凸多邊形。例如,下圖的點集共包含9個點,圖中的六邊形便是該點集的凸包。其中構成六邊形的6個點稱為「凸包上的點」(hull point),其餘3個點則並非「凸包上的點」。請注意上述定義中「最小面積」這個限制條件,因為除了凸包以外,還有無限多個包含點集中所有點的凸多邊形。例如,只要畫乙個面積足夠大的四邊形,便可包圍任意給定的點集。因此假如沒有這個限制條件,求凸包就變成非常容易但卻沒有唯一解的運算。

求凸包的應用程式

鏈結:

求凸包的基本原理

本程式採用循序漸進的方式求取給定點集的凸包,首先把使用者最初輸入的3個不共線(non-collinear)的點按逆時針方向構成乙個三角形(注1),這就是這3點的凸包。接著程式便會考察第4點,看看這個點是否位於前述三角形之內或三角形的邊上。若是,則這第4點並非凸包上的點,前述三角形保持不變。若否,則把這前述的三角形擴大為乙個四邊形,並把不適用的邊擦去。這個四邊形便是這首4點的凸包。接著程式又會考察第5點,如此類推,直至所有點均已被考察為止。使用者在使用本程式時可以清楚看到上述從最初的三角形逐步擴大為最終的凸包的過程。

這裡涉及到判斷一點是否被包圍在某一多邊形內的問題,人類憑肉眼很容易便能作出此一判斷。可是計算機沒有眼睛,它所具備的資訊只有給定點的座標,我們應如何「教」計算機作出上述判斷呢?其實方法並不太複雜。且來看看乙個簡單的例子。

在上圖中,a、b、c是最初輸入的三點,這三點按逆時針方向構成了乙個三角形。接著讓我們考察第4個點d。這一點有甚麼特點?假如我們循著逆時針方向在三角形的邊上走一周,我們便會發現d點總是位於我們的左方。事實上,在三角形範圍內的任何一點都具有此一特點。

看到這裡,讀者不禁要問,計算機如何判斷某一點是位於某條直線的左邊還是右邊呢?其實只要看看上圖,我們容易發現,左轉相當於逆時針方向,右轉則相當於順時針方向。因此我們可以利用逆時針和順時針這一組概念來代替左、右這兩個概念。這裡我們可以用向量代數中一條有關平面三角形面積的公式。給定平面上3點 p1、p2、p3的座標(x1, y1)、(x2, y2)和(x3, y3),這3點所構成三角形的面積可表達為乙個名為area的函式:

area(p1, p2, p3)=

此一公式使用行列式(determinant)來定義三角形面積,可以展開並化簡為:

area(p1, p2, p3) = (x1y2 - x1y3 - x2y1 + x3y1 + x2y3 - x3y2) / 2

但請注意,上式並非單純計算三角形的面積,而是「有向面積」(signed area),它不僅告訴我們給定3點所構成三角形的大小,而且告訴我們這3點的相對方向。當area(p1, p2, p3) 的值是負數時,這代表p1->p2->p3的走向是逆時針方向。反之,若 area(p1, p2, p3)的值是正數,則代表這3點的走向是順時針方向。若 area(p1, p2, p3)為零,則代表這3點共線。因此area這個函式在求凸包的運算中有極大的用途,可用來判斷哪些點是凸包上的點,以及應用直線鏈結哪些點。事實上,本程式亦廣泛運用這個函式。

注1:如果有3點在同一條直線上,我們就稱該3點共線(collinear)。若果3點共線,便不能構成乙個三角形。至於為何要按逆時針方向構成這個三角形,看看下文便會明白。

源文件

Graham凸包演算法簡介

凸包真是乙個神奇的演算法。對於平面上的一些點,我們要求凸包上所有的點,可以使用graham演算法 時間複雜度o nlogn 先找到最左下的點,把其他的點按叉積排序。然後維護乙個堆疊,每次利用叉積和棧頂比較判斷當前列舉到的點是否是凸包上的點,是則彈出棧頂元素 具體演算法click here 常熟巨大的...

凸包 Graham Scan演算法

graham scan演算法是一種靈活的凸包演算法,時間複雜度是o nlogn 演算法細節 1.選出最左下角的點 排序 x最小,其次是y最小 2.其餘點按極角排序,在極角相等的情況下距離極點 p 0 最近的優先 3.用乙個棧 陣列 儲存凸包上的點,先把p 0 p 1 壓入棧。4.掃瞄每乙個點,用叉積...

凸包 Andrew演算法

凸包的定義如下 在乙個點集d中,按一定順序選取子集q 使得q中所有點順次連線所構成的封閉凸多邊形包住d中所有點 可以形象地理解為 有許多個釘子釘在平面上,用一根牛皮筋把所有點包住 如下圖 andrew演算法是graham演算法的變種。其主要思想為把凸包上的點依次放入棧中,如果發現形成了凹多邊形 叉積...