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); }
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); }
/// <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); }
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); }
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); }