Exemplo n.º 1
0
        public void TestFindCircleEventAbove()
        {
            var beachLine = new BeachLine(0);
            var site1     = new Point {
                X = 130, Y = 160
            };
            var site2 = new Point {
                X = 110, Y = 150
            };
            var site3 = new Point {
                X = 170, Y = 140
            };
            var site4 = new Point {
                X = 140, Y = 120
            };


            beachLine.InsertSite(site1);
            //beachLine.GenerateCircleEvent(site1);
            beachLine.InsertSite(site2);
            //beachLine.GenerateCircleEvent(site2);
            var insert = beachLine.InsertSite(site3);

            var circleEvents = beachLine.GenerateCircleEvent(insert.Leaves, site3.Y);
            var result       = beachLine.FindCircleEventAbove(site4);

            Assert.IsNotNull(result);
            Assert.AreEqual(circleEvents.Single().Point, result.Point);
        }
Exemplo n.º 2
0
        public void TestRemoveLeaf()
        {
            var beachLine = new BeachLine(0);
            var site1     = new Point {
                X = 40, Y = 60
            };
            var site2 = new Point {
                X = 20, Y = 40
            };
            var site3 = new Point {
                X = 60, Y = 40
            };

            beachLine.InsertSite(site1);
            beachLine.InsertSite(site2);
            var insert = beachLine.InsertSite(site3);

            var circleEvents = beachLine.GenerateCircleEvent(insert.Leaves, site3.Y);
            var circleEvent  = circleEvents.Single();

            beachLine.RemoveLeaf(circleEvent.Arc);

            var rightSubtree = ((Node)beachLine.Root).Right as Node;
            var leafLeft     = rightSubtree.Left as Leaf;
            var leafRight    = rightSubtree.Right as Leaf;

            Assert.IsNotNull(leafLeft);
            Assert.IsNotNull(leafRight);

            Assert.AreEqual(rightSubtree.Breakpoint.Left, site3);
            Assert.AreEqual(rightSubtree.Breakpoint.Right, site1);
            Assert.AreEqual(leafLeft.Site, site3);
            Assert.AreEqual(leafRight.Site, site1);
        }
Exemplo n.º 3
0
        public void TestGenerateCircleEvent()
        {
            var beachLine = new BeachLine(0);
            var site1     = new Point {
                X = 130, Y = 160
            };
            var site2 = new Point {
                X = 110, Y = 150
            };
            var site3 = new Point {
                X = 170, Y = 140
            };

            beachLine.InsertSite(site1);
            beachLine.InsertSite(site2);
            var insert = beachLine.InsertSite(site3);

            var expectedCricleEvent = new Point {
                X = 136, Y = 84
            };

            var result = beachLine.GenerateCircleEvent(insert.Leaves, site3.Y);

            Assert.IsNotNull(result);
            Assert.AreEqual(1, result.Count);
            Assert.AreEqual(expectedCricleEvent.XInt, result.Single().Point.XInt);
            Assert.AreEqual(expectedCricleEvent.YInt, result.Single().Point.YInt);
            //Assert.AreEqual(site2, result.Single().LeftArc.Site);
            Assert.AreEqual(site1, result.Single().Arc.Site);
            //Assert.AreEqual(site3, result.Single().RightArc.Site);
        }
Exemplo n.º 4
0
        public void TestGenerateCircleEventZeroLengthArc()
        {
            var beachLine = new BeachLine(2000);
            var site1     = new Point {
                X = 40, Y = 60
            };
            var site2 = new Point {
                X = 20, Y = 40
            };
            var site3 = new Point {
                X = 60, Y = 40
            };

            beachLine.InsertSite(site1);
            beachLine.InsertSite(site2);
            var insert = beachLine.InsertSite(site3);

            var expectedCricleEvent = new Point {
                X = 40, Y = 20
            };

            var result = beachLine.GenerateCircleEvent(insert.Leaves, site3.Y);

            Assert.IsNotNull(result);
            Assert.AreEqual(1, result.Count);
            Assert.AreEqual(expectedCricleEvent, result.Single().Point);
            //Assert.AreEqual(site2, result.Single().LeftArc.Site);
            Assert.AreEqual(site1, result.Single().Arc.Site);
            //Assert.AreEqual(site3, result.Single().RightArc.Site);
        }
