使用前篇介紹的數據結構
輸入:座標平面內的n>1個無重合的點組成的點集P
輸出:構造好的Voronoi圖V(P)
1 對這n個點按照x座標值爲主關鍵字,y座標值爲次關鍵字進行排序
2 開始構造:
2.1 if n==2 then 構造兩個點的Voronoi圖,並返回
2.2 if n==3 then 構造三個點的Voronoi圖,並返回
2.3 把n個點平均分成兩部分Pl,Pr
2.4 把點集Pl構造成Voronoi圖 V(Pl)
2.5 把點集Pr構造成Voronoi圖 V(Pr)
2.6 合併V(Pl),V(Pr)爲V(P)
2.7 返回V(P)
輸入:已生成的V(Pl),V(Pr)
輸出:合併後的V(P),P=PlUPr
1 分別求Pl,Pr的凸包CH(Pl),CH(Pr)
2 BCT ß bottomConnected_tangent(CH(Pl),CH(Pr))
3 UCT ß upConnected_tangent(CH(Pl),CH(Pr))
4 L ß left point of BCT
Rß right point of BCT
5 while (not (BCT =UCT)) do
5.1 isRight ß isLeft ß false
5.2 initEdge(edgeL,edgeR,L,R)
5.3 insertEdge(L,edgeL)
insertEdge(R,edgeR)
5.4 /*對Pr中與R相鄰的點進行測試(以順時針的方向)
5.4.1 pre ß R中edgeR順時針方向下一個半邊節點
5.4.2 if pre != NULL and pre關聯的點在LR向量的左側 then
5.4.2.1 pre1 ß R中pre順時針方向下一個半邊節點
5.4.2.2 while pre1 != NULL and pre1關聯的點在L,R,pre組成的三角形外接圓內 do
5.4.2.2.1 deleteEdge(pre)
5.4.2.2.2 pre ß pre1
5.4.2.2.3 pre1 ß R中pre順時針方向下一個半邊節點
5.4.3 else isRight ß true
5.5 /*對Pl中與L相鄰的點進行測試(以逆時針方向)
5.5.1 next ß L中edgeL逆時針方向下一個半邊節點
5.5.2 if next!=NULL and next關聯的點在RL向量的右側
5.5.2.1 next1 ß L中next逆時針方向下一個半邊節點
5.5.2.2 while next1 !=NULL and next1關聯的點在L,R,next組成的三角形外接圓內 do
5.5.2.2.1 deleteEdge(next)
5.5.2.2.2 next ß next1
5.5.2.2.3 next1ß L中next逆時針方向下一個半邊節點
5.5.3 else isLeft ß true
5.6 if isRight then L ß next關聯的點序號
5.7 else if isLeft then R ß pre關聯的點序號
5.8 else if next關聯的點在L,R,pre組成的三角形外接圓內 then
L ß next關聯的點序號
5.9 else R ß pre關聯的點序號
6 initEdge(edgeL,edgeR,L,R)
7 insertEdge(L,edgeL)
insertEdge(R,edgeR)
initEdge(edgeL,edgeR,L,R)函數初始化兩個半邊節點edgeL和edgeR,其中edgeL將來插入到L的邊鏈表中,使R成爲L的相鄰點(edgeL->mainNum ß L,edgeL->adhereNum ß R);edgeR則剛好相反。
insertEdge(number,edge)函數把半邊節點edge插入到序號爲number的點的邊鏈表中,由於每個點維護的一個循環邊鏈表是按照相鄰點的逆時針方向存儲的,爲了在每次插入後仍然保持這個特性,必須在插入前,先計算要插入的點到第一個點(MyNodel結構中的start序號所示,在第一次插入時賦值,以後就算此節點被刪除,也不改變,以作參考)的夾角,按照夾角的大小來判斷插入的地方(夾角有序排列即意味着那些相鄰點按照逆時針方向排列)。
deleteEdge(edge)函數就是把半邊節點edge和它的對應半邊(twin域指向的半邊節點)刪除。
由於篇幅過長,對於算法的說明在此省略(如求凸包,BCT,UCT等)