private void DrawSubdivision(Subdivision division) { // generate new random subdivision if desired if (division == null) { PointD offset = new PointD(OutputBox.Width * 0.2, OutputBox.Height * 0.2); SizeD scale = new SizeD(OutputBox.Width * 0.6, OutputBox.Height * 0.6); int count = MersenneTwister.Default.Next(4, 12); PointD[] points = new PointD[count]; for (int i = 0; i < points.Length; i++) { points[i] = new PointD( offset.X + MersenneTwister.Default.NextDouble() * scale.Width, offset.Y + MersenneTwister.Default.NextDouble() * scale.Height); } // outer bounds for Voronoi pseudo-vertices double margin = 3 * FontSize; RectD bounds = new RectD(margin, margin, OutputBox.Width - 2 * margin, OutputBox.Height - 2 * margin); var result = Voronoi.FindAll(points, bounds); division = result.ToVoronoiSubdivision().Source; } _division = division; _division.Validate(); _nearestEdge = -1; _edges = DrawSubdivision(OutputBox, FontSize, division); OutputBox.Children.Add(VertexCircle); }
public void VoronoiTest() { int count = MersenneTwister.Default.Next(10, 100); var points = new PointD[count]; for (int i = 0; i < points.Length; i++) { points[i] = GeoAlgorithms.RandomPoint(-1000, -1000, 2000, 2000); } var results = Voronoi.FindAll(points, new RectD(-1000, -1000, 2000, 2000)); var delaunay = results.ToDelaunySubdivision(); delaunay.Validate(); var voronoi = results.ToVoronoiSubdivision(); voronoi.Source.Validate(); // compare original and subdivision’s Delaunay edges var delaunayEdges = delaunay.ToLines(); Assert.AreEqual(results.DelaunayEdges.Length, delaunayEdges.Length); foreach (LineD edge in results.DelaunayEdges) { if (PointDComparerY.CompareExact(edge.Start, edge.End) > 0) { Assert.Contains(edge.Reverse(), delaunayEdges); } else { Assert.Contains(edge, delaunayEdges); } } // compare original and subdivision’s Voronoi regions var voronoiFaces = voronoi.Source.Faces; Assert.AreEqual(results.VoronoiRegions.Length, voronoiFaces.Count - 1); foreach (var face in voronoiFaces.Values) { if (face.OuterEdge == null) { continue; } int index = voronoi.FromFace(face); PointD[] polygon = results.VoronoiRegions[index]; CollectionAssert.AreEquivalent(polygon, face.OuterEdge.CyclePolygon); PointD site = results.GeneratorSites[index]; Assert.AreNotEqual(PolygonLocation.Outside, face.OuterEdge.Locate(site)); } }
public static GraphManager <PointD> CreateSubdivisionManager(GraphDialog dialog) { RectD output = new RectD(0, 0, dialog.OutputBox.Width, dialog.OutputBox.Height); RectD bounds = new RectD(8, 8, output.Width - 16, output.Height - 16); PointD[] points = GeoAlgorithms.RandomPoints(40, bounds, new PointDComparerX(), 20); VoronoiResults results = Voronoi.FindAll(points, output); Subdivision division = results.ToDelaunySubdivision(output, true); var manager = new GraphManager <PointD>(dialog, 8); manager.Graph = division; manager.Renderer = new GraphRenderer <PointD>(manager); // scaling factor to keep step costs above node distance manager._scaleCost = output.Width + output.Height; return(manager); }
private void DrawDiagrams(PointD[] points) { RectD bounds = new RectD(0, 0, OutputBox.Width, OutputBox.Height); // generate new random point set if desired if (points == null) { PointD offset = new PointD(bounds.Width * 0.1, bounds.Height * 0.1); SizeD scale = new SizeD(bounds.Width * 0.8, bounds.Height * 0.8); int count = MersenneTwister.Default.Next(4, 20); points = new PointD[count]; for (int i = 0; i < points.Length; i++) { points[i] = new PointD( offset.X + MersenneTwister.Default.NextDouble() * scale.Width, offset.Y + MersenneTwister.Default.NextDouble() * scale.Height); } } _points = points; var result = Voronoi.FindAll(points, bounds); OutputBox.Children.Clear(); // draw source points const double radius = 2.0; for (int i = 0; i < points.Length; i++) { Ellipse circle = new Ellipse() { Width = 2 * radius, Height = 2 * radius, Stroke = Brushes.Black, Fill = Brushes.Black }; Canvas.SetLeft(circle, points[i].X - radius); Canvas.SetTop(circle, points[i].Y - radius); OutputBox.Children.Add(circle); } // draw interior of Voronoi regions foreach (PointD[] region in result.VoronoiRegions) { Polygon polygon = new Polygon() { Points = region.ToWpfPoints(), Stroke = Brushes.White, StrokeThickness = 6.0, Fill = Brushes.PaleGoldenrod }; OutputBox.Children.Add(polygon); } // draw edges of Voronoi diagram foreach (VoronoiEdge edge in result.VoronoiEdges) { PointD start = result.VoronoiVertices[edge.Vertex1]; PointD end = result.VoronoiVertices[edge.Vertex2]; Line line = new Line() { X1 = start.X, Y1 = start.Y, X2 = end.X, Y2 = end.Y, Stroke = Brushes.Red }; OutputBox.Children.Add(line); } // draw edges of Delaunay triangulation foreach (LineD edge in result.DelaunayEdges) { Line line = new Line() { X1 = edge.Start.X, Y1 = edge.Start.Y, X2 = edge.End.X, Y2 = edge.End.Y, Stroke = Brushes.Blue, StrokeDashArray = { 3.0, 2.0 } }; OutputBox.Children.Add(line); } }