public static VoronoiGraph ComputeVoronoiGraph(Dictionary<Point, VoronoiCell> cells)
{
BinaryPriorityQueue PQ = new BinaryPriorityQueue();
Hashtable CurrentCircles = new Hashtable();
VoronoiGraph VG = new VoronoiGraph();
VNode RootNode = null;
foreach(Point V in cells.Keys)
{
PQ.Push(new VDataEvent(V));
}
while(PQ.Count>0)
{
VEvent VE = PQ.Pop() as VEvent;
VDataNode[] CircleCheckList;
if(VE is VDataEvent)
{
RootNode = VNode.ProcessDataEvent(VE as VDataEvent,RootNode,VG,VE.Y,out CircleCheckList);
}
else if(VE is VCircleEvent)
{
CurrentCircles.Remove(((VCircleEvent)VE).NodeN);
if(!((VCircleEvent)VE).Valid)
continue;
RootNode = VNode.ProcessCircleEvent(VE as VCircleEvent,RootNode,VG,VE.Y,out CircleCheckList);
}
else throw new Exception("Got event of type "+VE.GetType().ToString()+"!");
foreach(VDataNode VD in CircleCheckList)
{
if(CurrentCircles.ContainsKey(VD))
{
((VCircleEvent)CurrentCircles[VD]).Valid=false;
CurrentCircles.Remove(VD);
}
VCircleEvent VCE = VNode.CircleCheckDataNode(VD,VE.Y);
if(VCE!=null)
{
PQ.Push(VCE);
CurrentCircles[VD]=VCE;
}
}
if(VE is VDataEvent)
{
Point DP = ((VDataEvent)VE).DataPoint;
foreach(VCircleEvent VCE in CurrentCircles.Values)
{
if (MathF.Dist(DP.X, DP.Y, VCE.Center.X, VCE.Center.Y) < VCE.Y - VCE.Center.Y && Math.Abs(MathF.Dist(DP.X, DP.Y, VCE.Center.X, VCE.Center.Y) - (VCE.Y - VCE.Center.Y)) > 1e-10)
VCE.Valid = false;
}
}
}
VNode.CleanUpTree(RootNode);
foreach(VoronoiEdge VE in VG.Edges)
{
if(VE.Done)
continue;
if(VE.VVertexB.IsUndefined)
{
VE.AddVertex(Fortune.VVInfinite);
if(Math.Abs(VE.LeftData.Y-VE.RightData.Y)<1e-10 && VE.LeftData.X<VE.RightData.X)
{
Point T = VE.LeftData;
VE.LeftData = VE.RightData;
VE.RightData = T;
}
}
}
ArrayList MinuteEdges = new ArrayList();
foreach (var edge in VG.Edges)
{
double ax = Math.Round(edge.VVertexA.X, Vector.Precision), ay = Math.Round(edge.VVertexA.Y, Vector.Precision),
bx = Math.Round(edge.VVertexB.X, Vector.Precision), by = Math.Round(edge.VVertexB.Y, Vector.Precision);
if (ax == bx && ay == by)
{
MinuteEdges.Add(edge);
continue;
}
edge.VVertexA = new Point(ax, ay);
edge.VVertexB = new Point(bx, by);
}
foreach(VoronoiEdge VE in MinuteEdges)
VG.Edges.Remove(VE);
foreach (var edge in VG.Edges)
{
VoronoiCell rightCell = cells[edge.RightData], leftCell = cells[edge.LeftData];
if (!rightCell.Edges.Contains(edge))
{
rightCell.Edges.Add(edge);
}
if (!leftCell.Edges.Contains(edge))
{
leftCell.Edges.Add(edge);
}
}
VG.Cells = cells;
return VG;
}