Exemplo n.º 5
0
    public Vector2[][] GenerateVoronoi(Vector2[] points, Vector2 center)
    {
        eq.ClearAll();
        Cell[] allCells;

        float boundaryLow   = -1;
        float boundaryHigh  = 1;
        float boundaryLeft  = -1;
        float boundaryRight = 1;

        // Read input points.
        allCells = new Cell[points.Length];

        for (int i = 0; i < points.Length; i++)
        {
            float x = points[i].x;
            float y = points[i].y;
            allCells[i] = new Cell(0, i, x, y);
            eq.Enqueue(allCells[i]);
        }

        Vector2   centerV2 = new Vector2(center.x, center.y);
        BeachLine BL       = new BeachLine(allCells, centerV2);

        float lastY = float.MaxValue;

        while (!eq.IsEmpty())
        {
            Site eventP = eq.Dequeue();

            if (eventP.type == 0)
            {
                BL.Insert(eventP);
            }
            else if (eventP.type == 1)
            {
                BL.HandleVVEvent((VoronoiVertexPoint)eventP);
            }

            BL.Print();
        }

        Vector2[][] OutputPoints = new Vector2[points.Length][];

        for (uint i = 0; i < points.Length; ++i)
        {
            Cell cell = allCells[i];
            cell.HandleEdges(boundaryHigh, boundaryLow, boundaryLeft, boundaryRight);
            cell.Sort();

            OutputPoints[i] = new Vector2[cell.relatedVoronoiVertex.Count];
            for (int j = 0; j < cell.relatedVoronoiVertex.Count; ++j)
            {
                OutputPoints[i][j] = new Vector2(cell.relatedVoronoiVertex[j].x, cell.relatedVoronoiVertex[j].y + cell.relatedVoronoiVertex[j].radius);
            }
        }

        return(OutputPoints);
    }
Exemplo n.º 6
0
 // Use this for initialization
 void Start()
 {
     //points = new List<Vector2>();
     point_objects = new List <Transform>();
     line_objects  = new List <Transform>();
     events        = new List <VoronoiEvent>();
     beachLine     = new BeachLine();
 }
Exemplo n.º 7
0
        public static LinkedList <VEdge> Run(List <FortuneSite> sites, double minX, double minY, double maxX, double maxY)
        {
            var eventQueue = new MinHeap <FortuneEvent>(5 * sites.Count);

            foreach (var s in sites)
            {
                eventQueue.Insert(new FortuneSiteEvent(s));
            }
            //init tree
            var beachLine = new BeachLine();
            var edges     = new LinkedList <VEdge>();
            var deleted   = new HashSet <FortuneCircleEvent>();

            //init edge list
            while (eventQueue.Count != 0)
            {
                var fEvent = eventQueue.Pop();
                if (fEvent is FortuneSiteEvent)
                {
                    beachLine.AddBeachSection((FortuneSiteEvent)fEvent, eventQueue, deleted, edges);
                }
                else
                {
                    if (deleted.Contains((FortuneCircleEvent)fEvent))
                    {
                        deleted.Remove((FortuneCircleEvent)fEvent);
                    }
                    else
                    {
                        beachLine.RemoveBeachSection((FortuneCircleEvent)fEvent, eventQueue, deleted, edges);
                    }
                }
            }


            //clip edges
            var edgeNode = edges.First;

            while (edgeNode != null)
            {
                var edge = edgeNode.Value;
                var next = edgeNode.Next;

                var valid = ClipEdge(edge, minX, minY, maxX, maxY);
                if (!valid)
                {
                    edges.Remove(edgeNode);
                }
                //advance
                edgeNode = next;
            }
            return(edges);
        }
