/** * 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; }
/** * 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; }
private Halfedge Init (Edge edge, Nullable<Side> lr) { this.edge = edge; leftRight = lr; nextInPriorityQueue = null; vertex = null; return this; }
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; }
public void ReallyDispose() { edgeListLeftNeighbor = null; edgeListRightNeighbor = null; nextInPriorityQueue = null; edge = null; leftRight = null; vertex = null; _pool.Add(this); }
public void Insert (Halfedge halfEdge) { Halfedge previous, next; int insertionBucket = Bucket (halfEdge); if (insertionBucket < _minBucket) { _minBucket = 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 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 (); } }
/** * This is the only way to make a Vertex * * @param halfedge0 * @param halfedge1 * @return * */ public static Vertex Intersect(Halfedge halfedge0, Halfedge halfedge1) { Edge edge0, edge1, edge; 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 (-1.0e-10 < determinant && determinant < 1.0e-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); }
public EdgeList (float xmin, float deltax, int sqrt_nsites) { _xmin = xmin; _deltax = deltax; _hashsize = 2 * sqrt_nsites; _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; }
public void Dispose () { Halfedge halfEdge = _leftEnd; Halfedge prevHe; while (halfEdge != _rightEnd) { prevHe = halfEdge; halfEdge = halfEdge.edgeListRightNeighbor; prevHe.Dispose (); } _leftEnd = null; _rightEnd.Dispose (); _rightEnd = null; int i; for (i = 0; i < _hashsize; ++i) { _hash [i] = null; } _hash = null; }
public EdgeList(float xmin, float deltax, int sqrt_nsites) { _xmin = xmin; _deltax = deltax; _hashsize = 2 * sqrt_nsites; int i; _hash = new List<Halfedge>(_hashsize); while (_hash.Count < _hashsize) { _hash.Add(null); } // 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; }
private Site FortunesAlgorithm_rightRegion (Halfedge he) { Edge edge = he.edge; if (edge == null) { return fortunesAlgorithm_bottomMostSite; } return edge.Site (SideHelper.Other ((Side)he.leftRight)); }
Site RightRegion(Halfedge he, Site bottomMostSite) { Edge edge = he.edge; if (edge == null) { return bottomMostSite; } return edge.GetSite(LR.Other(he.leftRight)); }
private Site FortunesAlgorithm_leftRegion(Halfedge he) { Edge edge = he.edge; if (edge == null) { return fortunesAlgorithm_bottomMostSite; } return edge.Site ((LR.Side)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; Rect dataBounds = _sites.GetSitesBounds(); int sqrt_nsites = (int)(Math.Sqrt(_sites.Length + 4)); HalfedgePriorityQueue heap = new HalfedgePriorityQueue(dataBounds.y, dataBounds.height, sqrt_nsites); EdgeList edgeList = new EdgeList(dataBounds.x, dataBounds.width, sqrt_nsites); List <Halfedge> halfEdges = new List <Halfedge>(); List <Vertex> vertices = new List <Vertex>(); Site bottomMostSite = _sites.Next(); newSite = _sites.Next(); for (; ;) { if (heap.Empty() == false) { newintstar = heap.Min(); } if (newSite != null && (heap.Empty() || CompareByYThenX(newSite, newintstar) < 0)) { /* new site is smallest */ //trace("smallest: new site " + newSite); // Step 8: lbnd = edgeList.EdgeListLeftNeighbor(newSite.Coord()); // the Halfedge just to the left of newSite //trace("lbnd: " + lbnd); rbnd = lbnd.edgeListRightNeighbor; // the Halfedge just to the right //trace("rbnd: " + rbnd); bottomSite = RightRegion(lbnd, bottomMostSite); // this is the same as leftRegion(rbnd) // this Site determines the region containing the new site //trace("new Site is in region of existing site: " + bottomSite); // Step 9: edge = Edge.CreateBisectingEdge(bottomSite, newSite); //trace("new edge: " + edge); _edges.Add(edge); bisector = Halfedge.Create(edge, LR.LEFT); halfEdges.Add(bisector); // inserting two Halfedges into edgeList static readonlyitutes 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() == false) { /* 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))); 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 edge2 in _edges) { edge2.ClipVertices(_plotBounds); } // but we don't actually ever use them again! foreach (Vertex vertex2 in vertices) { vertex2.Dispose(); } vertices.Clear(); }