public void Generate(List<Vector2> points, int width, int height) { mapWidth = width; mapHeight = height; graph = gen.ComputeVoronoiGraph(points, width, height); edges = graph.Edges.ToList(); sitePolygons = new List<Polygon>(); }
public MapGenerator(GraphicsDevice device, SpriteBatch spriteBatch) { gen = new Fortune(); graph = new VoronoiGraph(); edges = new List<VoronoiEdge>(); sitePolygons = new List<Polygon>(); this.device = device; this.spriteBatch = spriteBatch; }
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 FilterVG(VoronoiGraph VG, double minLeftRightDist) { VoronoiGraph VGErg = new VoronoiGraph(); foreach (VoronoiEdge VE in VG.Edges) { if (Math.Sqrt(Vector.Dist(VE.LeftData, VE.RightData)) >= minLeftRightDist) { VGErg.Edges.Add(VE); } } foreach (VoronoiEdge VE in VGErg.Edges) { VGErg.Vertizes.Add(VE.VVertexA); VGErg.Vertizes.Add(VE.VVertexB); } return(VGErg); }
private int NumberOfSites = 512; // Number of seed points to generate for the voronoi diagram, the higher the number the more tesselated the map will be. private bool BuildGraph () { Sites_World = GenerateRandom (Seed, NumberOfSites, 0, Max); Profiler.BeginSample ("Fortune Compute VoronoiGraph"); Graph_World = Fortune.ComputeVoronoiGraph (Sites_World); Profiler.EndSample (); if (Relax) { // Lloyd Relax the points here to get more even distribution. // First we need to know the N number of Voronoi Verts that make up each cell. // Then we can find the centroid of each of those Cells, and move the Site that created this cell to that centroid. // Finally we replace our existing Voronoi graph with a new one made from these centered sites. // This will be computationally expensive so we don't want to do it too many times, 2 max?? for (int i = 0; i < RelaxSteps; i++) { Sites_World = LloydRelax (Sites_World, Graph_World); Graph_World = Fortune.ComputeVoronoiGraph (Sites_World); } } // now you have all the voronoi vertices in graph.Vertices and all the voronoi edges in Relsult.Edges //Debug.Log ("Number of Sites: " + sites.Length); //Debug.Log ("graph.Verts Length: " + graph.Vertizes.Count); if (GenerateCells) { Debug.Log ("Starting Generating Cells in the BuildGraph, Max is: " + Max); //Convert Voronoi to Cells for (int j =0; j < Sites_World.Length; j++) { Vector v = Sites_World [j]; Cell c = new Cell (v); c.max = Max; c.border = false; List<VoronoiEdge> currentBorders = new List<VoronoiEdge> (); // Find Cell VoronoiEdges foreach (VoronoiEdge edge in Graph_World.Edges) { if (edge.LeftData == v || edge.RightData == v) { if (edge.IsInfinite) { c.IsBorder (); Vector AdjustedVec = edge.FixedPoint; edge.VVertexA = AdjustedVec; edge.VVertexB = AdjustedVec + (edge.DirectionVector * InfinityLength); } else if (edge.IsPartlyInfinite) { c.IsBorder (); Vector AdjustedVec = edge.FixedPoint; if (edge.VVertexA == Fortune.VVInfinite) { edge.VVertexA = AdjustedVec; } if (edge.VVertexB == Fortune.VVInfinite) { edge.VVertexB = AdjustedVec; } } BorderCellMax = Max - Border; BorderCellMin = Border; if (edge.VVertexA [0] < BorderCellMin || edge.VVertexA [0] > BorderCellMax || edge.VVertexA [1] < BorderCellMin || edge.VVertexA [1] > BorderCellMax || edge.VVertexB [0] < BorderCellMin || edge.VVertexB [0] > BorderCellMax || edge.VVertexB [1] < BorderCellMin || edge.VVertexB [1] > BorderCellMax) { c.IsBorder (); } if (!currentBorders.Contains (edge)) { currentBorders.Add (edge); } if (!c.neighborCells.Contains (edge.RightData)) { c.neighborCells.Add (edge.RightData); } } else if (edge.RightData == v) { if (!c.neighborCells.Contains (edge.LeftData)) { c.neighborCells.Add (edge.LeftData); } } } c.voronoiEdges = currentBorders; CellGraph.Add (v, c); } } //TODO make exceptions to handle errors during graph creation. if (CellGraph.Count > 0) { return true; } else { return false; } }
public void Restart () { // Reset the System Random seed. r = new System.Random (Seed); Sites_World = null; Graph_World = null; CellGraph.Clear (); }
// Lloyd Relax the points here to get more even distribution. // First we need to know the N number of Voronoi Verts that make up each cell. // Then we can find the centroid of each of those cells, and move the Site that created this cell to that centroid. public Vector[] LloydRelax (Vector[] sites, VoronoiGraph graph) { List<Vector> RelaxedSites = new List<Vector> (); for (int s =0; s < sites.Length; s++) { List<Vector> cellVerts = new List<Vector> (); foreach (VoronoiEdge edge in graph.Edges) { if (edge.LeftData == sites [s]) { // Check if one or more of the edge verts is infinity if (edge.IsPartlyInfinite) { if (edge.VVertexA == Fortune.VVInfinite) { edge.VVertexA = (edge.FixedPoint + (edge.DirectionVector * InfinityLength)); } if (edge.VVertexB == Fortune.VVInfinite) { edge.VVertexB = (edge.FixedPoint + (edge.DirectionVector * InfinityLength)); } } edge.Clamp (Border, Max - Border); cellVerts.Add (edge.VVertexA); cellVerts.Add (edge.VVertexB); } // If we didn't find a LeftData for this edge just put that site back uncentered. Vector centroid = sites [s]; if (cellVerts.Count > 0) { centroid = math_utilities.Compute2DPolygonCentroid (cellVerts); centroid.Clamp (Border, Max - Border);// lets hope this works better. } if (!RelaxedSites.Contains (centroid)) { RelaxedSites.Add (centroid); } } } return RelaxedSites.ToArray (); }
public static VoronoiGraph FilterVG(VoronoiGraph VG, double minLeftRightDist) { VoronoiGraph VGErg = new VoronoiGraph(); foreach(VoronoiEdge VE in VG.Edges) { if(Math.Sqrt(Vector.Dist(VE.LeftData,VE.RightData))>=minLeftRightDist) VGErg.Edges.Add(VE); } foreach(VoronoiEdge VE in VGErg.Edges) { VGErg.Vertizes.Add(VE.VVertexA); VGErg.Vertizes.Add(VE.VVertexB); } return VGErg; }
private void Canvas1_OnMouseDown(object sender, MouseButtonEventArgs e) { var rand = new Random(); var result = new List<int>(); var check = new HashSet<int>(); for (int i = 0; i < 2000; i++) { Int32 curValue = rand.Next(0, 4000); while (check.Contains(curValue)) { curValue = rand.Next(0, 4000); } result.Add(curValue); check.Add(curValue); } //generate points inside our rectangle for our voronoi generator var datapointlist = new List<Vector>(); for (int i = 0; i < 1000; i++) { datapointlist.Add(new Vector(result[i],result[i+1000])); } IEnumerable<Vector> datapoints = datapointlist; var vgraph = new VoronoiGraph(); vgraph = Fortune.ComputeVoronoiGraph(datapoints); foreach (var vertex in vgraph.Vertizes) { } var R = 0; var G = 0; var B = 0; foreach (var edge in vgraph.Edges) { if (R < 255) R++; if (R == 255 && G < 255) G++; if (R == 255 && G == 255 && B < 255) B++; var brush = new SolidColorBrush(Color.FromArgb(255, (byte)R, (byte)G, (byte)B)); var poly = new Line() { X1 = edge.LeftData[0], Y1 = edge.LeftData[1], X2 = edge.RightData[0], Y2 = edge.RightData[1], Stroke = brush, StrokeThickness = 1 }; canvas1.Children.Add(poly); canvas1.InvalidateVisual(); canvas1.UpdateLayout(); } }
public static VNode ProcessCircleEvent(VCircleEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList) { VDataNode a, b, c; VEdgeNode eu, eo; b = e.NodeN; a = VNode.LeftDataNode(b); c = VNode.RightDataNode(b); if (a == null || b.Parent == null || c == null || !a.DataPoint.Equals(e.NodeL.DataPoint) || !c.DataPoint.Equals(e.NodeR.DataPoint)) { CircleCheckList = new VDataNode[] {}; return(Root); // Abbruch da sich der Graph verändert hat } eu = (VEdgeNode)b.Parent; CircleCheckList = new VDataNode[] { a, c }; //1. Create the new Vertex Vector VNew = new Vector(e.Center[0], e.Center[1]); // VNew[0] = Fortune.ParabolicCut(a.DataPoint[0],a.DataPoint[1],c.DataPoint[0],c.DataPoint[1],ys); // VNew[1] = (ys + a.DataPoint[1])/2 - 1/(2*(ys-a.DataPoint[1]))*(VNew[0]-a.DataPoint[0])*(VNew[0]-a.DataPoint[0]); VG.Vertices.Add(VNew); //2. Find out if a or c are in a distand part of the tree (the other is then b's sibling) and assign the new vertex if (eu.Left == b) // c is sibling { eo = VNode.EdgeToRightDataNode(a); // replace eu by eu's Right eu.Parent.Replace(eu, eu.Right); } else // a is sibling { eo = VNode.EdgeToRightDataNode(b); // replace eu by eu's Left eu.Parent.Replace(eu, eu.Left); } eu.Edge.AddVertex(VNew); // ///////////////////// uncertain // if(eo==eu) // return Root; // ///////////////////// //complete & cleanup eo eo.Edge.AddVertex(VNew); //while(eo.Edge.VVertexB == Fortune.VVUnkown) //{ // eo.Flipped = !eo.Flipped; // eo.Edge.AddVertex(Fortune.VVInfinite); //} //if(eo.Flipped) //{ // Vector T = eo.Edge.LeftData; // eo.Edge.LeftData = eo.Edge.RightData; // eo.Edge.RightData = T; //} //2. Replace eo by new Edge VoronoiEdge VE = new VoronoiEdge(); VE.LeftData = a.DataPoint; VE.RightData = c.DataPoint; VE.AddVertex(VNew); VG.Edges.Add(VE); VEdgeNode VEN = new VEdgeNode(VE, false); VEN.Left = eo.Left; VEN.Right = eo.Right; if (eo.Parent == null) { return(VEN); } eo.Parent.Replace(eo, VEN); return(Root); }
private void AddEdges (VoronoiGraph g) { foreach (VoronoiEdge e in g.Edges) { if (EdgeBelongsToTile(e)) { AddEdge(e); } } }
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); }
public VoronoiGraph RefineGraph(VoronoiGraph g) { // Removes out of bound edges from a graph VoronoiGraph VGErg = new VoronoiGraph(); foreach(VoronoiEdge e in g.Edges) { if (EdgeInBounds(e)) { VGErg.Edges.Add(e); } } foreach(VoronoiEdge VE in VGErg.Edges) { VGErg.Vertizes.Add(VE.VVertexA); VGErg.Vertizes.Add(VE.VVertexB); } return VGErg; }
public void GenerateGraph () { Random.seed = seed; islandNoise = world.GetNoiseAt(islandPosition); cellVectors = RandomVectorList(voronoiCells); vGraph = GenerateRelaxedGraph(cellVectors, relaxationIterations-1); }
void Reset () { islandGenerated = false; islandTiles = null; vGraph = null; subIslands = null; cellVectors = null; }
private void ImproveMapData(VoronoiGraph voronoiMap, bool fix = false) { IFactory fact = new MapItemFactory(); foreach (VoronoiEdge edge in voronoiMap.Edges) { if (fix) { if (!FixPoints(edge)) continue; } Corner c1 = fact.CornerFactory(edge.VVertexA[0], edge.VVertexA[1]); Corner c2 = fact.CornerFactory(edge.VVertexB[0], edge.VVertexB[1]); Center cntrLeft = fact.CenterFactory(edge.LeftData[0], edge.LeftData[1]); Center cntrRight = fact.CenterFactory(edge.RightData[0], edge.RightData[1]); if(c1 == null || c2 == null) { } c1.AddAdjacent(c2); c2.AddAdjacent(c1); cntrRight.Corners.Add(c1); cntrRight.Corners.Add(c2); cntrLeft.Corners.Add(c1); cntrLeft.Corners.Add(c2); Edge e = fact.EdgeFactory(c1, c2, cntrLeft, cntrRight); cntrLeft.Borders.Add(e); cntrRight.Borders.Add(e); cntrLeft.Neighbours.Add(cntrRight); cntrRight.Neighbours.Add(cntrLeft); c1.AddProtrudes(e); c2.AddProtrudes(e); c1.AddTouches(cntrLeft); c1.AddTouches(cntrRight); c2.AddTouches(cntrLeft); c2.AddTouches(cntrRight); } foreach (Corner q in App.AppMap.Corners.Values) { if (!q.Border) { var point = new Point(0, 0); foreach (Center c in q.Touches) { point.X += c.Point.X; point.Y += c.Point.Y; } point.X = point.X / q.Touches.Count; point.Y = point.Y / q.Touches.Count; q.Point = point; } } //foreach (var c in App.AppMap.Centers) //{ // c.Value.FixBorders(); // c.SetEdgeAreas(); // c.Value.OrderCorners(); //} IslandHandler.CreateIsland(); }
public IslandTile (Vector c, VoronoiGraph g, Island isl) { island = isl; center = c; AddEdges(g); }
/// <summary> /// Will return the new root (unchanged except in start-up) /// </summary> public static VNode ProcessDataEvent(VDataEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList) { if(Root==null) { Root = new VDataNode(e.DataPoint); CircleCheckList = new VDataNode[] {(VDataNode)Root}; return Root; } //1. Find the node to be replaced VNode C = VNode.FindDataNode(Root, ys, e.DataPoint[0]); //2. Create the subtree (ONE Edge, but two VEdgeNodes) VoronoiEdge VE = new VoronoiEdge(); VE.LeftData = ((VDataNode)C).DataPoint; VE.RightData = e.DataPoint; VE.VVertexA = Fortune.VVUnkown; VE.VVertexB = Fortune.VVUnkown; VG.Edges.Add(VE); VNode SubRoot; if(Math.Abs(VE.LeftData[1]-VE.RightData[1])<1e-10) { if(VE.LeftData[0]<VE.RightData[0]) { SubRoot = new VEdgeNode(VE,false); SubRoot.Left = new VDataNode(VE.LeftData); SubRoot.Right = new VDataNode(VE.RightData); } else { SubRoot = new VEdgeNode(VE,true); SubRoot.Left = new VDataNode(VE.RightData); SubRoot.Right = new VDataNode(VE.LeftData); } CircleCheckList = new VDataNode[] {(VDataNode)SubRoot.Left,(VDataNode)SubRoot.Right}; } else { SubRoot = new VEdgeNode(VE,false); SubRoot.Left = new VDataNode(VE.LeftData); SubRoot.Right = new VEdgeNode(VE,true); SubRoot.Right.Left = new VDataNode(VE.RightData); SubRoot.Right.Right = new VDataNode(VE.LeftData); CircleCheckList = new VDataNode[] {(VDataNode)SubRoot.Left,(VDataNode)SubRoot.Right.Left,(VDataNode)SubRoot.Right.Right}; } //3. Apply subtree if(C.Parent == null) return SubRoot; C.Parent.Replace(C,SubRoot); return Root; }
private void ImproveMapData(VoronoiGraph voronoiMap, bool fix = false) { IFactory fact = new MapItemFactory(); foreach (VoronoiEdge edge in voronoiMap.Edges) { if (fix) { if (!newFix(edge)) continue; } Corner c1 = fact.CornerFactory(edge.VVertexA[0], edge.VVertexA[1]); Corner c2 = fact.CornerFactory(edge.VVertexB[0], edge.VVertexB[1]); Center cntrLeft = fact.CenterFactory(edge.LeftData[0], edge.LeftData[1]); Center cntrRight = fact.CenterFactory(edge.RightData[0], edge.RightData[1]); c1.AddAdjacent(c2); c2.AddAdjacent(c1); cntrRight.AddCorner(c1); cntrRight.AddCorner(c2); cntrLeft.AddCorner(c1); cntrLeft.AddCorner(c2); Edge e = fact.EdgeFactory(c1, c2, cntrLeft, cntrRight); cntrLeft.AddBorder(e); cntrRight.AddBorder(e); cntrLeft.AddNeighbour(cntrRight); cntrRight.AddNeighbour(cntrLeft); c1.AddProtrudes(e); c2.AddProtrudes(e); c1.AddTouches(cntrLeft); c1.AddTouches(cntrRight); c2.AddTouches(cntrLeft); c2.AddTouches(cntrRight); } foreach (var c in App.AppMap.Centers) { c.Value.FixBorders(); //c.SetEdgeAreas(); c.Value.OrderCorners(); } //IslandHandler.CreateIsland(); }
public static VNode ProcessCircleEvent(VCircleEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList) { VDataNode a,b,c; VEdgeNode eu,eo; b = e.NodeN; a = VNode.LeftDataNode(b); c = VNode.RightDataNode(b); if(a==null || b.Parent==null || c==null || !a.DataPoint.Equals(e.NodeL.DataPoint) || !c.DataPoint.Equals(e.NodeR.DataPoint)) { CircleCheckList = new VDataNode[]{}; return Root; // Abbruch da sich der Graph verändert hat } eu = (VEdgeNode)b.Parent; CircleCheckList = new VDataNode[] {a,c}; //1. Create the new Vertex Vector VNew = new Vector(e.Center[0],e.Center[1]); // VNew[0] = Fortune.ParabolicCut(a.DataPoint[0],a.DataPoint[1],c.DataPoint[0],c.DataPoint[1],ys); // VNew[1] = (ys + a.DataPoint[1])/2 - 1/(2*(ys-a.DataPoint[1]))*(VNew[0]-a.DataPoint[0])*(VNew[0]-a.DataPoint[0]); VG.Vertizes.Add(VNew); //2. Find out if a or c are in a distand part of the tree (the other is then b's sibling) and assign the new vertex if(eu.Left==b) // c is sibling { eo = VNode.EdgeToRightDataNode(a); // replace eu by eu's Right eu.Parent.Replace(eu,eu.Right); } else // a is sibling { eo = VNode.EdgeToRightDataNode(b); // replace eu by eu's Left eu.Parent.Replace(eu,eu.Left); } eu.Edge.AddVertex(VNew); // ///////////////////// uncertain // if(eo==eu) // return Root; // ///////////////////// //complete & cleanup eo eo.Edge.AddVertex(VNew); //while(eo.Edge.VVertexB == Fortune.VVUnkown) //{ // eo.Flipped = !eo.Flipped; // eo.Edge.AddVertex(Fortune.VVInfinite); //} //if(eo.Flipped) //{ // Vector T = eo.Edge.LeftData; // eo.Edge.LeftData = eo.Edge.RightData; // eo.Edge.RightData = T; //} //2. Replace eo by new Edge VoronoiEdge VE = new VoronoiEdge(); VE.LeftData = a.DataPoint; VE.RightData = c.DataPoint; VE.AddVertex(VNew); VG.Edges.Add(VE); VEdgeNode VEN = new VEdgeNode(VE, false); VEN.Left = eo.Left; VEN.Right = eo.Right; if(eo.Parent == null) return VEN; eo.Parent.Replace(eo,VEN); return Root; }
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; } } } 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; }