static void Main(string[] args)
        {
            //Define a set of segments and pass them to the voronoi wrapper
            List <Segment> input = new List <Segment>();

            input.Add(new Segment(0, 0, 0, 10));
            input.Add(new Segment(0, 10, 10, 10));
            input.Add(new Segment(10, 10, 10, 0));
            input.Add(new Segment(10, 0, 0, 0));

            //Instanciate the voronoi wrapper
            using (BoostVoronoi bv = new BoostVoronoi())
            {
                //Add a point
                bv.AddPoint(5, 5);

                //Add the segments
                foreach (var s in input)
                {
                    bv.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);
                }

                //Build the C# Voronoi
                bv.Construct();

                //Get the voronoi output
                for (long i = 0; i < bv.CountCells; i++)
                {
                    Cell cell = bv.GetCell(i);
                    Console.Out.WriteLine(String.Format("Cell Identifier {0}. Is open = {1}", cell.Index, cell.IsOpen));
                    foreach (var edgeIndex in cell.EdgesIndex)
                    {
                        Edge edge = bv.GetEdge(edgeIndex);
                        Console.Out.WriteLine(
                            String.Format("  Edge Index: {0}. Start vertex index: {1}, End vertex index: {2}",
                                          edgeIndex,
                                          edge.Start,
                                          edge.End));

                        //If the vertex index equals -1, it means the edge is infinite. It is impossible to print the coordinates.
                        if (edge.IsLinear)
                        {
                            Vertex start = bv.GetVertex(edge.Start);
                            Vertex end   = bv.GetVertex(edge.End);

                            Console.Out.WriteLine(
                                String.Format("     From:{0}, To: {1}",
                                              start.ToString(),
                                              end.ToString()));
                        }
                    }
                }
            }
            Console.In.ReadLine();
        }
Пример #2
0
        public void TestInvalidVertexIndexException()
        {
            List <Point> inputPoint = new List <Point>()
            {
                new Point(5, 5)
            };
            List <Segment> inputSegment = new List <Segment>();

            inputSegment.Add(new Segment(0, 0, 0, 10));
            inputSegment.Add(new Segment(0, 0, 10, 0));
            inputSegment.Add(new Segment(0, 10, 10, 10));
            inputSegment.Add(new Segment(10, 0, 10, 10));

            //Build the C# Voronoi
            using (BoostVoronoi bv = new BoostVoronoi())
            {
                foreach (var p in inputPoint)
                {
                    bv.AddPoint(p.X, p.Y);
                }
                foreach (var s in inputSegment)
                {
                    bv.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);
                }

                bv.Construct();
                bv.GetVertex(bv.CountVertices);
            }
        }
