private Halfedge Init(Edge edge, LR lr) { this.edge = edge; leftRight = lr; nextInPriorityQueue = null; vertex = null; return this; }
public void ReallyDispose() { edgeListLeftNeighbor = null; edgeListRightNeighbor = null; nextInPriorityQueue = null; edge = null; leftRight = null; vertex = null; pool.Enqueue(this); }
public void Dispose() { Halfedge halfedge = leftEnd; Halfedge prevHe; while (halfedge != rightEnd) { prevHe = halfedge; halfedge = halfedge.edgeListRightNeighbor; prevHe.Dispose(); } leftEnd = null; rightEnd.Dispose(); rightEnd = null; hash = null; }
public void Remove(Halfedge halfedge) { Halfedge previous; int removalBucket = Bucket(halfedge); if (halfedge.vertex != null) { previous = hash[removalBucket]; while (previous.nextInPriorityQueue != halfedge) { previous = previous.nextInPriorityQueue; } previous.nextInPriorityQueue = halfedge.nextInPriorityQueue; count--; halfedge.vertex = null; halfedge.nextInPriorityQueue = null; halfedge.Dispose(); } }
public void Insert(Halfedge halfedge) { Halfedge previous, next; int insertionBucket = Bucket(halfedge); if (insertionBucket < minBucked) { minBucked = insertionBucket; } previous = hash[insertionBucket]; while ((next = previous.nextInPriorityQueue) != null && (halfedge.ystar > next.ystar || (halfedge.ystar == next.ystar && halfedge.vertex.x > next.vertex.x))) { previous = next; } halfedge.nextInPriorityQueue = previous.nextInPriorityQueue; previous.nextInPriorityQueue = halfedge; count++; }
public EdgeList(float xmin, float deltaX, int sqrtSitesNb) { this.xmin = xmin; this.deltaX = deltaX; hashSize = 2 * sqrtSitesNb; hash = new Halfedge[hashSize]; // Two dummy Halfedges: leftEnd = Halfedge.CreateDummy(); rightEnd = Halfedge.CreateDummy(); leftEnd.edgeListLeftNeighbor = null; leftEnd.edgeListRightNeighbor = rightEnd; rightEnd.edgeListLeftNeighbor = leftEnd; rightEnd.edgeListRightNeighbor = null; hash[0] = leftEnd; hash[hashSize - 1] = rightEnd; }
/* * This is the only way to make a Vertex * * @param halfedge0 * @param halfedge1 * @return * */ public static Vertex Intersect(Halfedge halfedge0, Halfedge halfedge1) { Edge edge, edge0, edge1; Halfedge halfedge; float determinant, intersectionX, intersectionY; bool rightOfSite; edge0 = halfedge0.edge; edge1 = halfedge1.edge; if (edge0 == null || edge1 == null) { return null; } if (edge0.RightSite == edge1.RightSite) { return null; } determinant = edge0.a * edge1.b - edge0.b * edge1.a; if (Math.Pow(-1.0, 10) < determinant && determinant < Math.Pow(1.0, -10)) { // The edges are parallel return null; } intersectionX = (edge0.c * edge1.b - edge1.c * edge0.b)/determinant; intersectionY = (edge1.c * edge0.a - edge0.c * edge1.a)/determinant; if (Voronoi.CompareByYThenX(edge0.RightSite, edge1.RightSite) < 0) { halfedge = halfedge0; edge = edge0; } else { halfedge = halfedge1; edge = edge1; } rightOfSite = intersectionX >= edge.RightSite.x; if ((rightOfSite && halfedge.leftRight == LR.LEFT) || (!rightOfSite && halfedge.leftRight == LR.RIGHT)) { return null; } return Vertex.Create(intersectionX, intersectionY); }
private int Bucket(Halfedge halfedge) { int theBucket = (int)((halfedge.ystar - ymin)/deltaY * hashSize); if (theBucket < 0) theBucket = 0; if (theBucket >= hashSize) theBucket = hashSize - 1; return theBucket; }
/* * This function only removes the Halfedge from the left-right list. * We cannot dispose it yet because we are still using it. * @param halfEdge */ public void Remove(Halfedge halfedge) { halfedge.edgeListLeftNeighbor.edgeListRightNeighbor = halfedge.edgeListRightNeighbor; halfedge.edgeListRightNeighbor.edgeListLeftNeighbor = halfedge.edgeListLeftNeighbor; halfedge.edge = Edge.DELETED; halfedge.edgeListLeftNeighbor = halfedge.edgeListRightNeighbor = null; }
/* * Insert newHalfedge to the right of lb * @param lb * @param newHalfedge */ public void Insert(Halfedge lb, Halfedge newHalfedge) { newHalfedge.edgeListLeftNeighbor = lb; newHalfedge.edgeListRightNeighbor = lb.edgeListRightNeighbor; lb.edgeListRightNeighbor.edgeListLeftNeighbor = newHalfedge; lb.edgeListRightNeighbor = newHalfedge; }
private Site RightRegion(Halfedge he, Site bottomMostSite) { Edge edge = he.edge; if (edge == null) { return bottomMostSite; } return edge.Site(LR.Other(he.leftRight)); }
private void FortunesAlgorithm() { Site newSite, bottomSite, topSite, tempSite; Vertex v, vertex; Vector2 newIntStar = Vector2.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(); }
private void FortunesAlgorithm() { Profiler.BeginSample("DAll HEs"); Halfedge.DisposeAll(); Edge.DisposeAll(); Profiler.EndSample(); //UnityEngine.Debug.Log("HE pool: " + Halfedge.unusedPool.Count); currentSiteIndex = 0; nVertices = 0; // vars Profiler.BeginSample("Fortunes: initing"); Site newSite, bottomSite, topSite, tempSite; Vertex v, vertex; Vector2f newIntStar = Vector2f.zero; bool leftRight; Halfedge lbnd = null; Halfedge rbnd = null; Halfedge llbnd = null; Halfedge rrbnd = null; Halfedge bisector = null; Edge edge; Profiler.EndSample(); // Data bounds Profiler.BeginSample("Fortunes: Getting data bounds"); Rectf dataBounds = Site.GetSitesBounds(sites); Profiler.EndSample(); int sqrtSitesNb = (int)Math.Sqrt(sites.Count + 4); // WTF Profiler.BeginSample("Fortunes: Init heap"); if (heap == null) { heap = new HalfedgePriorityQueue(dataBounds.y, dataBounds.height, sqrtSitesNb); } else { heap.ReinitNoSizeChange(dataBounds.y, dataBounds.height); } Profiler.EndSample(); Profiler.BeginSample("Fortunes: Init EdgeList"); if (edgeList == null) { edgeList = new EdgeList(dataBounds.x, dataBounds.width, sqrtSitesNb); } else { edgeList.ClearNoResize(dataBounds.x, dataBounds.width); } //edgeList = new EdgeList(dataBounds.x, dataBounds.width, sqrtSitesNb); Profiler.EndSample(); Profiler.BeginSample("Fortunes: Init HEs and vertices"); if (halfEdges == null) // TODO: Move to init { halfEdges = new List <Halfedge>(); vertices = new List <Vertex>(); } else { halfEdges.Clear(); vertices.Clear(); } Profiler.EndSample(); Site bottomMostSite = GetNextSite(); newSite = GetNextSite(); Profiler.BeginSample("Fortunes: Main Loop"); while (true) { if (heap.count > 0) { newIntStar = heap.Min(); } if (newSite != null && (heap.count == 0 || CompareByYThenX(newSite, newIntStar) < 0)) { // New site is smallest //Debug.Log("smallest: new site " + newSite); // Step 8: // The halfedge just to the left of newSite //UnityEngine.Debug.Log("lbnd: " + lbnd); lbnd = edgeList.EdgeListLeftNeighbor(newSite.Coord); // The halfedge just to the right rbnd = lbnd.edgeListRightNeighbor; //UnityEngine.Debug.Log("rbnd: " + rbnd); // This is the same as leftRegion(rbnd) // This Site determines the region containing the new site bottomSite = RightRegion(lbnd, bottomMostSite); //UnityEngine.Debug.Log("new Site is in region of existing site: " + bottomSite); // Step 9 Profiler.BeginSample("CreateBisectingEdge"); edge = Edge.CreateBisectingEdge(bottomSite, newSite); Profiler.EndSample(); //UnityEngine.Debug.Log("new edge: " + edge); Edges.Add(edge); bisector = Halfedge.Create(edge, false); 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, true); 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 = GetNextSite(); } else if (heap.count > 0) { // 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...) #if TRIANGLES triangles.Add(new Triangle(bottomSite, topSite, RightRegion(lbnd, bottomMostSite))); #endif v = lbnd.vertex; v.VertexIndex = nVertices++; lbnd.edge.SetVertex(lbnd.leftRight, v); rbnd.edge.SetVertex(rbnd.leftRight, v); edgeList.Remove(lbnd); heap.Remove(rbnd); edgeList.Remove(rbnd); leftRight = false; if (bottomSite.y > topSite.y) { tempSite = bottomSite; bottomSite = topSite; topSite = tempSite; leftRight = true; } edge = Edge.CreateBisectingEdge(bottomSite, topSite); Profiler.BeginSample("addedge"); Edges.Add(edge); Profiler.EndSample(); bisector = Halfedge.Create(edge, leftRight); halfEdges.Add(bisector); edgeList.Insert(llbnd, bisector); edge.SetVertex(!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; } } Profiler.EndSample(); // DISPOSE // Heap should be empty now Profiler.BeginSample("Fortunes: Heap dispose"); heap.Dispose(); Profiler.EndSample(); Profiler.BeginSample("Fortunes: Edgelist dispose"); edgeList.Dispose(); Profiler.EndSample(); Profiler.BeginSample("Fortunes: Halfedges REALLY dispose"); for (int i = 0; i < halfEdges.Count; i++) { halfEdges[i].ReallyDispose(); } halfEdges.Clear(); Profiler.EndSample(); Profiler.BeginSample("Fortunes: ClipVertices"); // we need the vertices to clip the edges for (int i = 0; i < Edges.Count; i++) { Edges[i].ClipVertices(PlotBounds, true); } Profiler.EndSample(); // But we don't actually ever use them again! if (!disposeVerticesManually) { Profiler.BeginSample("Vertices dispose"); DisposeVertices(); Profiler.EndSample(); UnityEngine.Debug.Log("Disposing vertices!"); } /* * UnityEngine.Debug.Assert(Halfedge.unusedPool.Contains(lbnd), "lbnd"); * UnityEngine.Debug.Assert(Halfedge.unusedPool.Contains(rbnd), "rbnd"); * UnityEngine.Debug.Assert(Halfedge.unusedPool.Contains(llbnd), "llbnd"); * UnityEngine.Debug.Assert(Halfedge.unusedPool.Contains(rrbnd), "rrbnd"); * UnityEngine.Debug.Assert(Halfedge.unusedPool.Contains(bisector), "bisector"); */ }