예제 #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
        private void DrawSubdivision(Subdivision division)
        {
            // default to empty subdivision
            if (division == null)
            {
                division = new Subdivision();
            }

            _division = division;
            _division.Validate();
            SubdivisionTest.DrawSubdivision(OutputBox, FontSize, division);
        }
        private SubdivisionSearch CheckSearch(params LineD[] lines)
        {
            Subdivision division = Subdivision.FromLines(lines);

            division.Validate();
            SubdivisionSearch search = new SubdivisionSearch(division);

            search.Validate();
            CheckVertices(search);
            CheckEdges(search);

            PointD[] points = new[] {
                new PointD(+1, +1), new PointD(+1, -1),
                new PointD(-1, +1), new PointD(-1, -1)
            };

            if (division.Faces.Count == 1)
            {
                foreach (PointD point in points)
                {
                    Assert.IsTrue(search.Find(point).IsUnboundedFace);
                    Assert.IsTrue(division.Find(point).IsUnboundedFace);
                }
            }
            else
            {
                var element = new SubdivisionElement(division.Faces[1]);
                foreach (PointD point in points)
                {
                    Assert.AreEqual(element, search.Find(point));
                    Assert.AreEqual(element, division.Find(point));
                }
            }

            points = new[] {
                new PointD(+10, +10), new PointD(+10, -10),
                new PointD(-10, +10), new PointD(-10, -10)
            };

            foreach (PointD point in points)
            {
                Assert.IsTrue(search.Find(point).IsUnboundedFace);
                Assert.IsTrue(division.Find(point).IsUnboundedFace);
            }
            return(search);
        }
예제 #4
0
        /// <summary>
        /// Creates a random <see cref="Subdivision"/> with the specified number of full edges and
        /// comparison epsilon.</summary>
        /// <param name="size">
        /// The number of full edges, i.e. half the number of <see cref="Subdivision.Edges"/>, in
        /// the returned <see cref="Subdivision"/>.</param>
        /// <param name="epsilon">
        /// The maximum absolute difference at which two coordinates should be considered equal.
        /// </param>
        /// <returns>
        /// A new random <see cref="Subdivision"/> with the specified <paramref name="size"/> and
        /// <paramref name="epsilon"/>.</returns>

        private static Subdivision CreateSubdivision(int size, double epsilon)
        {
            LineD[] lines = new LineD[size];
            for (int i = 0; i < size; i++)
            {
                lines[i] = GeoAlgorithms.RandomLine(0, 0, 1000, 1000);
            }

            // split random set into non-intersecting line segments
            var crossings  = MultiLineIntersection.FindSimple(lines, epsilon);
            var splitLines = MultiLineIntersection.Split(lines, crossings);

            Array.Copy(splitLines, lines, size);

            // re-randomize lines to eliminate split ordering
            CollectionsUtility.Randomize(lines);
            Subdivision division = Subdivision.FromLines(lines);

            division.Validate();
            return(division);
        }
예제 #5
0
        private void OnIntersect(object sender, RoutedEventArgs args)
        {
            args.Handled = true;

            RectD  bounds = OutputBounds;
            double x      = bounds.Left + (double)LeftUpDown.Value;
            double y      = bounds.Top + (double)TopUpDown.Value;
            double dx     = (double)WidthUpDown.Value;
            double dy     = (double)HeightUpDown.Value;

            Subdivision rectangle;

            if (sender == RectangleButton)
            {
                rectangle = Subdivision.FromLines(new LineD[] {
                    new LineD(x, y, x + dx, y),
                    new LineD(x + dx, y, x + dx, y + dy),
                    new LineD(x + dx, y + dy, x, y + dy),
                    new LineD(x, y + dy, x, y)
                });
            }
            else if (sender == DiamondButton)
            {
                rectangle = Subdivision.FromLines(new LineD[] {
                    new LineD(x + dx / 2, y, x + dx, y + dy / 2),
                    new LineD(x + dx, y + dy / 2, x + dx / 2, y + dy),
                    new LineD(x + dx / 2, y + dy, x, y + dy / 2),
                    new LineD(x, y + dy / 2, x + dx / 2, y)
                });
            }
            else
            {
                return;
            }

            rectangle.Validate();
            _division = Subdivision.Intersection(_division, rectangle, out _faceKeys);
            _division.Validate();
            SubdivisionTest.DrawSubdivision(OutputBox, FontSize, _division);
        }
        private SubdivisionSearch CheckSearch(Subdivision division)
        {
            division.Validate();
            SubdivisionSearch search = new SubdivisionSearch(division);

            search.Validate();
            CheckVertices(search);
            CheckEdges(search);

            foreach (SubdivisionFace face in division.Faces.Values)
            {
                if (face.OuterEdge == null)
                {
                    continue;
                }
                PointD centroid = face.OuterEdge.CycleCentroid;
                var    element  = new SubdivisionElement(face);
                Assert.AreEqual(element, search.Find(centroid));
                Assert.AreEqual(element, division.Find(centroid));
            }

            return(search);
        }
