Ejemplo n.º 1
0
    void Update()
    {
        List <Site> sites        = new List <Site>(siteGenerator.Sites);
        float       newMouseYpos = Camera.main.ScreenToWorldPoint(Input.mousePosition).y;

        if (Input.GetKeyDown(KeyCode.G))
        {
            renderParabolas = !renderParabolas;
            foreach (Site site in sites)
            {
                site.mParabola.SetParabolaRender(renderParabolas);
            }
        }

        if (sites.Count != 0 && renderParabolas && newMouseYpos != mouseYpos)
        {
            root = null;
            foreach (VoronoiEdge oldEdge in edges)
            {
                Destroy(oldEdge.gameObject);
            }
            edges.Clear();
            mouseYpos = newMouseYpos;
            foreach (Site site in sites)
            {
                site.mParabola.CalculateParabola(site, newMouseYpos);
            }
            eventQueue = new SortedSet <VoronoiEvent>(new EventComparer());
            foreach (Site site in sites)
            {
                if (site.transform.position.y <= mouseYpos)
                {
                    eventQueue.Add(new SiteEvent(site.transform.position));
                }
            }
            while (eventQueue.Count != 0)
            {
                VoronoiEvent popEvent = eventQueue.Min;
                eventQueue.Remove(popEvent);
                sweepY = popEvent.yCoord;
                if (removed.Contains(popEvent))
                {
                    removed.Remove(popEvent);
                    continue;
                }
                if (popEvent.GetType() == typeof(SiteEvent))
                {
                    AddArc(((SiteEvent)popEvent).mSite);
                }
                else
                {
                    RemoveArc((SqueezeEvent)popEvent);
                }
            }
            if (root != null)
            {
                CompleteEdge(root);
            }
        }
    }
    private void Generate()
    {
        // We'll use a sweeping algorithm to calculate the vertices and edges
        // Start with a priority queue for our events, initially storing
        // all our site events (each cell) sorted by y-coord
        SortedSet <VoronoiEvent> events = new SortedSet <VoronoiEvent>(new VoronoiEventComparer());

        foreach (Cell cell in diagram.cells)
        {
            events.Add(new SiteEvent
            {
                site = cell
            });
        }

        float     sweep = ConfigurationManager.Instance.height;
        BeachTree beach = new BeachTree(ConfigurationManager.Instance.width, ConfigurationManager.Instance.height, diagram, events);

        while (events.Count > 0)
        {
            VoronoiEvent e = events.Min;
            events.Remove(e);

            sweep       = e.pos.y;
            beach.sweep = e.pos.y;

            if (e.GetType() == typeof(SiteEvent))
            {
                SiteEvent se = (SiteEvent)e;
                beach.Insert(se.site);
            }
            else
            {
                VertexEvent ve = (VertexEvent)e;
                beach.Remove(ve);
            }
        }
        beach.Finish();

        List <Edge> halves = diagram.edges.Where(e => e.section != null).ToList();

        foreach (Edge e in halves)
        {
            e.start.edges.Remove(e);
            e.start = e.section.end;
            e.section.left.edges.Remove(e.section);
            e.section.right.edges.Remove(e.section);
            e.section.end.edges.Remove(e.section);
            e.section.start.edges.Remove(e.section);
            diagram.edges.Remove(e.section);
        }

        FixDiagram();

        Debug.Log("Done");

        ConstructMap();
    }
 public VoronoiArcNode(Vector2 focus)
 {
     mFocus       = focus;
     squeezeEvent = null;
 }
Ejemplo n.º 4
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);
    }
