Exemplo n.º 1
0
    public List <BeachLineEdge> DoVoronoi(List <VoronoiSite> siteList)
    {
        List <BeachLineEdge> outEdges = new List <BeachLineEdge>();

        beachLine = new BeachLine();
        events    = new List <VoronoiEvent>();

        // Add site list to event list.
        foreach (VoronoiSite site in siteList)
        {
            events.Add(new SiteEvent(site));
        }

        // Sort site list.
        events.Sort();

        // Test for first two events being very close in y
        if (events.Count >= 2)
        {
            if (events[0].y - events[1].y < 0.01f)
            {
                // Add another site events far above them to prevent this from happening
                events.Insert(0, new SiteEvent(new VoronoiSite(new Vector2(0, -10))));
            }
        }

        // Start processing events
        int iterations = 0;

        while (events.Count != 0)
        {
            if (use_max_iterations && iterations == max_iterations)
            {
                break;
            }
            else
            {
                iterations++;
            }

            // Pop event off front of list
            VoronoiEvent thisEvent = events[0];


            // Set sweepline
            sweepLine = thisEvent.y;

            if (sweepLine >= target_sweepline)
            {
                sweepLine = target_sweepline;
                beachLine.Update(sweepLine);
                break;
            }

            beachLine.Update(sweepLine);

            if (thisEvent.IsValid())
            {
                // Check event type
                if (thisEvent is SiteEvent)
                {
                    SiteEvent siteEvent = (SiteEvent)thisEvent;

                    // Create a new arc for this event.
                    BeachLineArc newArc = new BeachLineArc(siteEvent.Site.Point, sweepLine);

                    // Find arc at this site
                    BeachLineArc arcToSplit = beachLine.SearchX(siteEvent.x);
                    if (arcToSplit == null)
                    {
                        // We could not find an arc, meaning this is the first one.
                        // Lets just add it to the beachline as root.
                        beachLine.SetRoot(newArc);
                    }
                    else
                    {
                        // Split the arc
                        arcToSplit.Split(newArc);

                        // The split will have added newArc to the tree and also created two new edges.
                        // We need to check those for intersections.
                        List <BeachLineArc> arcsToSqueeze = new List <BeachLineArc> {
                            newArc.LeftArc, newArc.RightArc
                        };
                        foreach (BeachLineArc arc in arcsToSqueeze)
                        {
                            CheckForNewEdgeEvents(arc);
                        }
                    }
                }
                else if (thisEvent is EdgeEvent)
                {
                    EdgeEvent edgeEvent = (EdgeEvent)thisEvent;

                    if (edgeEvent.SqueezedArc != null)
                    {
                        if (edgeEvent.SqueezedArc.LeftEdge != null && edgeEvent.SqueezedArc.RightEdge != null)
                        {
                            BeachLineEdge        newEdge;
                            List <BeachLineEdge> outputEdges = edgeEvent.SqueezedArc.Squeeze(out newEdge);

                            // Add edges to output
                            foreach (BeachLineEdge edge in outputEdges)
                            {
                                outEdges.Add(edge);
                            }

                            // Squeeze function will have removed arc and edges from tree and created a new edge.
                            // We need to check that edge for any new intersections.
                            CheckForNewEdgeEvents(newEdge.LeftArc);
                            CheckForNewEdgeEvents(newEdge.RightArc);
                        }
                    }
                    // Otherwise, this must have been pre-empted but not invalidated for some reason
                }
                else
                {
                    Debug.LogError("Wrong event type! Should not happen!");
                }
            }
            events.RemoveAt(0);
        }
        if (iterations != max_iterations)
        {
            sweepLine = target_sweepline;
            beachLine.Update(sweepLine);
        }

        if (events.Count == 0)
        {
            // We completed the events list.
            // Add the remaining edges to the output.
            BeachLineElement node = beachLine.GetRoot();
            if (node != null)
            {
                // Mode node to start
                while (node.Prev != null)
                {
                    node = node.Prev;
                }
                // Add all remaining edges
                while (node.Next != null)
                {
                    if (node is BeachLineEdge)
                    {
                        outEdges.Add(node as BeachLineEdge);
                    }
                    node = node.Next;
                }
            }
        }

        return(outEdges);
    }