Site RightRegion(Halfedge he, Site bottomMostSite) { Edge edge = he.edge; if (edge == null) { return(bottomMostSite); } return(edge.GetSite(LR.Other(he.leftRight))); }
private List <Vector2> ClipToBounds(Rect bounds) { List <Vector2> Vector2s = new List <Vector2>(); int n = _edges.Count; int i = 0; Edge edge; while (i < n && ((_edges[i] as Edge).Visible == false)) { ++i; } if (i == n) { // no edges visible return(new List <Vector2>()); } edge = _edges[i]; LR orientation = _edgeOrientations[i]; Vector2s.Add(edge.ClippedEnds[orientation]); Vector2s.Add(edge.ClippedEnds[LR.Other(orientation)]); for (int j = i + 1; j < n; ++j) { edge = _edges[j]; if (edge.Visible == false) { continue; } Connect(Vector2s, j, bounds); } // close up the polygon by adding another corner Vector2 of the bounds if needed: Connect(Vector2s, i, bounds, true); return(Vector2s); }
private List <Vector2f> ClipToBounds(Rectf bounds) { List <Vector2f> points = new List <Vector2f>(); int n = edges.Count; int i = 0; Edge edge; while (i < n && !edges[i].Visible()) { i++; } if (i == n) { // No edges visible return(new List <Vector2f>()); } edge = edges[i]; LR orientation = edgeOrientations[i]; points.Add(edge.ClippedEnds[orientation]); points.Add(edge.ClippedEnds[LR.Other(orientation)]); for (int j = i + 1; j < n; j++) { edge = edges[j]; if (!edge.Visible()) { continue; } Connect(ref points, j, bounds); } // Close up the polygon by adding another corner point of the bounds if needed: Connect(ref points, i, bounds, true); return(points); }
private void FortunesAlgorithm() { Site newSite, bottomSite, topSite, tempSite; Vertex v, vertex; PointF newintstar = PointF.Empty; LR leftRight; Halfedge lbnd, rbnd, llbnd, rrbnd, bisector; Edge edge; RectangleF 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(); }
private void Connect(List <Vector2> Vector2s, int j, Rect bounds, bool closingUp) { Vector2 rightVector2 = Vector2s[Vector2s.Count - 1]; Edge newEdge = _edges[j] as Edge; LR newOrientation = _edgeOrientations[j]; // the Vector2 that must be connected to rightVector2: Vector2 newVector2 = newEdge.ClippedEnds[newOrientation]; if (!CloseEnough(rightVector2, newVector2)) { // The Vector2s do not coincide, so they must have been clipped at the bounds; // see if they are on the same border of the bounds: if (rightVector2.x != newVector2.x && rightVector2.y != newVector2.y) { // They are on different borders of the bounds; // insert one or two corners of bounds as needed to hook them up: // (NOTE this will not be corRect if the region should take up more than // half of the bounds Rect, for then we will have gone the wrong way // around the bounds and included the smaller part rather than the larger) int rightCheck = BoundsCheck.Check(rightVector2, bounds); int newCheck = BoundsCheck.Check(newVector2, bounds); float px, py; //throw new NotImplementedException("Modified, might not work"); if (rightCheck == BoundsCheck.RIGHT) { px = bounds.right; if (newCheck == BoundsCheck.BOTTOM) { py = bounds.bottom; Vector2s.Add(new Vector2(px, py)); } else if (newCheck == BoundsCheck.TOP) { py = bounds.top; Vector2s.Add(new Vector2(px, py)); } else if (newCheck == BoundsCheck.LEFT) { if (rightVector2.y - bounds.y + newVector2.y - bounds.y < bounds.height) { py = bounds.top; } else { py = bounds.bottom; } Vector2s.Add(new Vector2(px, py)); Vector2s.Add(new Vector2(bounds.left, py)); } } else if (rightCheck == BoundsCheck.LEFT) { px = bounds.left; if (newCheck == BoundsCheck.BOTTOM) { py = bounds.bottom; Vector2s.Add(new Vector2(px, py)); } else if (newCheck == BoundsCheck.TOP) { py = bounds.top; Vector2s.Add(new Vector2(px, py)); } else if (newCheck == BoundsCheck.RIGHT) { if (rightVector2.y - bounds.y + newVector2.y - bounds.y < bounds.height) { py = bounds.top; } else { py = bounds.bottom; } Vector2s.Add(new Vector2(px, py)); Vector2s.Add(new Vector2(bounds.right, py)); } } else if (rightCheck == BoundsCheck.TOP) { py = bounds.top; if (newCheck == BoundsCheck.RIGHT) { px = bounds.right; Vector2s.Add(new Vector2(px, py)); } else if (newCheck == BoundsCheck.LEFT) { px = bounds.left; Vector2s.Add(new Vector2(px, py)); } else if (newCheck == BoundsCheck.BOTTOM) { if (rightVector2.x - bounds.x + newVector2.x - bounds.x < bounds.width) { px = bounds.left; } else { px = bounds.right; } Vector2s.Add(new Vector2(px, py)); Vector2s.Add(new Vector2(px, bounds.bottom)); } } else if (rightCheck == BoundsCheck.BOTTOM) { py = bounds.bottom; if (newCheck == BoundsCheck.RIGHT) { px = bounds.right; Vector2s.Add(new Vector2(px, py)); } else if (newCheck == BoundsCheck.LEFT) { px = bounds.left; Vector2s.Add(new Vector2(px, py)); } else if (newCheck == BoundsCheck.TOP) { if (rightVector2.x - bounds.x + newVector2.x - bounds.x < bounds.width) { px = bounds.left; } else { px = bounds.right; } Vector2s.Add(new Vector2(px, py)); Vector2s.Add(new Vector2(px, bounds.top)); } } } if (closingUp) { // newEdge's ends have already been added return; } Vector2s.Add(newVector2); } Vector2 newRightVector2 = newEdge.ClippedEnds[LR.Other(newOrientation)]; if (!CloseEnough(Vector2s[0], newRightVector2)) { Vector2s.Add(newRightVector2); } }
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(); }
private void Connect(ref List <Vector2f> points, int j, Rectf bounds, bool closingUp = false) { Vector2f rightPoint = points[points.Count - 1]; Edge newEdge = edges[j]; LR newOrientation = edgeOrientations[j]; // The point that must be conected to rightPoint: Vector2f newPoint = newEdge.ClippedEnds[newOrientation]; if (!CloseEnough(rightPoint, newPoint)) { // The points do not coincide, so they must have been clipped at the bounds; // see if they are on the same border of the bounds: if (rightPoint.x != newPoint.x && rightPoint.y != newPoint.y) { // They are on different borders of the bounds; // insert one or two corners of bounds as needed to hook them up: // (NOTE this will not be correct if the region should take up more than // half of the bounds rect, for then we will have gone the wrong way // around the bounds and included the smaller part rather than the larger) int rightCheck = BoundsCheck.Check(rightPoint, bounds); int newCheck = BoundsCheck.Check(newPoint, bounds); float px, py; if ((rightCheck & BoundsCheck.RIGHT) != 0) { px = bounds.right; if ((newCheck & BoundsCheck.BOTTOM) != 0) { py = bounds.bottom; points.Add(new Vector2f(px, py)); } else if ((newCheck & BoundsCheck.TOP) != 0) { py = bounds.top; points.Add(new Vector2f(px, py)); } else if ((newCheck & BoundsCheck.LEFT) != 0) { if (rightPoint.y - bounds.y + newPoint.y - bounds.y < bounds.height) { py = bounds.top; } else { py = bounds.bottom; } points.Add(new Vector2f(px, py)); points.Add(new Vector2f(bounds.left, py)); } } else if ((rightCheck & BoundsCheck.LEFT) != 0) { px = bounds.left; if ((newCheck & BoundsCheck.BOTTOM) != 0) { py = bounds.bottom; points.Add(new Vector2f(px, py)); } else if ((newCheck & BoundsCheck.TOP) != 0) { py = bounds.top; points.Add(new Vector2f(px, py)); } else if ((newCheck & BoundsCheck.RIGHT) != 0) { if (rightPoint.y - bounds.y + newPoint.y - bounds.y < bounds.height) { py = bounds.top; } else { py = bounds.bottom; } points.Add(new Vector2f(px, py)); points.Add(new Vector2f(bounds.right, py)); } } else if ((rightCheck & BoundsCheck.TOP) != 0) { py = bounds.top; if ((newCheck & BoundsCheck.RIGHT) != 0) { px = bounds.right; points.Add(new Vector2f(px, py)); } else if ((newCheck & BoundsCheck.LEFT) != 0) { px = bounds.left; points.Add(new Vector2f(px, py)); } else if ((newCheck & BoundsCheck.BOTTOM) != 0) { if (rightPoint.x - bounds.x + newPoint.x - bounds.x < bounds.width) { px = bounds.left; } else { px = bounds.right; } points.Add(new Vector2f(px, py)); points.Add(new Vector2f(px, bounds.bottom)); } } else if ((rightCheck & BoundsCheck.BOTTOM) != 0) { py = bounds.bottom; if ((newCheck & BoundsCheck.RIGHT) != 0) { px = bounds.right; points.Add(new Vector2f(px, py)); } else if ((newCheck & BoundsCheck.LEFT) != 0) { px = bounds.left; points.Add(new Vector2f(px, py)); } else if ((newCheck & BoundsCheck.TOP) != 0) { if (rightPoint.x - bounds.x + newPoint.x - bounds.x < bounds.width) { px = bounds.left; } else { px = bounds.right; } points.Add(new Vector2f(px, py)); points.Add(new Vector2f(px, bounds.top)); } } } if (closingUp) { // newEdge's ends have already been added return; } points.Add(newPoint); } Vector2f newRightPoint = newEdge.ClippedEnds[LR.Other(newOrientation)]; if (!CloseEnough(points[0], newRightPoint)) { points.Add(newRightPoint); } }
private void Connect(List <PointF> PointFs, int j, RectangleF bounds, bool closingUp) { PointF rightPointF = PointFs[PointFs.Count - 1]; Edge newEdge = _edges[j] as Edge; LR newOrientation = _edgeOrientations[j]; // the PointF that must be connected to rightPointF: PointF newPointF = newEdge.ClippedEnds[newOrientation]; if (!CloseEnough(rightPointF, newPointF)) { // The PointFs do not coincide, so they must have been clipped at the bounds; // see if they are on the same border of the bounds: if (rightPointF.X != newPointF.X && rightPointF.Y != newPointF.Y) { // They are on different borders of the bounds; // insert one or two corners of bounds as needed to hook them up: // (NOTE this will not be corRectangleF if the region should take up more than // half of the bounds RectangleF, for then we will have gone the wrong way // around the bounds and included the smaller part rather than the larger) int rightCheck = BoundsCheck.Check(rightPointF, bounds); int newCheck = BoundsCheck.Check(newPointF, bounds); float px, py; //throw new NotImplementedException("Modified, might not work"); if (rightCheck == BoundsCheck.RIGHT) { px = bounds.Right; if (newCheck == BoundsCheck.BOTTOM) { py = bounds.Bottom; PointFs.Add(new PointF(px, py)); } else if (newCheck == BoundsCheck.TOP) { py = bounds.Top; PointFs.Add(new PointF(px, py)); } else if (newCheck == BoundsCheck.LEFT) { if (rightPointF.Y - bounds.Y + newPointF.Y - bounds.Y < bounds.Height) { py = bounds.Top; } else { py = bounds.Bottom; } PointFs.Add(new PointF(px, py)); PointFs.Add(new PointF(bounds.Left, py)); } } else if (rightCheck == BoundsCheck.LEFT) { px = bounds.Left; if (newCheck == BoundsCheck.BOTTOM) { py = bounds.Bottom; PointFs.Add(new PointF(px, py)); } else if (newCheck == BoundsCheck.TOP) { py = bounds.Top; PointFs.Add(new PointF(px, py)); } else if (newCheck == BoundsCheck.RIGHT) { if (rightPointF.Y - bounds.Y + newPointF.Y - bounds.Y < bounds.Height) { py = bounds.Top; } else { py = bounds.Bottom; } PointFs.Add(new PointF(px, py)); PointFs.Add(new PointF(bounds.Right, py)); } } else if (rightCheck == BoundsCheck.TOP) { py = bounds.Top; if (newCheck == BoundsCheck.RIGHT) { px = bounds.Right; PointFs.Add(new PointF(px, py)); } else if (newCheck == BoundsCheck.LEFT) { px = bounds.Left; PointFs.Add(new PointF(px, py)); } else if (newCheck == BoundsCheck.BOTTOM) { if (rightPointF.X - bounds.X + newPointF.X - bounds.X < bounds.Width) { px = bounds.Left; } else { px = bounds.Right; } PointFs.Add(new PointF(px, py)); PointFs.Add(new PointF(px, bounds.Bottom)); } } else if (rightCheck == BoundsCheck.BOTTOM) { py = bounds.Bottom; if (newCheck == BoundsCheck.RIGHT) { px = bounds.Right; PointFs.Add(new PointF(px, py)); } else if (newCheck == BoundsCheck.LEFT) { px = bounds.Left; PointFs.Add(new PointF(px, py)); } else if (newCheck == BoundsCheck.TOP) { if (rightPointF.X - bounds.X + newPointF.X - bounds.X < bounds.Width) { px = bounds.Left; } else { px = bounds.Right; } PointFs.Add(new PointF(px, py)); PointFs.Add(new PointF(px, bounds.Top)); } } } if (closingUp) { // newEdge's ends have already been added return; } PointFs.Add(newPointF); } PointF newRightPointF = newEdge.ClippedEnds[LR.Other(newOrientation)]; if (!CloseEnough(PointFs[0], newRightPointF)) { PointFs.Add(newRightPointF); } }