public static VCircleEvent CircleCheckDataNode(VDataNode n, double ys) { VDataNode l = VNode.LeftDataNode(n); VDataNode r = VNode.RightDataNode(n); if (l == null || r == null || l.DataPoint == r.DataPoint || l.DataPoint == n.DataPoint || n.DataPoint == r.DataPoint) { return(null); } if (MathF.ccw(l.DataPoint.X, l.DataPoint.Y, n.DataPoint.X, n.DataPoint.Y, r.DataPoint.X, r.DataPoint.Y, false) <= 0) { return(null); } Point Center = Fortune.CircumCircleCenter(l.DataPoint, n.DataPoint, r.DataPoint); VCircleEvent VC = new VCircleEvent(); VC.NodeN = n; VC.NodeL = l; VC.NodeR = r; VC.Center = Center; VC.Valid = true; if (VC.Y > ys || Math.Abs(VC.Y - ys) < 1e-10) { return(VC); } return(null); }
/// <summary> /// Build a new vector from a string /// </summary> /// <param name="S">A string, as produced by ToString</param> public Vector(string S) { if (S[0] != '(' || S[S.Length - 1] != ')') { throw new Exception("Formatfehler!"); } string[] P = MathF.HighLevelSplit(S.Substring(1, S.Length - 2), ';'); data = new double[P.Length]; int i; for (i = 0; i < data.Length; i++) { data[i] = Convert.ToDouble(P[i]); } }
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); }