public void TestInvalidEdgeIndexException() { 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.GetEdge(bv.CountEdges); } }
public void TestPrimaryEdges() { 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(); int countPrimary = 0; int countSecondary = 0; int countFinite = 0; for (long i = 0; i < bv.CountEdges; i++) { Edge edge = bv.GetEdge(i); if (edge.IsPrimary) { countPrimary++; } if (edge.IsFinite) { countFinite++; } if (!edge.IsPrimary && edge.IsFinite) { countSecondary++; } } //8 finites from the center of the square corner + 8 edges arount the center point. Assert.AreEqual(countFinite, 16); //Check the number of secondary edge. Because this input is a square with a point in the center, the expected count is 0. Assert.AreEqual(countSecondary, 0); Assert.AreEqual(countPrimary, countFinite - countSecondary); } }
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(); }
public void TestSegmentTwin() { 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, 10, 10, 10)); inputSegment.Add(new Segment(10, 10, 10, 0)); inputSegment.Add(new Segment(10, 0, 0, 0)); //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(); //Test twin reciprocity for (long i = 0; i < bv.CountEdges; i++) { Edge edge = bv.GetEdge(i); Edge twin = bv.GetEdge(edge.Twin); Assert.AreEqual(i, twin.Twin); } } }
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)); }
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); } }