private List <Vector2> ClipToBounds(Rectangle bounds) { var points = new List <Vector2>(); var n = Edges.Count; var i = 0; while (i < n && (!(Edges[i]).Visible)) { i++; } if (i == n) { return(new List <Vector2>()); } var edge = Edges[i]; var orientation = _edgeOrientations[i]; points.Add(edge.ClippedEnds[orientation]); points.Add(edge.ClippedEnds[LR.Other(orientation)]); for (int j = i; j < n; j++) { edge = Edges[j]; if (edge.Visible) { Connect(points, j, bounds); } } Connect(points, i, bounds, true); return(points); }
public void SetVertex(LR leftRight, Vertex v) { if (leftRight == LR.Left) { _leftVertex = v; } else { _rightVertex = v; } }
private void Connect(List <Vector2> points, int j, Rectangle bounds, bool closingUp = false) { var rightPoint = points.Last(); var newEdge = Edges[j]; var newOrientation = _edgeOrientations[j]; var newPoint = newEdge.ClippedEnds[newOrientation]; if (!CloseEnough(rightPoint, newPoint)) { if (!Equals(rightPoint.X, newPoint.X) && !Equals(rightPoint.Y, newPoint.Y)) { var rightCheck = BoundsChecker.Check(rightPoint, bounds); var newCheck = BoundsChecker.Check(newPoint, bounds); float px, py; if (rightCheck.HasFlag(BoundsCheck.Right)) { px = bounds.Right; if (newCheck.HasFlag(BoundsCheck.Bottom)) { py = bounds.Bottom; points.Add(new Vector2(px, py)); } else if (newCheck.HasFlag(BoundsCheck.Top)) { py = bounds.Top; points.Add(new Vector2(px, py)); } else if (newCheck.HasFlag(BoundsCheck.Left)) { py = rightPoint.Y - bounds.Top + newPoint.Y - bounds.Top < bounds.Height ? bounds.Top : bounds.Bottom; points.Add(new Vector2(px, py)); points.Add(new Vector2(bounds.Left, py)); } } else if (rightCheck.HasFlag(BoundsCheck.Left)) { px = bounds.Left; if (newCheck.HasFlag(BoundsCheck.Bottom)) { py = bounds.Bottom; points.Add(new Vector2(px, py)); } else if (newCheck.HasFlag(BoundsCheck.Top)) { py = bounds.Top; points.Add(new Vector2(px, py)); } else if (newCheck.HasFlag(BoundsCheck.Right)) { py = rightPoint.Y - bounds.Top + newPoint.Y - bounds.Top < bounds.Height ? bounds.Top : bounds.Bottom; points.Add(new Vector2(px, py)); points.Add(new Vector2(bounds.Right, py)); } } else if (rightCheck.HasFlag(BoundsCheck.Top)) { py = bounds.Top; if (newCheck.HasFlag(BoundsCheck.Right)) { px = bounds.Right; points.Add(new Vector2(px, py)); } else if (newCheck.HasFlag(BoundsCheck.Left)) { px = bounds.Left; points.Add(new Vector2(px, py)); } else if (newCheck.HasFlag(BoundsCheck.Bottom)) { px = rightPoint.X - bounds.Left + newPoint.X - bounds.Left < bounds.Width ? bounds.Left : bounds.Right; points.Add(new Vector2(px, py)); points.Add(new Vector2(px, bounds.Bottom)); } } else if (rightCheck.HasFlag(BoundsCheck.Bottom)) { py = bounds.Bottom; if (newCheck.HasFlag(BoundsCheck.Right)) { px = bounds.Right; points.Add(new Vector2(px, py)); } else if (newCheck.HasFlag(BoundsCheck.Left)) { px = bounds.Left; points.Add(new Vector2(px, py)); } else if (newCheck.HasFlag(BoundsCheck.Top)) { px = rightPoint.X - bounds.Left + newPoint.X - bounds.Left < bounds.Width ? bounds.Left : bounds.Right; points.Add(new Vector2(px, py)); points.Add(new Vector2(px, bounds.Top)); } } } if (closingUp) { return; } points.Add(newPoint); } var newRightPoint = newEdge.ClippedEnds[LR.Other(newOrientation)]; if (!CloseEnough(points[0], newRightPoint)) { points.Add(newRightPoint); } }
public Site Site(LR lr) { return _sites[lr]; }
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; }
public HalfEdge(Edge edge, LR lr) { Init(edge, lr); }
public Site Site(LR lr) { return(_sites[lr]); }