예제 #1
0
    public void ReplaceWithSingleNode(BeachLineElement newNode)
    {
        if (Parent != null)
        {
            newNode.SetParent(Parent);
            if (Parent.LeftChild == this)
            {
                Parent.SetLeftChild(newNode);
            }
            else
            {
                Parent.SetRightChild(newNode);
            }
        }
        else
        {
            // This is the root node
            mBeachLine.SetRoot(newNode);
        }

        if (LeftChild != null)
        {
            newNode.SetLeftChild(LeftChild);
            LeftChild.SetParent(newNode);
        }
        if (RightChild != null)
        {
            newNode.SetRightChild(RightChild);
            RightChild.SetParent(newNode);
        }
        mParent     = null;
        mLeftChild  = null;
        mRightChild = null;
    }
예제 #2
0
 public BeachLineElement LinkInsertAfter(BeachLineElement newElement)
 {
     if (Next != null)
     {
         Next.SetPrev(newElement);
         newElement.SetNext(Next);
     }
     SetNext(newElement);
     newElement.SetPrev(this);
     return(newElement);
 }
예제 #3
0
 public void Add(BeachLineElement newElement)
 {
     if (root == null)
     {
         root = newElement;
     }
     else
     {
         //
         // Find place for new element
         //if(newElement)
         //root.SetLeftChild(newElement);
     }
 }
예제 #4
0
 public void ReplaceWithSubTree(BeachLineElement newSubtreeParentNode)
 {
     if (Parent != null)
     {
         newSubtreeParentNode.SetParent(Parent);
         if (Parent.LeftChild == this)
         {
             Parent.SetLeftChild(newSubtreeParentNode);
         }
         else
         {
             Parent.SetRightChild(newSubtreeParentNode);
         }
     }
 }
예제 #5
0
    public void Split(BeachLineArc newArc)
    {
        float splitX    = newArc.Focus.x;
        float sweepLine = newArc.Focus.y;

        BeachLineArc newLeftArc    = new BeachLineArc(this);
        BeachLineArc newRightArc   = new BeachLineArc(this);
        Vector2      splitPoint    = new Vector2(splitX, y(splitX));
        Vector2      edgeDirection = Tangent(splitX);

        // Make edgeDirection always point in the positive x direction
        edgeDirection = edgeDirection.x < 0 ? -edgeDirection : edgeDirection;
        BeachLineEdge newLeftEdge  = new BeachLineEdge(splitPoint, -edgeDirection);
        BeachLineEdge newRightEdge = new BeachLineEdge(splitPoint, edgeDirection);

        newLeftEdge.SetLeftChild(newLeftArc);
        newLeftEdge.SetRightChild(newRightEdge);
        newLeftEdge.SetParent(Parent);
        newRightEdge.SetLeftChild(newArc);
        newRightEdge.SetRightChild(newRightArc);
        newRightEdge.SetParent(newLeftEdge);
        newLeftArc.SetParent(newLeftEdge);
        newRightArc.SetParent(newRightEdge);
        newArc.SetParent(newRightEdge);

        // Change next and prev links
        BeachLineEdge prevEdge = (BeachLineEdge)Prev;
        BeachLineEdge nextEdge = (BeachLineEdge)Next;

        LinkRemove();
        if (prevEdge != null)
        {
            prevEdge.LinkInsertAfter(newLeftArc);
        }
        else
        {
            // newLeftArc is going to be the new start of the list
            if (nextEdge != null)
            {
                newLeftArc.SetNext(nextEdge);
                nextEdge.SetPrev(newLeftArc);
            }
        }
        newLeftArc.LinkInsertAfter(newLeftEdge)
        .LinkInsertAfter(newArc)
        .LinkInsertAfter(newRightEdge)
        .LinkInsertAfter(newRightArc);
        //if (nextEdge != null)
        //{
        //    newRightArc.SetNext(nextEdge);
        //    nextEdge.SetPrev(newRightArc);
        //}

        BeachLineElement parent = Parent;

        if (parent == null)
        {
            // This is root. Replace this with left edge.
            BeachLineRoot.SetRoot(newLeftEdge);
        }
        else
        {
            // Set parent to point to new construct
            if (parent.LeftChild == this)
            {
                parent.SetLeftChild(newLeftEdge);
            }
            else if (parent.RightChild == this)
            {
                parent.SetRightChild(newLeftEdge);
            }
            else
            {
                Debug.LogError("Error in Split - couldn't find child in parent.");
            }
        }

        // We can now remove this node
        //SetLeftArc(null);
        //SetRightArc(null);
        //SetLeftEdge(null);
        //SetRightEdge(null);
        SetLeftChild(null);
        SetRightChild(null);
        SetParent(null);
    }
