使用前篇介绍的数据结构
输入:坐标平面内的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等)