public FortuneArc SplitArc(FortuneArc splittingArc, FortuneArc splitter) { FortuneArc left = new FortuneArc(); left.Site = splittingArc.Site; FortuneArc right = new FortuneArc(); right.Site = splittingArc.Site; // create a new edge VoronoiEdge edge = new VoronoiEdge(splittingArc.Site.Cell, splitter.Site.Cell); // both nodes of the edge are initially points at infinity, // but can become final after the event range double x = splitter.Site.Cell.DataPoint.X; double y = splitter.Site.Cell.DataPoint.Y; double distance = getDistanceToArc(splittingArc.Site.Cell.DataPoint, y, x); edge.Node1 = new VoronoiNode(x, y - distance); edge.Node1.IsInfinit = true; edge.Node2 = new VoronoiNode(x, y - distance); edge.Node2.IsInfinit = true; // add this edge in both cell diagram splitter.Site.Cell.AddEdge(edge); splittingArc.Site.Cell.AddEdge(edge); //add nodes to the arcs of the ribs splitter.LeftNode = edge.Node1; splitter.RightNode = edge.Node2; left.LeftNode = splittingArc.LeftNode; left.RightNode = edge.Node1; right.LeftNode = edge.Node2; right.RightNode = splittingArc.RightNode; left.Left = splittingArc.Left; right.Right = splittingArc.Right; splitter.Left = left; splitter.Right = right; if (splittingArc.Parent != null) { if (splittingArc.Parent.Left == splittingArc) { splittingArc.Parent.Left = splitter; } else if (splittingArc.Parent.Right == splittingArc) { splittingArc.Parent.Right = splitter; } } else { Root = splitter; } return(splitter); }
/// <summary> /// Adds an edge to the cell. /// </summary> /// <param name="edge">An edge to add</param> internal void AddEdge(VoronoiEdge edge) { if (edge.Cell1 != this && edge.Cell2 != this) { throw new ArgumentException("Edge does not contain a reference to this cell", "edge"); } _edges.Add(edge); }
/// <summary> /// Removes an edge from the cell. /// </summary> /// <param name="edge">An edge to remove</param> internal void RemoveEdge(VoronoiEdge edge) { if (_edges.Contains(edge)) { _edges.Remove(edge); } else { throw new ArgumentException("Cell does not contain this edge", "edge"); } }
private void init(List <VoronoiCell> cells, int lastMaxYIndex) { _rectangle = new BoundingRectangle(); _eventList = new LinkedList <FortuneEvent>(); _startVerticalNodes = new List <VoronoiNode>(); // Where several points have the minimum ordinate requires a separate pre-treatment int skipEventCount = 0; if (lastMaxYIndex > 0) { VoronoiNode previousNode = null; FortuneArc currentArc = null; skipEventCount = lastMaxYIndex + 1; for (int i = 0; i <= lastMaxYIndex; i++) { // add an arc of coastline FortuneArc arc = new FortuneArc(); FortuneSite site = new FortuneSite(); site.Cell = cells[i]; arc.Site = site; if (currentArc != null) { currentArc.Right = arc; } currentArc = arc; if (_shoreLine.Root == null) { _shoreLine.Root = arc; } if (previousNode != null) { arc.LeftNode = previousNode; } // add the vertical edges of the Voronoi diagram if (i < lastMaxYIndex) { VoronoiEdge edge = new VoronoiEdge(cells[i], cells[i + 1]); double middleX = (cells[i].DataPoint.X + cells[i + 1].DataPoint.X) / 2; double middleY = cells[i].DataPoint.Y; edge.Node1 = new VoronoiNode(middleX, middleY); edge.Node1.IsInfinit = true; _startVerticalNodes.Add(edge.Node1); edge.Node2 = new VoronoiNode(middleX, middleY); edge.Node2.IsInfinit = true; previousNode = edge.Node2; arc.RightNode = edge.Node2; cells[i].AddEdge(edge); cells[i + 1].AddEdge(edge); } } } // fill all point events int j = 0; foreach (VoronoiCell cell in cells) { if (skipEventCount > j++) { continue; } FortunePointEvent ev = new FortunePointEvent(); ev.Point = cell.DataPoint; ev.Cell = cell; _eventList.AddLast(ev); } }
private void handleCircleEvent(FortuneCircleEvent ev) { FortuneArc ln = ev.Arc.LeftNeighbor; FortuneArc rn = ev.Arc.RightNeighbor; // remove events range associated with this arc if (ln.CircleEvent != null) { _eventList.Remove(ln.CircleEvent); } if (rn.CircleEvent != null) { _eventList.Remove(rn.CircleEvent); } // remove the arc of coastline _shoreLine.RemoveArc(ev.Arc); //fix slave nodes arc ribs if (ev.Arc.LeftNode != null) { ev.Arc.LeftNode.Point = ev.CircleCenter; ev.Arc.LeftNode.IsInfinit = false; } if (ev.Arc.RightNode != null) { ev.Arc.RightNode.Point = ev.CircleCenter; ev.Arc.RightNode.IsInfinit = false; } // add a new edge VoronoiEdge edge = new VoronoiEdge(ln.Site.Cell, rn.Site.Cell); edge.Node1 = new VoronoiNode(ev.CircleCenter.X, ev.CircleCenter.Y); edge.Node2 = new VoronoiNode((ln.Site.Cell.DataPoint.X + rn.Site.Cell.DataPoint.X) / 2, (ln.Site.Cell.DataPoint.Y + rn.Site.Cell.DataPoint.Y) / 2); //expand the bounding rectangle of the chart _rectangle.Join(ev.CircleCenter); // one node of the new edge is fixed, the second - no edge.Node1.IsInfinit = false; edge.Node2.IsInfinit = true; // dobavleyaem edge to cells ln.Site.Cell.AddEdge(edge); rn.Site.Cell.AddEdge(edge); //add a triangle in the Delaunay triangulation, if necessary if (_buildTriangles) { _triangles.Add(ev.Triangle); } // not a fixed node is a new edge now vanished neighbors arc ln.RightNode = edge.Node2; rn.LeftNode = edge.Node2; FortuneArc lnln = ln.LeftNeighbor; FortuneArc lnrn = ln.RightNeighbor; FortuneArc rnln = rn.LeftNeighbor; FortuneArc rnrn = rn.RightNeighbor; // add events to the newly formed circle arcs triples if (lnln != null) { if (lnrn != null) { FortuneEvent eventToAdd = getCircleEvent(lnln, ln, lnrn, ev.Point.Y); if (eventToAdd != null) { addCircleEvent(eventToAdd); } ln.CircleEvent = eventToAdd; } } if (rnln != null) { if (rnrn != null) { FortuneEvent eventToAdd = getCircleEvent(rnln, rn, rnrn, ev.Point.Y); if (eventToAdd != null) { addCircleEvent(eventToAdd); } rn.CircleEvent = eventToAdd; } } }