Exemplo n.º 8
0
    public LinkedList <Edge> GenerateVoronoi(List <FortuneSite> sites, double minX, double minY, double maxX, double maxY)
    {
        MinHeap <FortuneEvent> eventQueue = new MinHeap <FortuneEvent>(5 * sites.Count);

        foreach (FortuneSite site in sites)
        {
            eventQueue.Insert(new FortuneSiteEvent(site));
        }

        BeachLine                    beachLine = new BeachLine();
        LinkedList <Edge>            edges     = new LinkedList <Edge>();
        HashSet <FortuneCircleEvent> deleted   = new HashSet <FortuneCircleEvent>();

        while (eventQueue.count != 0)
        {
            FortuneEvent fortuneEvent = eventQueue.Pop();

            if (fortuneEvent is FortuneSiteEvent)
            {
                beachLine.AddSection((FortuneSiteEvent)fortuneEvent, eventQueue, deleted, edges);
            }
            else
            {
                if (deleted.Contains((FortuneCircleEvent)fortuneEvent))
                {
                    deleted.Remove((FortuneCircleEvent)fortuneEvent);
                }
                else
                {
                    beachLine.RemoveBeachSection((FortuneCircleEvent)fortuneEvent, eventQueue, deleted, edges);
                }
            }
        }

        LinkedListNode <Edge> edgeNode = edges.First;

        while (edgeNode != null)
        {
            Edge edge = edgeNode.Value;
            LinkedListNode <Edge> nextNode = edgeNode.Next;

            if (!ClipEdge(edge, minX, minY, maxX, maxY))
            {
                edges.Remove(edgeNode);
            }

            edgeNode = nextNode;
        }

        return(edges);
    }
Exemplo n.º 9
0
        public void TestAddSingleLeaf()
        {
            var beachLine = new BeachLine(2000);
            var site      = new Point {
                X = 464, Y = 500
            };

            beachLine.InsertSite(site);

            var leaf = beachLine.Root as Leaf;

            Assert.IsNotNull(leaf);
            Assert.AreEqual(site, leaf.Site);
        }
Exemplo n.º 10
0
        public void DetachBeachSection(TreeNode beachSectionNode)
        {
            //this.detachCircleEvent(beachsection); // detach potentially attached circle event
            //this.beachline.rbRemoveNode(beachsection); // remove from RB-tree
            //this.beachsectionJunkyard.push(beachsection); // mark for reuse

            DetachCircleEvent(beachSectionNode);
            BeachLine.RemoveNode(beachSectionNode);

            //BeachLine.Dump("BeachLine removing node", beachLineCounter++);
            BeachLine.Dump("detachBeachSection, remove", beachLineCounter++);
            //dumpTree(this.beachline, "detachBeachSection, remove", beachLineCounter);
            beachLineCounter++;
        }
Exemplo n.º 11
0
        public void TestAddThreeLeaves()
        {
            var beachLine = new BeachLine(2000);
            var site1     = new Point {
                X = 20, Y = 1000
            };
            var site2 = new Point {
                X = 4000, Y = 500
            };
            var site3 = new Point {
                X = 464, Y = 64
            };

            beachLine.InsertSite(site1);
            beachLine.InsertSite(site2);
            beachLine.InsertSite(site3);

            var root = beachLine.Root as Node;

            Assert.IsNotNull(root);

            var nodeLeft         = root.Left as Node;
            var nodeLeftLeft     = nodeLeft.Left as Node;
            var nodeLeftLeftLeft = nodeLeftLeft.Left as Node;

            Assert.IsNotNull(nodeLeft);
            Assert.IsNotNull(nodeLeftLeft);
            Assert.IsNotNull(nodeLeftLeftLeft);

            var leafRight             = root.Right as Leaf;
            var leafLeftRight         = nodeLeft.Right as Leaf;
            var leafLeftLeftRight     = nodeLeftLeft.Right as Leaf;
            var leafLeftLeftLeftLeft  = nodeLeftLeftLeft.Left as Leaf;
            var leafLeftLeftLeftRight = nodeLeftLeftLeft.Right as Leaf;

            Assert.IsNotNull(leafRight);
            Assert.IsNotNull(leafLeftRight);
            Assert.IsNotNull(leafLeftLeftRight);
            Assert.IsNotNull(leafLeftLeftLeftLeft);
            Assert.IsNotNull(leafLeftLeftLeftRight);

            Assert.AreEqual(site1, leafRight.Site);
            Assert.AreEqual(site2, leafLeftRight.Site);
            Assert.AreEqual(site1, leafLeftLeftRight.Site);
            Assert.AreEqual(site1, leafLeftLeftLeftLeft.Site);
            Assert.AreEqual(site3, leafLeftLeftLeftRight.Site);
        }
