1. 什麼是泰森多邊形
下面來科普下泰森多邊形(Voronoi),來自百度百科。
左邊的圖就是泰森多邊形,看著是不是有點眼熟?對了,水立方便是基於此原理設計的。
圖:左為泰森多邊形,右為水立方
long long ago,美國氣候學家A·H·Thiessen提出了一種根據離散分佈的氣象站的降雨量來計算平均降雨量的方法,即將所有相鄰氣象站連成三角形,作這些三角形各邊的垂直平分線,於是每個氣象站周圍的若干垂直平分線便圍成一個多邊形。用這個多邊形內所包含的一個唯一氣象站的降雨強度來表示這個多邊形區域內的降雨強度,並稱這個多邊形為泰森多邊形。
泰森多邊形的特性是:
1、每個泰森多邊形內僅含有一個離散點資料;
2、泰森多邊形內的點到相應離散點的距離最近;
3、位於泰森多邊形邊上的點到其兩邊的離散點的距離相等。
泰森多邊形可用於定性分析、統計分析、鄰近分析等。例如,可以用離散點的性質來描述泰森多邊形區域的性質;可用離散點的資料來計算泰森多邊形區域的資料;判斷一個離散點與其它哪些離散點相鄰時,可根據泰森多邊形直接得出,且若泰森多邊形是n邊形,則就與n個離散點相鄰;當某一資料點落入某一泰森多邊形中時,它與相應的離散點最鄰近,無需計算距離。
在泰森多邊形的構建中,首先要將離散點構成三角網。這種三角網稱為Delaunay三角網。
泰森多邊形又叫馮洛諾伊圖(Voronoi diagram),得名於Georgy Voronoi。
2. 泰森多邊形的建立步驟
建立泰森多邊形演算法的關鍵是對離散資料點合理地連成三角網,即構建Delaunay三角網。建立泰森多邊形的步驟為:
1) 離散點自動構建三角網,即構建Delaunay三角網。對離散點和形成的三角形編號,記錄每個三角形是由哪三個離散點構成的。
2) 找出與每個離散點相鄰的所有三角形的編號,並記錄下來。這隻要在已構建的三角網中找出具有一個相同頂點的所有三角形即可。
3) 對與每個離散點相鄰的三角形按順時針或逆時針方向排序,以便下一步連線生成泰森多邊形。設離散點為o。找出以o為頂點的一個三角形,設為A;取三角形A除o以外的另一頂點,設為a,則另一個頂點也可找出,即為f;則下一個三角形必然是以of為邊的,即為三角形F;三角形F的另一頂點為e,則下一三角形是以oe為邊的;如此重複進行,直到回到oa邊。
4) 計算每個三角形的外接圓圓心,並記錄之。
5) 根據每個離散點的相鄰三角形,連線這些相鄰三角形的外接圓圓心,即得到泰森多邊形。對於三角網邊緣的泰森多邊形,可作垂直平分線與圖廓相交,與圖廓一起構成泰森多邊形。
3. IDL中建立泰森多邊形的方法
從上邊可以看到,需要先提供離散點,然後構建Delaunay三角網,最後根據規則構建泰森多邊形,用到的IDL函式為TRIANGULATE和VORONOI。分幾種情況進行介紹。
注:下圖中黑點為離散點位置,可以更好理解泰森多邊形的構建過程。
3.1 隨機離散點
透過如下程式碼生成隨機離散點,效果圖如下:
N = 36
X = RANDOMN(seed, N)
Y = RANDOMN(seed, N)
圖:隨機離線點自動構建的泰森多邊形
3.2 規則離散點
座標為正規網格,例如[0, 0]、[0, 1]、[0, 2]、[1, 0]、[1, 1]、[1, 2]… …
使用如下程式碼生成規則離散點:
X = REBIN(INDGEN(6)+10, 36,1)
Y = REFORM(REBIN(INDGEN(6)+10, 6,6),36,1)
X為:
10 10 10 10 10 10
11 11 11 11 11 11
12 12 12 12 12 12
13 13 13 13 13 13
14 14 14 14 14 14
15 15 15 15 15 15
Y為:
10 11 12 13 14 15
10 11 12 13 14 15
10 11 12 13 14 15
10 11 12 13 14 15
10 11 12 13 14 15
10 11 12 13 14 15
生成的泰森多邊形就是這樣的規則網格了。
圖:規則離散點生成的泰森多邊形
3.3 較規則離散點
其實就是給規則離散點加入一些隨機噪聲,利用Randomu或Randomn可以生成。程式碼如下:
X = REBIN(INDGEN(6)+10, 36,1)+ RANDOMU(seed, 36,1)
Y = REFORM(REBIN(INDGEN(6)+10, 6,6),36,1)+ RANDOMU(seed, 36,1)
生成的泰森多邊形如下所示,較為類似於水立方的效果。
圖:較規則離散點構建的泰森多邊形(類似水立方)
最後來一張疊加三角網顯示效果圖,更有利於瞭解泰森多邊形的構建原理:
圖:疊加三角網顯示效果
附IDL原始碼:
PRO testVoronoi
idx = 0
; 建立離散點
CASE idx OF
; 隨機離散點
0: BEGIN
N = 36
X = RANDOMN(seed, N)
Y = RANDOMN(seed, N)
END
; 規則離散點
1: BEGIN
X = REBIN(INDGEN(6)+10, 36,1)
Y = REFORM(REBIN(INDGEN(6)+10, 6,6),36,1)
N = N_ELEMENTS(X)
END
; 較規則離散點
2: BEGIN
X = REBIN(INDGEN(6)+10, 36,1)+ RANDOMU(seed, 36,1)
Y = REFORM(REBIN(INDGEN(6)+10, 6,6),36,1)+ RANDOMU(seed, 36,1)
N = N_ELEMENTS(X)
END
ELSE:
ENDCASE
; 構建Delaunay三角網
TRIANGULATE, X, Y, tr, CONN=C
; 繪製離散點
Points = PLOT(x, y, $
LINESTYLE=6, $
SYMBOL='o', SYM_COLOR='black', $
SYM_SIZE=0.5, $
/SYM_FILLED, SYM_FILL_COLOR='black', $
AXIS_STYLE=4, $
MARGIN=[0,0,0,0], $
WINDOW_TITLE='泰森多邊形')
FOR I=0, N-1 DO BEGIN
; 獲取第i個泰森多邊形:
VORONOI, X, Y, I, C, Xp, Yp
; 快速視覺化繪製
; 建立Polygon函式中的CONNECTIVITY關鍵字,指定連通性
n=N_ELEMENTS(Xp)
con = [n,INDGEN(n)]
; 繪製泰森多邊形
poly = POLYGON(Xp,Yp,/data,CONNECTIVITY=con, /current, $
FILL_BACKGROUND=1, FILL_COLOR=I*7+5, RGB_TABLE=25, $
COLOR='white')
ENDFOR
; 繪製三角網,如果不想繪製,把這幾行註釋即可
n_Tr = (SIZE(tr, /DIMENSIONS))[1]
FOR i = 0,n_Tr-1 DO BEGIN
tri = POLYGON(X[tr[*,i]], Y[tr[*,i]], CONNECTIVITY=[3,0,1,2], $
/current, color = 'black', /data, FILL_BACKGROUND=0, $
LINESTYLE=4)
ENDFOR
; 將離散點置頂顯示
Points.ORDER, /BRING_TO_FRONT
END