예제 #7
0
        public static Subdivision CreateTriforce(bool test)
        {
            PointD[] points =
            {
                new PointD(-5, -4), new PointD(0,  6), new PointD(5, -4),
                new PointD(0,   0), new PointD(-1, 2), new PointD(1, 2)
            };
            LineD[] lines =
            {
                new LineD(points[0], points[1]), new LineD(points[2], points[1]),
                new LineD(points[0], points[2]), new LineD(points[3], points[4]),
                new LineD(points[3], points[5]), new LineD(points[4], points[5])
            };

            Subdivision division = Subdivision.FromLines(lines);

            division.Validate();
            if (!test)
            {
                return(division);
            }

            CollectionAssert.AreEquivalent(lines, division.ToLines());
            var edges = division.Edges.Values;
            var faces = division.Faces.Values;

            CollectionAssert.AreEqual(new[] {
                new VertexPair(points[0], edges[0]),
                new VertexPair(points[2], edges[2]),
                new VertexPair(points[3], edges[6]),
                new VertexPair(points[4], edges[7]),
                new VertexPair(points[5], edges[9]),
                new VertexPair(points[1], edges[1]),
            }, division.Vertices);

            CollectionAssert.AreEqual(new[] {
                new SubdivisionEdge(0, points[0], edges[1], faces[0], edges[3], edges[5]),
                new SubdivisionEdge(1, points[1], edges[0], faces[1], edges[4], edges[2]),
                new SubdivisionEdge(2, points[2], edges[3], faces[1], edges[1], edges[4]),
                new SubdivisionEdge(3, points[1], edges[2], faces[0], edges[5], edges[0]),
                new SubdivisionEdge(4, points[0], edges[5], faces[1], edges[2], edges[1]),
                new SubdivisionEdge(5, points[2], edges[4], faces[0], edges[0], edges[3]),
                new SubdivisionEdge(6, points[3], edges[7], faces[1], edges[10], edges[9]),
                new SubdivisionEdge(7, points[4], edges[6], faces[2], edges[8], edges[11]),
                new SubdivisionEdge(8, points[3], edges[9], faces[2], edges[11], edges[7]),
                new SubdivisionEdge(9, points[5], edges[8], faces[1], edges[6], edges[10]),
                new SubdivisionEdge(10, points[4], edges[11], faces[1], edges[9], edges[6]),
                new SubdivisionEdge(11, points[5], edges[10], faces[2], edges[7], edges[8]),
            }, edges);

            CollectionAssert.AreEqual(new[] {
                new SubdivisionFace(division, 0, null, new[] { edges[0] }),
                new SubdivisionFace(division, 1, edges[1], new[] { edges[6] }),
                new SubdivisionFace(division, 2, edges[7], null),
            }, faces);

            PointD centroid = new PointD(0, -2 / 3.0);

            CheckFace(edges[0], new[] { points[0], points[1], points[2] }, -50, centroid);
            CheckFace(edges[1], new[] { points[1], points[0], points[2] }, +50, centroid);

            centroid = new PointD(0, 4 / 3.0);
            CheckFace(edges[6], new[] { points[3], points[4], points[5] }, -2, centroid);
            CheckFace(edges[7], new[] { points[4], points[3], points[5] }, +2, centroid);

            var cycles = division.GetZeroAreaCycles();

            Assert.AreEqual(0, cycles.Count);
            return(division);
        }