Exemplo n.º 12
0
        public void TestAddTwoLeaves()
        {
            var beachLine = new BeachLine(2000);
            var site1     = new Point {
                X = 20, Y = 1000
            };
            var site2 = new Point {
                X = 464, Y = 500
            };

            beachLine.InsertSite(site1);
            beachLine.InsertSite(site2);

            var root = beachLine.Root as Node;

            Assert.IsNotNull(root);
            Assert.IsNotNull(root.HalfEdge);
            Assert.AreEqual(site1, root.HalfEdge.Right);
            Assert.AreEqual(site2, root.HalfEdge.Left);

            var nodeLeft = root.Left as Node;

            Assert.IsNotNull(nodeLeft);
            Assert.IsNotNull(nodeLeft.HalfEdge);
            Assert.AreEqual(site1, nodeLeft.HalfEdge.Left);
            Assert.AreEqual(site2, nodeLeft.HalfEdge.Right);

            var leafRight     = root.Right as Leaf;
            var leafLeftLeft  = nodeLeft.Left as Leaf;
            var leafLeftRight = nodeLeft.Right as Leaf;

            Assert.IsNotNull(leafRight);
            Assert.IsNotNull(leafLeftLeft);
            Assert.IsNotNull(leafLeftRight);

            Assert.AreEqual(site2, leafLeftRight.Site);
            Assert.AreEqual(site1, leafLeftLeft.Site);
            Assert.AreEqual(site1, leafRight.Site);

            Assert.AreEqual(root.Breakpoint.Left, site2);
            Assert.AreEqual(root.Breakpoint.Right, site1);
            Assert.AreEqual(nodeLeft.Breakpoint.Left, site1);
            Assert.AreEqual(nodeLeft.Breakpoint.Right, site2);
        }
Exemplo n.º 13
0
        public VoronoiMap CreateVoronoiMap(int height, int width, int pointQuantity)
        {
            _eventQueue = new EventQueue();
            _beachLine  = new BeachLine(height);

            try
            {
                var sites = _siteGenerator.GenerateSites(width, height, pointQuantity);
                return(CreateVoronoiMap(height, width, sites));
            }
            catch (Exception e)
            {
                _logger.Log(e.Message);
                _logger.Log(e.StackTrace);
                _logger.ToFile();

                return(null);
            }
        }
        public void TestHandleEvent()
        {
            var beachLine = new BeachLine(10);
            var center    = beachLine.InsertSite(new Point(4, 6));
            var right     = beachLine.InsertSite(new Point(6, 4));
            var left      = beachLine.InsertSite(new Point(2, 3));

            //var centerLeaf = ((Node)((Node)((Node)beachLine.Root).Left).Left).Right;

            //var sweepEvent = new CircleEvent
            //{
            //    LeftArc = new Leaf(new Point(2, 3)),
            //    CenterArc = left.Leaves[0],
            //    RightArc = new Leaf(new Point(6, 4)),
            //    Edges = new List<HalfEdge> {
            //        halfEdgesLeft[1],
            //        halfEdgesRight[1]
            //    },
            //    Point = new Point(4, 2),
            //    Vertex = new Point(4, 4)
            //};
            //var eventQueue = new EventQueue();

            //var strategy = new CircleEventHandlerStrategy();
            //var result = strategy.HandleEvent(sweepEvent, eventQueue, beachLine).ToList();

            //Assert.IsNotNull(result);
            //var vertex = ((Vertex)result.Single(g => g is Vertex));
            //Assert.AreEqual(sweepEvent.Vertex, vertex.Point);
            //Assert.AreEqual(3, vertex.HalfEdges.Count);

            //var start = vertex.HalfEdges.Single(h => h.Start != null);
            //Assert.IsNull(start.End);
            //Assert.AreEqual(new Point(2, 3), start.Left);
            //Assert.AreEqual(new Point(6, 4), start.Right);

            //var ends = vertex.HalfEdges.Where(h => h.End != null);
            //Assert.AreEqual(2, ends.Count());
            //Assert.IsTrue(!ends.Contains(start));
            //Assert.IsTrue(ends.All(h => h.Start == null));
        }
Exemplo n.º 15
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);
        //    }
        //}
    }
