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); }
/// <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 void Reset() { GL.Enable(EnableCap.LineSmooth); GL.Enable(EnableCap.PolygonSmooth); // GL.Enable(EnableCap.DepthTest); Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY); GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref modelview); int seeds = 1280; int extraSeeds = 512; Vector[] points = new Vector[seeds + extraSeeds]; double thetaOffset = Tau / 4; for (int i = 0; i < seeds + extraSeeds; i++) { double theta = (double)(i + 1) * Tau / Phi; double r = Math.Sqrt(i+1); double x = (r) * Math.Cos(theta + thetaOffset); double y = (r) * Math.Sin(theta + thetaOffset); points[i] = new Vector(new double[] { x, y }); } VoronoiGraph graph = Fortune.ComputeVoronoiGraph(points); cells = new SortedDictionary<Vector, List<VoronoiEdge>>(); foreach (VoronoiEdge edge in graph.Edges) { if (double.IsNaN(edge.VVertexA.X) || double.IsNaN(edge.VVertexA.Y) || double.IsNaN(edge.VVertexB.X) || double.IsNaN(edge.VVertexB.Y) ) continue; if (!cells.ContainsKey(edge.LeftData)) cells[edge.LeftData] = new List<VoronoiEdge>(); cells[edge.LeftData].Add(edge); if (!cells.ContainsKey(edge.RightData)) cells[edge.RightData] = new List<VoronoiEdge>(); cells[edge.RightData].Add(edge); Complex pA = new Complex(edge.VVertexA.X, edge.VVertexA.Y); Complex pB = new Complex(edge.VVertexB.X, edge.VVertexB.Y); int sampleCount = 2; Complex[] samples = new Complex[sampleCount]; samples[0] = pA; samples[sampleCount - 1] = pB; for (int i = 1; i < sampleCount - 1; i++) { double ratio = (double)i / sampleCount; samples[i] = pA * (1 - ratio) + pB * ratio; } } for (int i = 0; i < seeds; i++) { Queue<VoronoiEdge> edges = new Queue<VoronoiEdge>(cells.Values.ElementAt(i)); var firstEdge = edges.Dequeue(); List<Complex> polygonPoints = new List<Complex>(); polygonPoints.Add(new Complex(firstEdge.VVertexA.X * scale, firstEdge.VVertexA.Y * scale)); polygonPoints.Add(new Complex(firstEdge.VVertexB.X * scale, firstEdge.VVertexB.Y * scale)); while (edges.Count > 0) { var edge = edges.Dequeue(); Complex pA = new Complex(edge.VVertexA.X * scale, edge.VVertexA.Y * scale); Complex pB = new Complex(edge.VVertexB.X * scale, edge.VVertexB.Y * scale); if (polygonPoints[0] == pA) { polygonPoints.Insert(0, pB); continue; } if (polygonPoints[0] == pB) { polygonPoints.Insert(0, pA); continue; } if (polygonPoints[polygonPoints.Count - 1] == pA) { polygonPoints.Add(pB); continue; } if (polygonPoints[polygonPoints.Count - 1] == pB) { polygonPoints.Add(pA); continue; } edges.Enqueue(edge); } polygons.Add(polygonPoints); } for (int i = 0; i <= ModuloActor.MaxMod; i++) ModuloActor.Maps[i] = CreateIndexMap(i, cells); actors[0] = new ModuloActor(21, 0 / 3, new Color4(1f, 0.5f, 0.5f, 1f)); actors[1] = new ModuloActor(13, 1 / 3, new Color4(0.5f, 1f, 0.5f, 1f)); actors[2] = new ModuloActor(0, 2 / 3, new Color4(0.5f, 0.5f, 1f, 1f)); ModuloActor.AnnounceFibonaccis(); }
public Vector[] GenerateRandom (int seed, double numPoints, double min, double max) { //Debug.Log ("Starting to Generate Random Numbers, Max is: " + max); List<Vector> tempList = new List<Vector> (); UnityEngine.Random.seed = seed; Vector p; while (tempList.Count < numPoints) { p = new Vector (UnityEngine.Random.Range ((int)min, (int)max), UnityEngine.Random.Range ((int)min, (int)max)); if (!tempList.Contains (p)) { tempList.Add (p); } } return tempList.ToArray (); }
public static VoronoiGraph ComputeVoronoiGraph (Vector[] 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)); } Profiler.BeginSample ("Fortune Compute VoronoiGraph While PQ.Count > 0"); 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; Profiler.BeginSample ("DIST Function"); 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; } Profiler.EndSample (); } } Profiler.EndSample (); VNode.CleanUpTree (RootNode); foreach (VoronoiEdge VE in VG.Edges) { if (VE.Done) continue; if (VE.VVertexB == Fortune.VVUnkown) { VE.AddVertex (Fortune.VVInfinite); Profiler.BeginSample ("Infinite Function"); 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; } Profiler.EndSample (); } } 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 VDataEvent(Vector DP) { this.DataPoint = DP; }
public VDataNode(Vector DP) { this.DataPoint = DP; }
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 Cell (Vector Site) { site = Site; Reset (); }
/// <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(); } }
// 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 (); }
/// <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) { }
public static Vector operator / (Vector A, double B) { Vector Erg = new Vector(A.Dim); for (int i = 0; i < A.Dim; i++) { Erg[i] = A[i] / B; } return Erg; }