private void build(List <VoronoiCell> cells, int lastMaxYIndex) { init(cells, lastMaxYIndex); // handle all while (_eventList.Count > 0) { FortuneEvent currentEvent = _eventList.First.Value; _eventList.RemoveFirst(); switch (currentEvent.Kind) { case FortuneEvent.EventKind.Point: handlePointEvent((FortunePointEvent)currentEvent); break; case FortuneEvent.EventKind.Circle: handleCircleEvent((FortuneCircleEvent)currentEvent); break; } } // calculate the coordinates of the "free" sites _shoreLine.Finish(_rectangle, _startVerticalNodes); // remove degenerate edges clean(cells); }
private void addCircleEvent(FortuneEvent ev) { LinkedListNode <FortuneEvent> currentEvent = _eventList.First; while (currentEvent != null) { if (currentEvent.Value.Point.Y < ev.Point.Y) { _eventList.AddBefore(currentEvent, ev); return; } currentEvent = currentEvent.Next; } _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; } } }
private void handlePointEvent(FortunePointEvent ev) { if (_shoreLine.Root == null) { FortuneArc arc = new FortuneArc(); FortuneSite site = new FortuneSite(); site.Cell = ev.Cell; arc.Site = site; _shoreLine.Root = arc; return; } FortuneArc arcAbove = _shoreLine.FindArc(ev.Point.X, ev.Point.Y); // remove events range from the queue if (arcAbove.CircleEvent != null) { _eventList.Remove(arcAbove.CircleEvent); } // create an arc FortuneArc splitter = new FortuneArc(); splitter.Site = new FortuneSite(); splitter.Site.Cell = ev.Cell; FortuneArc newArc = _shoreLine.SplitArc(arcAbove, splitter); FortuneArc ln = newArc.LeftNeighbor; FortuneArc lnln = null; if (ln != null) { lnln = ln.LeftNeighbor; } FortuneArc rn = newArc.RightNeighbor; FortuneArc rnrn = null; if (rn != null) { rnrn = rn.RightNeighbor; } if (ln != null) { if (lnln != null) { FortuneEvent eventToAdd = getCircleEvent(lnln, ln, newArc, ev.Point.Y); if (eventToAdd != null) { addCircleEvent(eventToAdd); } ln.CircleEvent = eventToAdd; } } if (rn != null) { if (rnrn != null) { FortuneEvent eventToAdd = getCircleEvent(newArc, rn, rnrn, ev.Point.Y); if (eventToAdd != null) { addCircleEvent(eventToAdd); } rn.CircleEvent = eventToAdd; } } }