Exemplo n.º 16
0
        public ICollection <IGeometry> HandleEvent(CircleEvent sweepEvent, EventQueue eventQueue, BeachLine beachLine)
        {
            if (sweepEvent.Arc.Parent == null)
            {
                throw new InvalidOperationException($"CircleEvent: Arc {sweepEvent.Arc.Site}: Parent of node {0} is null");
            }

            var leftParent  = sweepEvent.Arc.GetParent(TraverseDirection.CounterClockwise);
            var rightParent = sweepEvent.Arc.GetParent(TraverseDirection.Clockwise);
            var left        = leftParent?.GetLeaf(TraverseDirection.CounterClockwise);
            var right       = rightParent?.GetLeaf(TraverseDirection.Clockwise);

            if (left == null || right == null)
            {
                throw new InvalidOperationException($"Neighbor of node {sweepEvent.Arc.Site} is null.");
            }

            if (left.CircleEvent != null)
            {
                eventQueue.Remove(left.CircleEvent);
                left.CircleEvent = null;
            }
            if (right.CircleEvent != null)
            {
                eventQueue.Remove(right.CircleEvent);
                right.CircleEvent = null;
            }

            var p = new Point(sweepEvent.Point.X, _calculationService.GetY(sweepEvent.Arc.Site, sweepEvent.Point));

            leftParent.HalfEdge.EndPoint  = p;
            rightParent.HalfEdge.EndPoint = p;

            var vertex = new Vertex {
                Point = p
            };

            ConnectHalfEdgeWithVertex(leftParent.HalfEdge, vertex, (e, v) => e.End  = v);
            ConnectHalfEdgeWithVertex(rightParent.HalfEdge, vertex, (e, v) => e.End = v);

            // Add third half edge
            var halfEdge = new HalfEdge(p, left.Site, right.Site);

            ConnectHalfEdgeWithVertex(halfEdge, vertex, (e, v) => e.Start = v);
            Logger.Instance.Log($"Left parent: {leftParent.HalfEdge}");
            Logger.Instance.Log($"Right parent: {rightParent.HalfEdge}");
            var higher = sweepEvent.Arc.GetFirstParent(leftParent, rightParent);

            Logger.Instance.Log($"Higher node: {higher}");
            Logger.Instance.Log($"Higher edge old: {higher.HalfEdge}");
            higher.HalfEdge = halfEdge;

            if (vertex.HalfEdges.Count != 3)
            {
                var message = $"Halfedge {halfEdge} is already connected to Vertex {vertex}";
                Logger.Instance.Log(message);
                Logger.Instance.ToFile();
                throw new InvalidOperationException(message);
            }

            Logger.Instance.Log($"CircleEvent: Remove Arc {sweepEvent.Arc.Site}");
            beachLine.RemoveLeaf(sweepEvent.Arc);

            var circleEvents = beachLine.GenerateCircleEvent(new[] { left, right }, sweepEvent.Point.Y);

            eventQueue.Insert(circleEvents);

            return(new List <IGeometry> {
                vertex, halfEdge
            });
        }
Exemplo n.º 17
0
        public VoronoiMap CreateVoronoiMap(int height, int width, IEnumerable <Site> sites)
        {
            if (sites == null)
            {
                throw new ArgumentNullException("sites");
            }

            if (sites.GroupBy(s => s.Point).Count() != sites.Count())
            {
                throw new ArgumentException("Multiple sites with the same coordinates passed!");
            }

            var siteList = string.Join(", ", sites.Select(s => s.Point.ToString()).ToArray());

            _logger.Log($"Create Voronoi map with sites: {siteList}");

            _eventQueue = new EventQueue();
            _beachLine  = new BeachLine(height);
            var map = new VoronoiMap();

            _eventQueue.Initialize(sites.Select(s => s.Point));
            map.AddRange(sites.Cast <IGeometry>());

            while (_eventQueue.HasEvents)
            {
                var sweepEvent = _eventQueue.GetNextEvent();

                var siteEvent = sweepEvent as SiteEvent;
                if (siteEvent != null)
                {
                    _logger.Log($"Sweepline SiteEvent: {siteEvent.Point}");
                    var halfEdges = _siteEventHandler.HandleEvent(siteEvent, _eventQueue, _beachLine);
                    map.AddRange(halfEdges);

                    foreach (var geo in halfEdges)
                    {
                        _logger.Log($"Add {geo}");
                    }

                    continue;
                }

                var circleEvent = sweepEvent as CircleEvent;
                if (circleEvent == null)
                {
                    throw new InvalidOperationException("SweepEvent is neither SiteEvent nor CircleEvent");
                }

                //_logger.Log($"Sweepline CircleEvent: {circleEvent.Point} for arc {circleEvent.Arc.Site}");
                var circleEventResult = _circleEventHandler.HandleEvent(circleEvent, _eventQueue, _beachLine);

                foreach (var geo in circleEventResult)
                {
                    _logger.Log($"Add {geo}");
                }

                // Add vertex and new half edge
                map.AddRange(circleEventResult);
            }

            _beachLine.FinishEdge(_beachLine.Root, width);

            //map.FinishEdges(width);

            map.ConnectEdges();

            _logger.Log("Finished Voronoi map creation");

            foreach (var edge in map.Where(g => g is HalfEdge).Cast <HalfEdge>())
            {
                _logger.Log(edge.ToString());
            }

            return(map);
        }
