예제 #1
0
        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);
        }
예제 #2
0
        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));
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
            }
        }