/* * This is the only way to create a new Edge * @param site0 * @param site1 * @return */ public static Edge CreateBisectingEdge(Site s0, Site s1) { float dx, dy; float absdx, absdy; float a, b, c; dx = s1.x - s0.x; dy = s1.y - s0.y; absdx = dx > 0 ? dx : -dx; absdy = dy > 0 ? dy : -dy; c = s0.x * dx + s0.y * dy + (dx*dx + dy*dy) * 0.5f; if (absdx > absdy) { a = 1; b = dy/dx; c /= dx; } else { b = 1; a = dx/dy; c/= dy; } Edge edge = Edge.Create(); edge.LeftSite = s0; edge.RightSite = s1; s0.AddEdge(edge); s1.AddEdge(edge); edge.a = a; edge.b = b; edge.c = c; return edge; }
public static int CompareByYThenX(Site s1, Vector2f s2) { if (s1.y < s2.Y) return -1; if (s1.y > s2.Y) return 1; if (s1.x < s2.X) return -1; if (s1.x > s2.X) return 1; return 0; }
public static int CompareByYThenX(Site s1, Site s2) { if (s1.y < s2.y) return -1; if (s1.y > s2.y) return 1; if (s1.x < s2.x) return -1; if (s1.x > s2.x) return 1; return 0; }
public int CompareTo(Site s1) { int returnValue = Voronoi.CompareByYThenX(this,s1); int tempIndex; if (returnValue == -1) { if (this.siteIndex > s1.SiteIndex) { tempIndex = this.SiteIndex; this.SiteIndex = s1.SiteIndex; s1.SiteIndex = tempIndex; } } else if (returnValue == 1) { if (s1.SiteIndex > this.SiteIndex) { tempIndex = s1.SiteIndex; s1.SiteIndex = this.SiteIndex; this.SiteIndex = tempIndex; } } return returnValue; }
public Polygon(Site site) { const float eps = 0.001f; var newVertices = new List<Vector2>(site.Edges.Count + 1); foreach (var edge in site.Edges) { if (edge.ClippedEnds == null) return; var p0 = edge.ClippedEnds[LR.LEFT]; var p1 = edge.ClippedEnds[LR.RIGHT]; var begin = new Vector2(p0.x, p0.y); var end = new Vector2(p1.x, p1.y); bool hasBegin = false; bool hasEnd = false; foreach (var point in newVertices) { if ((point - begin).sqrMagnitude < eps) { hasBegin = true; } if ((point - end).sqrMagnitude < eps) { hasEnd = true; } } if (!hasBegin) newVertices.Add(begin); if (!hasEnd) newVertices.Add(end); } Vertices = newVertices; }
public int Add(Site site) { sorted = false; sites.Add(site); return sites.Count; }
private Site RightRegion(Halfedge he, Site bottomMostSite) { Edge edge = he.edge; if (edge == null) { return bottomMostSite; } return edge.Site(LR.Other(he.leftRight)); }
public Triangle(Site a, Site b, Site c) { sites = new List<Site>(); sites.Add(a); sites.Add(b); sites.Add(c); }
public void LloydRelaxation(int nbIterations) { // Reapeat the whole process for the number of iterations asked for (int i = 0; i < nbIterations; i++) { List <Vector2f> newPoints = new List <Vector2f>(); // Go thourgh all sites sites.ResetListIndex(); Site site = sites.Next(); while (site != null) { // Loop all corners of the site to calculate the centroid List <Vector2f> region = site.Region(plotBounds); if (region.Count < 1) { site = sites.Next(); continue; } Vector2f centroid = Vector2f.zero; float signedArea = 0; float x0 = 0; float y0 = 0; float x1 = 0; float y1 = 0; float a = 0; // For all vertices except last for (int j = 0; j < region.Count - 1; j++) { x0 = region[j].x; y0 = region[j].y; x1 = region[j + 1].x; y1 = region[j + 1].y; a = x0 * y1 - x1 * y0; signedArea += a; centroid.x += (x0 + x1) * a; centroid.y += (y0 + y1) * a; } // Do last vertex x0 = region[region.Count - 1].x; y0 = region[region.Count - 1].y; x1 = region[0].x; y1 = region[0].y; a = x0 * y1 - x1 * y0; signedArea += a; centroid.x += (x0 + x1) * a; centroid.y += (y0 + y1) * a; signedArea *= 0.5f; centroid.x /= (6 * signedArea); centroid.y /= (6 * signedArea); // Move site to the centroid of its Voronoi cell newPoints.Add(centroid); site = sites.Next(); } // Between each replacement of the cendroid of the cell, // we need to recompute Voronoi diagram: Rectf origPlotBounds = this.plotBounds; Dispose(); Init(newPoints, origPlotBounds); } }
private void FortunesAlgorithm() { Site newSite, bottomSite, topSite, tempSite; Vertex v, vertex; Vector2f newIntStar = Vector2f.zero; LR leftRight; Halfedge lbnd, rbnd, llbnd, rrbnd, bisector; Edge edge; Rectf dataBounds = sites.GetSitesBounds(); int sqrtSitesNb = (int)Math.Sqrt(sites.Count() + 4); HalfedgePriorityQueue heap = new HalfedgePriorityQueue(dataBounds.y, dataBounds.height, sqrtSitesNb); EdgeList edgeList = new EdgeList(dataBounds.x, dataBounds.width, sqrtSitesNb); List <Halfedge> halfEdges = new List <Halfedge>(); List <Vertex> vertices = new List <Vertex>(); Site bottomMostSite = sites.Next(); newSite = sites.Next(); while (true) { if (!heap.Empty()) { newIntStar = heap.Min(); } if (newSite != null && (heap.Empty() || CompareByYThenX(newSite, newIntStar) < 0)) { // New site is smallest //Debug.Log("smallest: new site " + newSite); // Step 8: lbnd = edgeList.EdgeListLeftNeighbor(newSite.Coord); // The halfedge just to the left of newSite //UnityEngine.Debug.Log("lbnd: " + lbnd); rbnd = lbnd.edgeListRightNeighbor; // The halfedge just to the right //UnityEngine.Debug.Log("rbnd: " + rbnd); bottomSite = RightRegion(lbnd, bottomMostSite); // This is the same as leftRegion(rbnd) // This Site determines the region containing the new site //UnityEngine.Debug.Log("new Site is in region of existing site: " + bottomSite); // Step 9 edge = Edge.CreateBisectingEdge(bottomSite, newSite); //UnityEngine.Debug.Log("new edge: " + edge); Edges.Add(edge); bisector = Halfedge.Create(edge, LR.LEFT); halfEdges.Add(bisector); // Inserting two halfedges into edgelist constitutes Step 10: // Insert bisector to the right of lbnd: edgeList.Insert(lbnd, bisector); // First half of Step 11: if ((vertex = Vertex.Intersect(lbnd, bisector)) != null) { vertices.Add(vertex); heap.Remove(lbnd); lbnd.vertex = vertex; lbnd.ystar = vertex.y + newSite.Dist(vertex); heap.Insert(lbnd); } lbnd = bisector; bisector = Halfedge.Create(edge, LR.RIGHT); halfEdges.Add(bisector); // Second halfedge for Step 10:: // Insert bisector to the right of lbnd: edgeList.Insert(lbnd, bisector); // Second half of Step 11: if ((vertex = Vertex.Intersect(bisector, rbnd)) != null) { vertices.Add(vertex); bisector.vertex = vertex; bisector.ystar = vertex.y + newSite.Dist(vertex); heap.Insert(bisector); } newSite = sites.Next(); } else if (!heap.Empty()) { // Intersection is smallest lbnd = heap.ExtractMin(); llbnd = lbnd.edgeListLeftNeighbor; rbnd = lbnd.edgeListRightNeighbor; rrbnd = rbnd.edgeListRightNeighbor; bottomSite = LeftRegion(lbnd, bottomMostSite); topSite = RightRegion(rbnd, bottomMostSite); // These three sites define a Delaunay triangle // (not actually using these for anything...) // triangles.Add(new Triangle(bottomSite, topSite, RightRegion(lbnd, bottomMostSite))); v = lbnd.vertex; v.SetIndex(); lbnd.edge.SetVertex(lbnd.leftRight, v); rbnd.edge.SetVertex(rbnd.leftRight, v); edgeList.Remove(lbnd); heap.Remove(rbnd); edgeList.Remove(rbnd); leftRight = LR.LEFT; if (bottomSite.Y > topSite.Y) { tempSite = bottomSite; bottomSite = topSite; topSite = tempSite; leftRight = LR.RIGHT; } edge = Edge.CreateBisectingEdge(bottomSite, topSite); Edges.Add(edge); bisector = Halfedge.Create(edge, leftRight); halfEdges.Add(bisector); edgeList.Insert(llbnd, bisector); edge.SetVertex(LR.Other(leftRight), v); if ((vertex = Vertex.Intersect(llbnd, bisector)) != null) { vertices.Add(vertex); heap.Remove(llbnd); llbnd.vertex = vertex; llbnd.ystar = vertex.y + bottomSite.Dist(vertex); heap.Insert(llbnd); } if ((vertex = Vertex.Intersect(bisector, rrbnd)) != null) { vertices.Add(vertex); bisector.vertex = vertex; bisector.ystar = vertex.y + bottomSite.Dist(vertex); heap.Insert(bisector); } } else { break; } } // Heap should be empty now heap.Dispose(); edgeList.Dispose(); foreach (Halfedge halfedge in halfEdges) { halfedge.ReallyDispose(); } halfEdges.Clear(); // we need the vertices to clip the edges foreach (Edge e in Edges) { e.ClipVertices(plotBounds); } // But we don't actually ever use them again! foreach (Vertex ve in vertices) { ve.Dispose(); } vertices.Clear(); }
public int Compare(Site s1, Site s2) { return(s1.CompareTo(s2)); }
public int Compare(Site s1, Site s2) { return s1.CompareTo(s2); }