Exemplo n.º 18
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);
    }
Exemplo n.º 19
0
 public void SetBeachLine(BeachLine beachLine)
 {
     mBeachLine = beachLine;
 }
Exemplo n.º 20
0
        public void AddBeachSection(Site site)
        {
            //var x = site.x,
            //    directrix = site.y;

            var x   = site.X;
            var dir = site.Y;

            //var lArc, rArc,
            //    dxl, dxr,
            //    node = this.beachline.root;

            TreeNode lArc = null, rArc = null;
            double   dxl, dxr;
            TreeNode node = BeachLine.root;

            while (node != null)
            {
                //    dxl = this.leftBreakPoint(node, directrix) - x;
                dxl = GetLeftBreakPoint(node.BeachSection, node, dir) - x;

                //    // x lessThanWithEpsilon xl => falls somewhere before the left edge of the beachsection
                //    if (dxl > 1e-9)
                //    {
                //        node = node.rbLeft;
                //    }
                //    else
                //    {
                if (dxl > epsilon)
                {
                    node = node.Left;
                }
                else
                {
                    //        dxr = x - this.rightBreakPoint(node, directrix);
                    dxr = x - GetRightBreakPoint(node.BeachSection, node, dir);

                    //        // x greaterThanWithEpsilon xr => falls somewhere after the right edge of the beachsection
                    //        if (dxr > 1e-9)
                    //        {
                    //            if (!node.rbRight)
                    //            {
                    //                lArc = node;
                    //                break;
                    //            }
                    //            node = node.rbRight;
                    //        }
                    if (dxr > epsilon)
                    {
                        if (node.Right == null)
                        {
                            lArc = node;
                            break;
                        }

                        node = node.Right;
                    }
                    else
                    {
                        if (dxl > -epsilon)
                        {
                            lArc = node.Previous;
                            rArc = node;
                        }
                        else if (dxr > -epsilon)
                        {
                            lArc = node;
                            rArc = node.Next;
                        }
                        else
                        {
                            lArc = node;
                            rArc = node;
                        }
                        break;
                    }

                    //        else
                    //        {
                    //            // x equalWithEpsilon xl => falls exactly on the left edge of the beachsection
                    //            if (dxl > -1e-9)
                    //            {
                    //                lArc = node.rbPrevious;
                    //                rArc = node;
                    //            }
                    //            // x equalWithEpsilon xr => falls exactly on the right edge of the beachsection
                    //            else if (dxr > -1e-9)
                    //            {
                    //                lArc = node;
                    //                rArc = node.rbNext;
                    //            }
                    //            // falls exactly somewhere in the middle of the beachsection
                    //            else
                    //            {
                    //                lArc = rArc = node;
                    //            }
                    //            break;
                    //        }

                    //    }
                }
            }

            //var newArc = this.createBeachsection(site);
            //this.beachline.rbInsertSuccessor(lArc, newArc);

            var newArc     = CreateBeachSection(site);
            var newArcNode = new TreeNode {
                BeachSection = newArc, X = site.X, Y = site.Y, Site = site
            };

            BeachLine.InsertSuccessor(lArc, newArcNode);

            //dumpTree(this.beachline, "BeachLine, addBeachSection first insert", beachLineCounter);
            BeachLine.Dump("BeachLine, addBeachSection first insert", beachLineCounter++);

            //if (!lArc && !rArc)
            //{
            //    return;
            //}

            if (lArc == null && rArc == null)
            {
                return;
            }

            //if (lArc === rArc)
            //{
            //    this.detachCircleEvent(lArc);

            //    rArc = this.createBeachsection(lArc.site);
            //    this.beachline.rbInsertSuccessor(newArc, rArc);

            //    newArc.edge = rArc.edge = this.createEdge(lArc.site, newArc.site);

            //    this.a--ttachCircleEvent(lArc);
            //    this.a--ttachCircleEvent(rArc);
            //    return;
            //}

            if (lArc == rArc)
            {
                DetachCircleEvent(lArc);

                var s = lArc.BeachSection.Site;
                rArc = new TreeNode {
                    BeachSection = CreateBeachSection(s), X = s.X, Y = s.Y, Site = s
                };
                BeachLine.InsertSuccessor(newArcNode, rArc);
                BeachLine.Dump("BeachLine, addBeachSection second insert", beachLineCounter++);

                newArc.Edge            = CreateEdge(lArc.BeachSection.Site, newArc.Site, null, null);
                rArc.BeachSection.Edge = newArc.Edge;

                AttachCircleEvent(lArc);
                AttachCircleEvent(rArc);
                return;
            }

            //if (lArc && !rArc)
            //{
            //    newArc.edge = this.createEdge(lArc.site, newArc.site);
            //    return;
            //}

            if (lArc != null && rArc == null)
            {
                newArc.Edge = CreateEdge(lArc.BeachSection.Site, newArc.Site, null, null);
                return;
            }

            ////if (!lArc && rArc) {
            ////    throw "Voronoi.addBeachsection(): What is this I don't even";
            ////    }
            ///
            if (lArc == null && rArc != null)
            {
                Console.WriteLine("SHOULD NOT HAPPEN");
            }

            //if (lArc !== rArc)
            //{
            //    this.detachCircleEvent(lArc);
            //    this.detachCircleEvent(rArc);

            //    var lSite = lArc.site,
            //        ax = lSite.x,
            //        ay = lSite.y,
            //        bx = site.x - ax,
            //        by = site.y - ay,
            //        rSite = rArc.site,
            //        cx = rSite.x - ax,
            //        cy = rSite.y - ay,
            //        d = 2 * (bx * cy - by * cx),
            //        hb = bx * bx + by * by,
            //        hc = cx * cx + cy * cy,
            //        vertex = this.createVertex((cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay);

            //    this.setEdgeStartpoint(rArc.edge, lSite, rSite, vertex);

            //    newArc.edge = this.createEdge(lSite, site, undefined, vertex);
            //    rArc.edge = this.createEdge(site, rSite, undefined, vertex);

            //    this.a--ttachCircleEvent(lArc);
            //    this.a--ttachCircleEvent(rArc);
            //    return;
            //}

            if (lArc != rArc)
            {
                DetachCircleEvent(lArc);
                DetachCircleEvent(rArc);

                var lSite  = lArc.BeachSection.Site;
                var ax     = lSite.X;
                var ay     = lSite.Y;
                var bx     = site.X - ax;
                var by     = site.Y - ay;
                var rSite  = rArc.BeachSection.Site;
                var cx     = rSite.X - ax;
                var cy     = rSite.Y - ay;
                var d      = 2 * (bx * cy - by * cx);
                var hb     = bx * bx + by * by;
                var hc     = cx * cx + cy * cy;
                var vertex = CreateVertex((cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay);

                rArc.BeachSection.Edge = CreateEdge(lSite, site, null, vertex);

                newArc.Edge            = CreateEdge(lSite, site, null, vertex);
                rArc.BeachSection.Edge = CreateEdge(site, rSite, null, vertex);

                AttachCircleEvent(lArc);
                AttachCircleEvent(rArc);
                return;
            }
        }
Exemplo n.º 21
0
 public void Setup()
 {
     _eventQueue = new EventQueue();
     _beachLine  = new BeachLine(10);
     _strategy   = new SiteEventHandlerStrategy();
 }
Exemplo n.º 22
0
        public ICollection <IGeometry> HandleEvent(SiteEvent sweepEvent, EventQueue eventQueue, BeachLine beachLine)
        {
            var circleEvent = beachLine.FindCircleEventAbove(sweepEvent.Point);

            if (circleEvent != null)
            {
                Logger.Instance.Log($"SiteEvent: {sweepEvent.Point.ToString()}: Remove CircleEvent {circleEvent.Point} from queue.");
                eventQueue.Remove(circleEvent);
            }

            Logger.Instance.Log($"SiteEvent: {sweepEvent.Point.ToString()}: Insert site into beach line");
            var result = beachLine.InsertSite(sweepEvent.Point);

            var circleEvents = beachLine.GenerateCircleEvent(result?.Leaves, sweepEvent.Point.Y);

            eventQueue.Insert(circleEvents);

            if (result != null)
            {
                return new List <IGeometry> {
                           result.HalfEdge
                }
            }
            ;
            return(new List <IGeometry>());
        }
    }