public Arc(VoronoiCell cell, Point p, Arc prev, Arc next) : this(cell, p, prev) { this.next = next; }
public Arc(VoronoiCell cell, Point p, Arc prev) : this(cell, p) { this.prev = prev; }
void FinishEdges() { // Advance the sweep line so no parabolas can cross the bounding box. double l = X1 + (X1 - X0) + (Y1 - Y0); // Extend each remaining segment to the new parabola intersections. for (Arc i = root; i.next != null; i = i.next) { if (i.s1 != null) { i.s1.Finish(Intersection(i.p, i.next.p, l * 2)); } } // Crop output for (int c = 0; c < cells.Length; c++) { VoronoiCell cell = cells [c]; bool cropped = false; // Crop segments if needed for (int k = 0; k < cell.segments.Count; k++) { Segment s = cell.segments [k]; // is the segment completely outside? if (!s.done || (s.start.x < X0 && s.end.x < X0) || (s.start.y < Y0 && s.end.y < Y0) || (s.start.x > X1 && s.end.x > X1) || (s.start.y > Y1 && s.end.y > Y1) || Point.EqualsBoth(s.start, s.end)) { s.deleted = true; continue; } // is any endpoint outside of the canvas? bool p1inside = PointInsideRect(s.start); if (!p1inside) { s.start = CropPoint(s.start, s, cell); cropped = true; } bool p2inside = PointInsideRect(s.end); if (!p2inside) { s.end = CropPoint(s.end, s, cell); cropped = true; } } if (cropped) { // join borders with 2 points if (cell.top.Count > 1) { cell.segments.Add(new Segment(cell.top [0], cell.top [1], true)); } if (cell.bottom.Count > 1) { cell.segments.Add(new Segment(cell.bottom [0], cell.bottom [1], true)); } if (cell.left.Count > 1) { cell.segments.Add(new Segment(cell.left [0], cell.left [1], true)); } if (cell.right.Count > 1) { cell.segments.Add(new Segment(cell.right [0], cell.right [1], true)); } } } // 2nd step - snap to nearest corners Point[] corners = new Point[4]; corners [0] = new Point(X0, Y0); corners [1] = new Point(X0, Y1); corners [2] = new Point(X1, Y0); corners [3] = new Point(X1, Y1); Point np; for (int cornerIndex = 0; cornerIndex < corners.Length; cornerIndex++) { Point corner = corners [cornerIndex]; // Get the nearest point of the segments VoronoiCell nearestCell = GetNearestCellFrom(corner); // this territory is the nearest to the corner so now we can snap the nearest segment safely if (GetNearestSegmentPointToCorner(corner, nearestCell.segments, true, out np)) { nearestCell.segments.Add(new Segment(np, corner, true)); } if (GetNearestSegmentPointToCorner(corner, nearestCell.segments, false, out np)) { nearestCell.segments.Add(new Segment(np, corner, true)); } } }
public Arc(VoronoiCell cell, Point p) { this.p = p; this.cell = cell; }
public void AssignData(Point[] centers) { if (this.cells == null || this.cells.Length != centers.Length) { this.cells = new VoronoiCell[centers.Length]; } for (int k = 0; k < cells.Length; k++) { cells [k] = new VoronoiCell(centers [k]); } if (eventQueue == null) { eventQueue = new List <Event> (cells.Length); } else { eventQueue.Clear(); } root = null; eventQueueTop = 0; if (hit == null) { hit = new Dictionary <Point, bool> (cells.Length); } else { hit.Clear(); } for (int k = 0; k < cells.Length; k++) { Point p = cells [k].center; // Checks that p is not near than PRECISION from other point while (hit.ContainsKey(p)) { if (p.x > 0) { p.x -= Point.PRECISION * 2.0f; } else { p.x += Point.PRECISION * 2.0f; } } hit.Add(p, true); Event siteEvent = new Event(EVENT_TYPE.SiteEvent); siteEvent.p = p; siteEvent.x = p.x; siteEvent.cell = cells [k]; eventQueue.Add(siteEvent); } eventQueue.Sort((Event e1, Event e2) => { if (e1.x < e2.x - Point.PRECISION) { return(-1); } else if (e1.x > e2.x + Point.PRECISION) { return(1); } else if (e1.p.y < e2.p.y - Point.PRECISION) { return(-1); } else if (e1.p.y > e2.p.y + Point.PRECISION) { return(1); } else { return(0); } }); }