Пример #1
0
        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);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
 /// <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");
     }
 }
Пример #4
0
        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);
            }
        }
Пример #5
0
        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;
                }
            }
        }