public static VoronoiGraph ComputeVoronoiGraph(IEnumerable Datapoints) { BinaryPriorityQueue PQ = new BinaryPriorityQueue(); Hashtable CurrentCircles = new Hashtable(); VoronoiGraph VG = new VoronoiGraph(); VNode RootNode = null; foreach (Vector V in Datapoints) { 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) { Vector DP = ((VDataEvent)VE).DataPoint; foreach (VCircleEvent VCE in CurrentCircles.Values) { if (MathTools.Dist(DP[0], DP[1], VCE.Center[0], VCE.Center[1]) < VCE.Y - VCE.Center[1] && Math.Abs(MathTools.Dist(DP[0], DP[1], VCE.Center[0], VCE.Center[1]) - (VCE.Y - VCE.Center[1])) > 1e-10) { VCE.Valid = false; } } } } return(VG); }
public static VoronoiGraph ComputeVoronoiGraph(IEnumerable Datapoints) { BinaryPriorityQueue PQ = new BinaryPriorityQueue(); Hashtable CurrentCircles = new Hashtable(); VoronoiGraph VG = new VoronoiGraph(); VNode RootNode = null; foreach (Vector V in Datapoints) { 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) { Vector DP = ((VDataEvent)VE).DataPoint; foreach (VCircleEvent VCE in CurrentCircles.Values) { if (MathTools.Dist(DP[0], DP[1], VCE.Center[0], VCE.Center[1]) < VCE.Y - VCE.Center[1] && Math.Abs(MathTools.Dist(DP[0], DP[1], VCE.Center[0], VCE.Center[1]) - (VCE.Y - VCE.Center[1])) > 1e-10) { VCE.Valid = false; } } } } VNode.CleanUpTree(RootNode); foreach (VoronoiEdge VE in VG.Edges) { if (VE.Done) { continue; } if (VE.VVertexB == Fortune.VVUnkown) { VE.AddVertex(Fortune.VVInfinite); if (Math.Abs(VE.LeftData[1] - VE.RightData[1]) < 1e-10 && VE.LeftData[0] < VE.RightData[0]) { Vector T = VE.LeftData; VE.LeftData = VE.RightData; VE.RightData = T; } } } ArrayList MinuteEdges = new ArrayList(); foreach (VoronoiEdge VE in VG.Edges) { if (!VE.IsPartlyInfinite && VE.VVertexA.Equals(VE.VVertexB)) { MinuteEdges.Add(VE); // prevent rounding errors from expanding to holes foreach (VoronoiEdge VE2 in VG.Edges) { if (VE2.VVertexA.Equals(VE.VVertexA)) { VE2.VVertexA = VE.VVertexA; } if (VE2.VVertexB.Equals(VE.VVertexA)) { VE2.VVertexB = VE.VVertexA; } } } } foreach (VoronoiEdge VE in MinuteEdges) { VG.Edges.Remove(VE); } return(VG); }
public static VoronoiGraph ComputeVoronoiGraph(IEnumerable Datapoints) { BinaryPriorityQueue PQ = new BinaryPriorityQueue(); Hashtable CurrentCircles = new Hashtable(); VoronoiGraph VG = new VoronoiGraph(); VNode RootNode = null; foreach (Vector V in Datapoints) { 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) { Vector DP = ((VDataEvent)VE).DataPoint; foreach (VCircleEvent VCE in CurrentCircles.Values) { if (MathTools.Dist(DP[0], DP[1], VCE.Center[0], VCE.Center[1]) < VCE.Y - VCE.Center[1] && Math.Abs(MathTools.Dist(DP[0], DP[1], VCE.Center[0], VCE.Center[1]) - (VCE.Y - VCE.Center[1])) > 1e-10) { VCE.Valid = false; } } } } VG.Regions = new Dictionary <Vector, VoronoiRegion>(); foreach (VoronoiEdge e in VG.Edges) { if (e.VVertexA == VVUnkown || e.VVertexB == VVUnkown) { continue; } for (int i = 0; i < 2; ++i) { VoronoiRegion r; Vector key = i == 0 ? e.LeftData : e.RightData; bool exist = VG.Regions.TryGetValue(key, out r); if (exist) { } else { r = new VoronoiRegion(); } if (r.Coners.IndexOf(e.VVertexA) == -1) { r.Coners.Add(e.VVertexA); } if (r.Coners.IndexOf(e.VVertexB) == -1) { r.Coners.Add(e.VVertexB); } r.Edges.Add(e); if (exist) { } else { VG.Regions.Add(key, r); } } } return(VG); }