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 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;
                }
            }
        }