Пример #3
0
        public static IReadOnlyList <TerrainNode> Analyze <TNode>(Map2D <TNode> map, Func <TNode, bool> isBlocking, int pruneDistanceToObstacleSquared, int maxDistanceToMergeSquared)
        {
            var tracingResult = ComponentLabeling.Trace(map, node => isBlocking(node) ? 1 : 0);

            var contours = new List <List <Point2D> >();

            foreach (var blob in tracingResult.Blobs)
            {
                contours.AddRange(
                    new[] { blob.ExternalContour }.Concat(blob.InternalContours).Select(
                        points => DouglasPeucker.Simplify(points.ToList(), 2 * 2, DistanceSquared)));
            }

            var edges        = new List <Edge>();
            var leftBorder   = new List <int>();
            var rightBorder  = new List <int>();
            var topBorder    = new List <int>();
            var bottomBorder = new List <int>();
            var wallsTree    = new RTree <Edge>(5, 9);

            using (var voronoi = new BoostVoronoi())
            {
                foreach (var contour in contours)
                {
                    var startPoint = contour.First();
                    foreach (var point in contour.Skip(1))
                    {
                        voronoi.AddSegment((int)startPoint.X, (int)startPoint.Y, (int)point.X, (int)point.Y);
                        wallsTree.Insert(new Edge {
                            Start = startPoint, End = point
                        }, new RTree <Edge> .Envelope(startPoint, point));

                        if ((int)startPoint.X == 0 && (int)point.X == 0)
                        {
                            leftBorder.Add((int)startPoint.Y);
                            leftBorder.Add((int)point.Y);
                        }

                        if ((int)startPoint.X == map.Width - 1 && (int)point.X == map.Width - 1)
                        {
                            rightBorder.Add((int)startPoint.Y);
                            rightBorder.Add((int)point.Y);
                        }

                        if ((int)startPoint.Y == 0 && (int)point.Y == 0)
                        {
                            topBorder.Add((int)startPoint.X);
                            topBorder.Add((int)point.X);
                        }

                        if ((int)startPoint.Y == map.Height - 1 && (int)point.Y == map.Height - 1)
                        {
                            bottomBorder.Add((int)startPoint.X);
                            bottomBorder.Add((int)point.X);
                        }

                        startPoint = point;
                    }
                }

                AddVerticalBorder(voronoi, wallsTree, leftBorder.OrderBy(x => x).ToList(), 0, map.Height - 1);
                AddVerticalBorder(voronoi, wallsTree, rightBorder.OrderBy(x => x).ToList(), map.Width - 1, map.Height - 1);
                AddHorizontalBorder(voronoi, wallsTree, topBorder.OrderBy(x => x).ToList(), 0, map.Width - 1);
                AddHorizontalBorder(voronoi, wallsTree, bottomBorder.OrderBy(x => x).ToList(), map.Height - 1, map.Width - 1);

                var visitedTwins = new List <long>();
                voronoi.Construct();
                for (long i = 0; i < voronoi.CountEdges; i++)
                {
                    var edge = voronoi.GetEdge(i);

                    if (!edge.IsPrimary || !edge.IsFinite || visitedTwins.Contains(edge.Twin))
                    {
                        continue;
                    }

                    visitedTwins.Add(edge.Twin);

                    var start = voronoi.GetVertex(edge.Start);
                    var end   = voronoi.GetVertex(edge.End);

                    if (double.IsNaN(start.X) || double.IsNaN(start.Y) || double.IsNaN(end.X) || double.IsNaN(end.Y))
                    {
                        continue;
                    }

                    if (edges.Any(
                            e => (int)e.Start.X == (int)start.X && (int)e.Start.Y == (int)start.Y &&
                            (int)e.End.X == (int)end.X && (int)e.End.Y == (int)end.Y ||
                            (int)e.Start.X == (int)end.X && (int)e.Start.Y == (int)end.Y &&
                            (int)e.End.X == (int)start.X && (int)e.End.Y == (int)start.Y))
                    {
                        continue;
                    }

                    edges.Add(new Edge
                    {
                        Start = new Point2D((int)start.X, (int)start.Y),
                        End   = new Point2D((int)end.X, (int)end.Y)
                    });
                }
            }

            var walkableEdges = edges.Where(edge => IsOnNonBlocking(edge, map, isBlocking)).ToList();

            var nodes = new List <InternalNode>();

            foreach (var node in walkableEdges)
            {
                if (node.Start == node.End)
                {
                    continue;
                }

                var startNode = nodes.Find(x => x.Point == node.Start);
                if (startNode == null)
                {
                    startNode = CreateNode(wallsTree, node.Start);
                    nodes.Add(startNode);
                }

                var endNode = nodes.Find(x => x.Point == node.End);
                if (endNode == null)
                {
                    endNode = CreateNode(wallsTree, node.End);
                    nodes.Add(endNode);
                }

                startNode.Neighbors.Add(endNode);
                endNode.Neighbors.Add(startNode);
            }

            PruneNodes(nodes, pruneDistanceToObstacleSquared);

            GetPointsOfInterest(nodes, pruneDistanceToObstacleSquared, maxDistanceToMergeSquared);

            var mergedNodes = MergeNodes(nodes, maxDistanceToMergeSquared);

            return(MapToTerrainNodes(mergedNodes, wallsTree));
        }
Пример #4
0
        public void TestSegmentDicretization()
        {
            List <Point> inputPoint = new List <Point>()
            {
                new Point(5, 5)
            };
            List <Segment> inputSegment = new List <Segment>();

            inputSegment.Add(new Segment(0, 0, 0, 10));
            inputSegment.Add(new Segment(0, 0, 10, 0));
            inputSegment.Add(new Segment(0, 10, 10, 10));
            inputSegment.Add(new Segment(10, 0, 10, 10));

            //Build the C# Voronoi
            using (BoostVoronoi bv = new BoostVoronoi())
            {
                foreach (var p in inputPoint)
                {
                    bv.AddPoint(p.X, p.Y);
                }
                foreach (var s in inputSegment)
                {
                    bv.AddSegment(s.Start.X, s.Start.Y, s.End.X, s.End.Y);
                }

                bv.Construct();

                long testEdgeIndex = 2;

                for (long i = 0; i < bv.CountEdges; i++)
                {
                    Edge edge = bv.GetEdge(i);
                    Edge twin = bv.GetEdge(edge.Twin);

                    Cell edgeCell = bv.GetCell(edge.Cell);
                    Cell twinCell = bv.GetCell(twin.Cell);

                    if (twinCell.SourceCategory == CellSourceCatory.SinglePoint
                        &&
                        edgeCell.Site == 1)
                    {
                        testEdgeIndex = i;
                    }
                }

                Edge          testEdge    = bv.GetEdge(testEdgeIndex);
                Vertex        startVertex = bv.GetVertex(testEdge.Start);
                Vertex        endVertex   = bv.GetVertex(testEdge.End);
                List <Vertex> dvertices   = bv.SampleCurvedEdge(testEdge, Distance.ComputeDistanceBetweenPoints(startVertex, endVertex) / 2);
                int           lastDicretizedVertexIndex = dvertices.Count - 1;

                //Make sure that the end points are consistents
                Assert.AreEqual(dvertices[0].X, startVertex.X);
                Assert.AreEqual(dvertices[0].Y, startVertex.Y);

                Assert.AreEqual(dvertices[lastDicretizedVertexIndex].X, endVertex.X);
                Assert.AreEqual(dvertices[lastDicretizedVertexIndex].Y, endVertex.Y);

                Assert.AreEqual(dvertices[2].X, 2.5);
                Assert.AreEqual(dvertices[2].Y, 5);
            }
        }