예제 #6
0
    public List <BeachLineEdge> Squeeze(out BeachLineEdge newEdge)
    {
        // These are the output edges
        BeachLineEdge leftEdge  = (BeachLineEdge)Prev;
        BeachLineEdge rightEdge = (BeachLineEdge)Next;
        BeachLineArc  leftArc   = (BeachLineArc)leftEdge.Prev;
        BeachLineArc  rightArc  = (BeachLineArc)rightEdge.Next;

        // Create new edge
        // To create it, we need the intersection point of the two output edges plus the
        // focuses of the two arcs.
        Vector2 intersection;

        leftEdge.CheckIntersection(rightEdge, out intersection);
        Vector2 focus1           = leftArc.Focus;
        Vector2 focus2           = rightArc.Focus;
        Vector2 perpendicular    = focus2 - focus1;
        Vector2 newEdgeDirection = new Vector2(perpendicular.y, -perpendicular.x);

        if (Vector2.Dot(leftEdge.Direction.normalized + rightEdge.Direction.normalized, -newEdgeDirection) > 0)
        //if (newEdgeDirection.y < 0)
        {
            newEdgeDirection = -newEdgeDirection;
        }

        newEdge = new BeachLineEdge(intersection, newEdgeDirection.normalized);


        BeachLineEdge edgeToReplace = leftEdge == Parent ? rightEdge : leftEdge;

        //newEdge.SetLeftArc(LeftArc);
        //newEdge.SetRightArc(RightArc);
        // Replace other edge with new edge
        edgeToReplace.ReplaceWithSingleNode(newEdge);

        // Replace parent with sibling

        BeachLineElement sibling = Sibling;

        sibling.SetParent(null);
        bool iAmLeftChild = this == Parent.LeftChild;

        if (iAmLeftChild)
        {
            Parent.SetRightChild(null);
        }
        else
        {
            Parent.SetLeftChild(null);
        }

        BeachLineElement parentsParent     = Parent.Parent;
        bool             parentIsLeftChild = Parent == parentsParent.LeftChild;

        if (parentIsLeftChild)
        {
            parentsParent.SetLeftChild(sibling);
        }
        else
        {
            parentsParent.SetRightChild(sibling);
        }
        sibling.SetParent(parentsParent);

        //Parent.ReplaceWith(Sibling);

        //Parent.SetLeftChild(null);
        //Parent.SetRightChild(null);

        // Set next/prev for altered nodes
        leftArc.SetNext(newEdge);
        newEdge.SetPrev(leftArc);
        newEdge.SetNext(rightArc);
        rightArc.SetPrev(newEdge);

        // Remove this node from tree
        SetParent(null);
        SetLeftChild(null);
        SetRightChild(null);
        SetNext(null);
        SetPrev(null);
        leftEdge.SetParent(null);
        leftEdge.SetLeftChild(null);
        leftEdge.SetRightChild(null);
        leftEdge.SetNext(null);
        leftEdge.SetPrev(null);
        rightEdge.SetParent(null);
        rightEdge.SetLeftChild(null);
        rightEdge.SetRightChild(null);
        rightEdge.SetNext(null);
        rightEdge.SetPrev(null);

        leftEdge.SetEndpoint(intersection);
        rightEdge.SetEndpoint(intersection);

        List <BeachLineEdge> outputList = new List <BeachLineEdge>
        {
            leftEdge,
            rightEdge
        };

        return(outputList);
    }
예제 #7
0
 public void SetParent(BeachLineElement newParent)
 {
     mParent = newParent;
 }
예제 #8
0
 public void SetRightChild(BeachLineElement newRightChild)
 {
     mRightChild = newRightChild;
 }
예제 #9
0
 public void SetLeftChild(BeachLineElement newLeftChild)
 {
     mLeftChild = newLeftChild;
 }
예제 #10
0
 public void SetPrev(BeachLineElement prev)
 {
     mPrev = prev;
 }
예제 #11
0
 public void SetNext(BeachLineElement next)
 {
     mNext = next;
 }
예제 #12
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);
    }
예제 #13
0
 public void SetRoot(BeachLineElement root)
 {
     mRoot = root;
     mRoot.SetBeachLine(this);
 }
예제 #14
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);
        //    }
        //}
    }