public static Vertex Intersect(HalfEdge he0, HalfEdge he1) { var edge0 = he0.Edge; var edge1 = he1.Edge; if (edge0 == null || edge1 == null) return null; if (edge0.RightSite == edge1.RightSite) return null; var determinant = edge0.A*edge1.B - edge0.B*edge1.A; if (-1.0e-10 < determinant && determinant < 1.0e-10) { return null; } var intersectionX = (edge0.C*edge1.B - edge1.C*edge0.B)/determinant; var intersectionY = (edge1.C*edge0.A - edge0.C * edge1.A)/determinant; HalfEdge halfEdge; Edge edge; if (Voronoi.CompareByYThenX(edge0.RightSite, edge1.RightSite) < 0) { halfEdge = he0; edge = edge0; } else { halfEdge = he1; edge = edge1; } var rightOfSite = intersectionX >= edge.RightSite.X; if ((rightOfSite && halfEdge.LeftRight == LR.Left) || (!rightOfSite && halfEdge.LeftRight == LR.Right)) { return null; } return Create(intersectionX, intersectionY); }
public void Remove(HalfEdge halfEdge) { var removalBucket = Bucket(halfEdge); if (halfEdge.Vertex != null) { var previous = _hash[removalBucket]; while (previous.NextInPriorityQueue != halfEdge) { previous = previous.NextInPriorityQueue; } previous.NextInPriorityQueue = halfEdge.NextInPriorityQueue; _count--; } }
public void Insert(HalfEdge halfEdge) { var insertionBucket = Bucket(halfEdge); if (insertionBucket < _minBucket) { _minBucket = insertionBucket; } var previous = _hash[insertionBucket]; HalfEdge next; while ((next = previous.NextInPriorityQueue) != null && (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 sqrtNSites) { _xmin = xmin; _deltaX = deltax; _hashSize = 2 * sqrtNSites; _hash = new List<HalfEdge>(new HalfEdge[_hashSize]); LeftEnd = new HalfEdge(); RightEnd = new HalfEdge(); LeftEnd.EdgeListLeftNeighbor = null; LeftEnd.EdgeListRightNeighbor = RightEnd; RightEnd.EdgeListLeftNeighbor = LeftEnd; RightEnd.EdgeListRightNeighbor = null; _hash[0] = LeftEnd; _hash[_hashSize - 1] = RightEnd; }
private static Site RightRegion(HalfEdge he) { var edge = he.Edge; return edge == null ? null : edge.Site(LR.Other(he.LeftRight)); }
private void FortunesAlgorithm() { var dataBounds = _sites.GetSiteBounds(); var sqrtNSites = (int)Math.Sqrt(_sites.Length + 4); var heap = new HalfEdgePriorityQueue(dataBounds.Top, dataBounds.Height, sqrtNSites); var edgeList = new EdgeList(dataBounds.Left, dataBounds.Width, sqrtNSites); var halfEdges = new List<HalfEdge>(); var vertices = new List<Vertex>(); var bottomMostSite = _sites.Next(); var newSite = _sites.Next(); var newIntStar = new Vector2(); for (; ; ) { if (!heap.Empty) { newIntStar = heap.Min(); } if (newSite != null && (heap.Empty || CompareByYThenX(newSite, newIntStar) < 0)) { Console.WriteLine("smallest: new site " + newSite); var lbnd = edgeList.EdgeListLeftNeighbor(newSite.Coord); Console.WriteLine("lbnd: " + lbnd); var rbnd = lbnd.EdgeListRightNeighbor; Console.WriteLine("rbnd: " + rbnd); var bottomSite = RightRegion(lbnd) ?? bottomMostSite; Console.WriteLine("new site is in region of existing site: " + bottomSite); var edge = Edge.CreateBisectingEdge(bottomSite, newSite); Console.WriteLine("new edge: " + edge); Edges.Add(edge); var bisector = new HalfEdge(edge, LR.Left); halfEdges.Add(bisector); edgeList.Insert(lbnd, bisector); Vertex vertex = Vertex.Intersect(lbnd, bisector); if (vertex != null) { vertices.Add(vertex); heap.Remove(lbnd); lbnd.Vertex = vertex; lbnd.YStar = vertex.Y + newSite.Distance(vertex); heap.Insert(lbnd); } lbnd = bisector; bisector = new HalfEdge(edge, LR.Right); halfEdges.Add(bisector); edgeList.Insert(lbnd, bisector); vertex = Vertex.Intersect(bisector, rbnd); if (vertex != null) { vertices.Add(vertex); bisector.Vertex = vertex; bisector.YStar = vertex.Y + newSite.Distance(vertex); heap.Insert(bisector); } newSite = _sites.Next(); } else if (!heap.Empty) { var lbnd = heap.ExtractMin(); var llbnd = lbnd.EdgeListLeftNeighbor; var rbnd = lbnd.EdgeListRightNeighbor; var rrbnd = rbnd.EdgeListRightNeighbor; var bottomSite = LeftRegion(lbnd) ?? bottomMostSite; var topSite = RightRegion(rbnd) ?? bottomMostSite; var 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); var leftRight = LR.Left; if (bottomSite.Y > topSite.Y) { var tempSite = bottomSite; bottomSite = topSite; topSite = tempSite; leftRight = LR.Right; } var edge = Edge.CreateBisectingEdge(bottomSite, topSite); Edges.Add(edge); var bisector = new HalfEdge(edge, leftRight); halfEdges.Add(bisector); edgeList.Insert(llbnd, bisector); edge.SetVertex(LR.Other(leftRight), v); Vertex vertex; if ((vertex = Vertex.Intersect(llbnd, bisector)) != null) { vertices.Add(vertex); heap.Remove(llbnd); llbnd.Vertex = vertex; llbnd.YStar = vertex.Y + bottomSite.Distance(vertex); heap.Insert(llbnd); } if ((vertex = Vertex.Intersect(bisector, rrbnd)) != null) { vertices.Add(vertex); bisector.Vertex = vertex; bisector.YStar = vertex.Y + bottomSite.Distance(vertex); heap.Insert(bisector); } } else { break; } } halfEdges.Clear(); var nullVerts = Edges.Where(e => e.RightVertex == null || e.LeftVertex == null).ToList(); foreach (var edge in Edges) { edge.ClipVertices(PlotBounds); } vertices.Clear(); }
private void FortunesAlgorithm() { var dataBounds = _sites.GetSiteBounds(); var sqrtNSites = (int)Math.Sqrt(_sites.Length + 4); var heap = new HalfEdgePriorityQueue(dataBounds.Top, dataBounds.Height, sqrtNSites); var edgeList = new EdgeList(dataBounds.Left, dataBounds.Width, sqrtNSites); var halfEdges = new List <HalfEdge>(); var vertices = new List <Vertex>(); var bottomMostSite = _sites.Next(); var newSite = _sites.Next(); var newIntStar = new Vector2(); for (; ;) { if (!heap.Empty) { newIntStar = heap.Min(); } if (newSite != null && (heap.Empty || CompareByYThenX(newSite, newIntStar) < 0)) { Console.WriteLine("smallest: new site " + newSite); var lbnd = edgeList.EdgeListLeftNeighbor(newSite.Coord); Console.WriteLine("lbnd: " + lbnd); var rbnd = lbnd.EdgeListRightNeighbor; Console.WriteLine("rbnd: " + rbnd); var bottomSite = RightRegion(lbnd) ?? bottomMostSite; Console.WriteLine("new site is in region of existing site: " + bottomSite); var edge = Edge.CreateBisectingEdge(bottomSite, newSite); Console.WriteLine("new edge: " + edge); Edges.Add(edge); var bisector = new HalfEdge(edge, LR.Left); halfEdges.Add(bisector); edgeList.Insert(lbnd, bisector); Vertex vertex = Vertex.Intersect(lbnd, bisector); if (vertex != null) { vertices.Add(vertex); heap.Remove(lbnd); lbnd.Vertex = vertex; lbnd.YStar = vertex.Y + newSite.Distance(vertex); heap.Insert(lbnd); } lbnd = bisector; bisector = new HalfEdge(edge, LR.Right); halfEdges.Add(bisector); edgeList.Insert(lbnd, bisector); vertex = Vertex.Intersect(bisector, rbnd); if (vertex != null) { vertices.Add(vertex); bisector.Vertex = vertex; bisector.YStar = vertex.Y + newSite.Distance(vertex); heap.Insert(bisector); } newSite = _sites.Next(); } else if (!heap.Empty) { var lbnd = heap.ExtractMin(); var llbnd = lbnd.EdgeListLeftNeighbor; var rbnd = lbnd.EdgeListRightNeighbor; var rrbnd = rbnd.EdgeListRightNeighbor; var bottomSite = LeftRegion(lbnd) ?? bottomMostSite; var topSite = RightRegion(rbnd) ?? bottomMostSite; var 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); var leftRight = LR.Left; if (bottomSite.Y > topSite.Y) { var tempSite = bottomSite; bottomSite = topSite; topSite = tempSite; leftRight = LR.Right; } var edge = Edge.CreateBisectingEdge(bottomSite, topSite); Edges.Add(edge); var bisector = new HalfEdge(edge, leftRight); halfEdges.Add(bisector); edgeList.Insert(llbnd, bisector); edge.SetVertex(LR.Other(leftRight), v); Vertex vertex; if ((vertex = Vertex.Intersect(llbnd, bisector)) != null) { vertices.Add(vertex); heap.Remove(llbnd); llbnd.Vertex = vertex; llbnd.YStar = vertex.Y + bottomSite.Distance(vertex); heap.Insert(llbnd); } if ((vertex = Vertex.Intersect(bisector, rrbnd)) != null) { vertices.Add(vertex); bisector.Vertex = vertex; bisector.YStar = vertex.Y + bottomSite.Distance(vertex); heap.Insert(bisector); } } else { break; } } halfEdges.Clear(); var nullVerts = Edges.Where(e => e.RightVertex == null || e.LeftVertex == null).ToList(); foreach (var edge in Edges) { edge.ClipVertices(PlotBounds); } vertices.Clear(); }
private static Site RightRegion(HalfEdge he) { var edge = he.Edge; return(edge == null ? null : edge.Site(LR.Other(he.LeftRight))); }
private void Init(Edge edge, LR lr) { Edge = edge; LeftRight = lr; NextInPriorityQueue = null; Vertex = null; }
private int Bucket(HalfEdge halfEdge) { var theBucket = (int)((halfEdge.YStar - _ymin)/_deltaY*_hashSize); if (theBucket < 0) theBucket = 0; if (theBucket >= _hashSize) theBucket = _hashSize - 1; return theBucket; }
private void Initialize() { _count = 0; _minBucket = 0; _hash = new List<HalfEdge>(new HalfEdge[_hashSize]); for (int i = 0; i < _hashSize; i++) { _hash[i] = new HalfEdge { NextInPriorityQueue = null }; } }
public void Remove(HalfEdge halfEdge) { halfEdge.EdgeListLeftNeighbor.EdgeListRightNeighbor = halfEdge.EdgeListRightNeighbor; halfEdge.EdgeListRightNeighbor.EdgeListLeftNeighbor = halfEdge.EdgeListLeftNeighbor; halfEdge.Edge = Edge.Deleted; halfEdge.EdgeListLeftNeighbor = halfEdge.EdgeListRightNeighbor = null; }
public void Insert(HalfEdge lb, HalfEdge newHalfEdge) { newHalfEdge.EdgeListLeftNeighbor = lb; newHalfEdge.EdgeListRightNeighbor = lb.EdgeListRightNeighbor; lb.EdgeListRightNeighbor.EdgeListLeftNeighbor = newHalfEdge; lb.EdgeListRightNeighbor = newHalfEdge; }