Ejemplo n.º 5
0
    // Update is called once per frame
    void Update()
    {
        // Destroy existing gameobjects
        foreach (Transform t in point_objects)
        {
            Destroy(t.gameObject);
        }
        point_objects.Clear();

        foreach (Transform t in line_objects)
        {
            Destroy(t.gameObject);
        }
        line_objects.Clear();


        if (randomize)
        {
            UnityEngine.Random.InitState(seed);

            points.Clear();
            // Generate points
            for (int i = 0; i < num_points; i++)
            {
                Vector2 point = new Vector2(
                    UnityEngine.Random.Range(
                        (-x_range / 2) - edge_size, (x_range / 2) + edge_size
                        ),
                    UnityEngine.Random.Range(
                        (-y_range / 2) - edge_size, (y_range / 2) + edge_size
                        ));

                points.Add(point);
            }
        }



        // Add points to event list
        foreach (Vector2 point in points)
        {
            events.Add(new VoronoiEvent(point));
        }

        // Sort events by y_value
        events.Sort();

        bool complete_early = false;
        int  iterations     = 0;

        beachLine = new BeachLine();
        while (!(events.Count == 0) && !complete_early)
        {
            VoronoiEvent e = events[0]; // Get first event

            // Update directrix for beach line
            beachLine.SetDirectrix(e.y_value);

            if (beachLine.root == null)
            {
                // This is the first event
                beachLine.Add(new BeachLineArc(new Arc(e.site, e.y_value)));
            }
            // If site event
            else if (e.IsSiteEvent())
            {
                // Create new arc
                //Arc newArc = new Arc(e.site, e.y_value);

                Vector2 intersection = Vector2.zero;
                Vector2 direction    = Vector2.zero;

                BeachLineArc arcToSplit = beachLine.GetArcAtX(e.site.x, out intersection, out direction);

                if (arcToSplit != null)
                {
                    Arc newLeftArc = new Arc(arcToSplit.arc.focus, arcToSplit.arc.directrix);
                    newLeftArc.start_x = arcToSplit.arc.start_x;
                    newLeftArc.end_x   = e.site.x;
                    BeachLineArc newLeftBLArc = new BeachLineArc(newLeftArc);

                    Arc newRightArc = new Arc(arcToSplit.arc.focus, arcToSplit.arc.directrix);
                    newRightArc.start_x = e.site.x;
                    newRightArc.end_x   = arcToSplit.arc.end_x;
                    BeachLineArc newRightBLArc = new BeachLineArc(newRightArc);

                    Edge          newLeftEdge    = new Edge(intersection, direction, 0);
                    Edge          newRightEdge   = new Edge(intersection, -direction, 0);
                    BeachLineEdge newLeftBLEdge  = new BeachLineEdge(newLeftEdge);
                    BeachLineEdge newRightBLEdge = new BeachLineEdge(newRightEdge);

                    BeachLineElement parentElement = arcToSplit.parent;
                    bool             isLeft        = false;
                    if (parentElement != null)
                    {
                        if (parentElement.leftChild == arcToSplit)
                        {
                            isLeft = true;
                        }
                    }

                    arcToSplit.parent         = newRightBLEdge;
                    newRightBLEdge.leftChild  = arcToSplit;
                    newRightBLArc.parent      = newRightBLEdge;
                    newRightBLEdge.rightChild = newRightBLArc;
                    newRightBLEdge.parent     = newLeftBLEdge;
                    newLeftBLEdge.rightChild  = newRightBLEdge;
                    newLeftBLArc.parent       = newLeftBLEdge;
                    newLeftBLEdge.leftChild   = newLeftBLArc;

                    if (parentElement == null)
                    {
                        beachLine.root       = newLeftBLEdge;
                        newLeftBLEdge.parent = null;
                    }
                    else
                    {
                        newLeftBLEdge.parent = parentElement;
                        if (isLeft)
                        {
                            parentElement.leftChild = newLeftBLEdge;
                        }
                        else
                        {
                            parentElement.rightChild = newLeftBLEdge;
                        }
                    }
                }

                //Arc leftArc = arcToSplit.SplitLeft(e.site.x);
                //Arc rightArc = arcToSplit.SplitRight(e.site.x);

                //// Direction should always point left
                //BeachLineEdge leftEdge = new BeachLineEdge(new Edge(intersection, direction, 0));
                //BeachLineEdge rightEdge = new BeachLineEdge(new Edge(intersection, -direction, 0));

                ////beachLine.Add(new BeachLineArc(newArc));

                //arcToSplit.ReplaceWith(leftEdge);
                //leftEdge.SetLeftChild(new BeachLineArc(leftArc));
                //leftEdge.SetRightChild(rightEdge);
                //rightEdge.SetLeftChild(new BeachLineArc(rightArc));

                // This arc is going to split existing arc
                // We will end of with a left/right arc, plus a left right edge
            }

            // Event handled. Remove event from list.
            events.RemoveAt(0);
            iterations++;


            if (iterations == max_iterations)
            {
                complete_early = true;
            }
        }
        beachLine.Draw(transform.position);



        foreach (Vector2 point in points)
        {
            Transform point_object = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
            point_object.parent        = transform;
            point_object.localScale    = new Vector3(point_size, point_size, point_size);
            point_object.localPosition = new Vector3(point.x, point.y, 0f);

            point_objects.Add(point_object);
        }

        // TEST
        Transform newLine = CreateLine(points[0], points[1]);

        line_objects.Add(newLine);

        //foreach(Vector2 point in points)
        //{
        //    if(point != points[0])
        //    {
        //        Transform newLine = CreateLine(point, points[0]);
        //        line_objects.Add(newLine);
        //    }
        //}
    }
    private IEnumerator GenerateVisualized()
    {
        // We'll use a sweeping algorithm to calculate the vertices and edges
        // Start with a priority queue for our events, initially storing
        // all our site events (each cell) sorted by y-coord
        SortedSet <VoronoiEvent> events = new SortedSet <VoronoiEvent>(new VoronoiEventComparer());

        foreach (Cell cell in diagram.cells)
        {
            events.Add(new SiteEvent
            {
                site = cell
            });
        }

        float     sweep = ConfigurationManager.Instance.height;
        BeachTree beach = new BeachTree(ConfigurationManager.Instance.width, ConfigurationManager.Instance.height, diagram, events);


        GameObject        sweepObj    = Instantiate(sweepPrefab, lineRenderersContainer);
        LineRenderer      sweepRend   = sweepObj.GetComponentInChildren <LineRenderer>();
        GameObject        eventObj    = Instantiate(eventPrefab, verticesContainer);
        List <GameObject> beachObjs   = new List <GameObject>();
        List <GameObject> diagramObjs = new List <GameObject>();

        foreach (Cell cell in diagram.cells)
        {
            GameObject cellGObject = Instantiate(cellPrefab, cellsContainer);
            cellGObject.transform.localPosition = cell.pos;
            cellGObject.transform.GetComponentInChildren <TextMeshPro>().text = cell.name;
            // TODO implement CellController and initialize it
        }

        //MakeBeach(beachObjs, beach.GetPoints(sweep));

        sweepRend.SetPositions(new Vector3[] { new Vector2(0, sweep), new Vector2(ConfigurationManager.Instance.width, sweep) });
        yield return(new WaitForSeconds(0.05f));

        while (events.Count > 0)
        {
            VoronoiEvent e = events.Min;
            events.Remove(e);
            eventObj.transform.localPosition = e.pos;
            while (sweep - 0.1f > e.pos.y)
            {
                sweep       = sweep - 0.1f;
                beach.sweep = sweep;

                sweepRend.SetPositions(new Vector3[] { new Vector2(0, sweep), new Vector2(ConfigurationManager.Instance.width, sweep) });
                MakeVoronoi(diagramObjs);
                MakeBeach(beachObjs, beach.GetBeachPoints());
                yield return(new WaitForSeconds(0.1f));
            }
            sweep       = e.pos.y;
            beach.sweep = e.pos.y;

            sweepRend.SetPositions(new Vector3[] { new Vector2(0, sweep), new Vector2(ConfigurationManager.Instance.width, sweep) });
            MakeVoronoi(diagramObjs);
            MakeBeach(beachObjs, beach.GetBeachPoints());
            yield return(new WaitForSeconds(0.1f));

            if (e.GetType() == typeof(SiteEvent))
            {
                SiteEvent se = (SiteEvent)e;
                beach.Insert(se.site);
            }
            else
            {
                VertexEvent ve = (VertexEvent)e;
                beach.Remove(ve);
            }
            MakeVoronoi(diagramObjs);
            MakeBeach(beachObjs, beach.GetBeachPoints());
            yield return(new WaitForSeconds(0.1f));
        }
        Debug.Log("Finished Events");
        beach.Finish();

        List <Edge> halves = diagram.edges.Where(e => e.section != null).ToList();

        foreach (Edge e in halves)
        {
            e.start.edges.Remove(e);
            e.start = e.section.end;
            e.section.left.edges.Remove(e.section);
            e.section.right.edges.Remove(e.section);
            e.section.end.edges.Remove(e.section);
            e.section.start.edges.Remove(e.section);
            diagram.edges.Remove(e.section);
        }

        FixDiagram();

        while (beachObjs.Count > 0)
        {
            Destroy(beachObjs[0]);
            beachObjs.RemoveAt(0);
        }
        while (diagramObjs.Count > 0)
        {
            Destroy(diagramObjs[0]);
            diagramObjs.RemoveAt(0);
        }
        // Construct current map
        ConstructMap();
    }