//Generate the voronoi diagram using an external library public VoronoiDiagram GetVoronoi(List<Point> points) { _siteCells = new Dictionary<Point, Cell>(); var nrPoints = points.Count; var dataPoints = new Vector[nrPoints]; for (int i = 0; i < nrPoints; i++) { var point = points[i]; if (_siteCells.ContainsKey(point)) continue; dataPoints[i] = new Vector(point.X,point.Y); var cell = new Cell {SitePoint = point}; _siteCells.Add(point, cell); } //Create Voronoi Data using library var data = Fortune.ComputeVoronoiGraph(dataPoints); //data = BenTools.Mathematics.Fortune.FilterVG(data, 15); //Create Diagram _voronoi = new VoronoiDiagram(); _voronoi.HalfEdges = GenerateLines(data); _voronoi.VoronoiCells = GenerateCells(data); _voronoi.Sites = points; return _voronoi; }
/// <summary> /// Build a new vector as a copy of an existing one /// </summary> /// <param name="O">The existing vector</param> public Vector(Vector O) : this(O.data) { }
/// <summary> /// Reset all elements with ransom values from the given range /// </summary> /// <param name="MinMax">MinMax[0] - Min /// MinMax[1] - Max</param> public void Randomize(Vector[] MinMax) { int i; for(i=0;i<data.Length;i++) { this[i] = MinMax[0][i] + (MinMax[1][i]-MinMax[0][i])*MathTools.R.NextDouble(); } }
/// <summary> /// Add another vector /// </summary> /// <param name="V">V</param> public void Add(Vector V) { int i; for(i=0;i<data.Length;i++) { this[i] += V[i]; } }
/// <summary> /// Get the distance of two vectors /// </summary> public static double Dist(Vector V1, Vector V2) { if(V1.Dim != V2.Dim) return -1; int i; double E = 0,D; for(i=0;i<V1.Dim;i++) { D=(V1[i]-V2[i]); E+=D*D; } return E; }
/// <summary> /// Subtract two vectors /// </summary> public static Vector operator -(Vector A, Vector B) { if(A.Dim!=B.Dim) throw new Exception("Vectors of different dimension!"); Vector Erg = new Vector(A.Dim); int i; for(i=0;i<A.Dim;i++) Erg[i]=A[i]-B[i]; return Erg; }
/// <summary> /// Scale one vector /// </summary> public static Vector operator *(Vector A, double B) { Vector Erg = new Vector(A.Dim); int i; for(i=0;i<A.Dim;i++) Erg[i]=A[i]*B; return Erg; }
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 VDataNode(Vector DP) { this.DataPoint = DP; }
public VDataEvent(Vector DP) { this.DataPoint = DP; }
public void AddVertex(Vector V) { if(VVertexA==Fortune.VVUnkown) VVertexA = V; else if(VVertexB==Fortune.VVUnkown) VVertexB = V; else throw new Exception("Tried to add third vertex!"); }
internal static Vector CircumCircleCenter(Vector A, Vector B, Vector C) { if(A==B || B==C || A==C) throw new Exception("Need three different points!"); double tx = (A[0] + C[0])/2; double ty = (A[1] + C[1])/2; double vx = (B[0] + C[0])/2; double vy = (B[1] + C[1])/2; double ux,uy,wx,wy; if(A[0] == C[0]) { ux = 1; uy = 0; } else { ux = (C[1] - A[1])/(A[0] - C[0]); uy = 1; } if(B[0] == C[0]) { wx = -1; wy = 0; } else { wx = (B[1] - C[1])/(B[0] - C[0]); wy = -1; } double alpha = (wy*(vx-tx)-wx*(vy - ty))/(ux*wy-wx*uy); return new Vector(tx+alpha*ux,ty+alpha*uy); }