/// <summary> /// Converts all <see cref="DelaunayEdges"/> to a planar <see cref="Subdivision"/>, using /// the specified clipping bounds.</summary> /// <param name="bounds"> /// A <see cref="RectD"/> that indicates the clipping bounds for all <see /// cref="DelaunayEdges"/>.</param> /// <param name="addRegions"> /// <c>true</c> to add all <see cref="VoronoiRegions"/> with the corresponding <see /// cref="GeneratorSites"/> to the <see cref="Subdivision.VertexRegions"/> collection of the /// new <see cref="Subdivision"/>; otherwise, <c>false</c>.</param> /// <returns> /// A new <see cref="Subdivision"/> whose <see cref="Subdivision.Edges"/> correspond to the /// <see cref="DelaunayEdges"/> of the <see cref="VoronoiResults"/>.</returns> /// <remarks><para> /// The specified <paramref name="bounds"/> determine the subset of <see /// cref="GeneratorSites"/> and <see cref="DelaunayEdges"/> that is stored in the new <see /// cref="Subdivision"/>, as described in <see cref="ClipDelaunayEdges"/>. /// </para><para> /// If <paramref name="addRegions"/> is <c>true</c>, the polygons added to the <see /// cref="Subdivision.VertexRegions"/> collection are also clipped the specified <paramref /// name="bounds"/>.</para></remarks> public Subdivision ToDelaunySubdivision(RectD bounds, bool addRegions = false) { LineD[] edges = ClipDelaunayEdges(bounds); Subdivision division = Subdivision.FromLines(edges); if (addRegions) { for (int i = 0; i < GeneratorSites.Length; i++) { PointD site = GeneratorSites[i]; if (!bounds.Contains(site)) { continue; } PointD[] region; if (bounds.Intersect(VoronoiRegions[i], out region)) { division.VertexRegions.Add(site, region); } } } return(division); }
public static Subdivision CreateSquareStar(bool test) { PointD[] points = { new PointD(), new PointD(-1, -2), new PointD(-1, 2), new PointD(1, 2), new PointD(1, -2) }; LineD[] lines = { new LineD(points[1], points[2]), new LineD(points[2], points[3]), new LineD(points[4], points[3]), new LineD(points[1], points[4]), new LineD(points[0], points[1]), new LineD(points[0], points[2]), new LineD(points[0], points[3]), new LineD(points[0], points[4]) }; var division = Subdivision.FromLines(lines); division.Validate(); if (!test) { return(division); } var edges = division.Edges.Values; var faces = division.Faces.Values; Assert.AreEqual(16, edges.Count); Assert.AreEqual(5, faces.Count); CollectionAssert.AreEqual(new[] { new SubdivisionEdge(0, points[1], edges[1], faces[0], edges[2], edges[7]), new SubdivisionEdge(1, points[2], edges[0], faces[1], edges[9], edges[10]), new SubdivisionEdge(2, points[2], edges[3], faces[0], edges[5], edges[0]), new SubdivisionEdge(3, points[3], edges[2], faces[2], edges[11], edges[12]), new SubdivisionEdge(4, points[4], edges[5], faces[3], edges[13], edges[14]), new SubdivisionEdge(5, points[3], edges[4], faces[0], edges[7], edges[2]), new SubdivisionEdge(6, points[1], edges[7], faces[4], edges[15], edges[8]), new SubdivisionEdge(7, points[4], edges[6], faces[0], edges[0], edges[5]), new SubdivisionEdge(8, points[0], edges[9], faces[4], edges[6], edges[15]), new SubdivisionEdge(9, points[1], edges[8], faces[1], edges[10], edges[1]), new SubdivisionEdge(10, points[0], edges[11], faces[1], edges[1], edges[9]), new SubdivisionEdge(11, points[2], edges[10], faces[2], edges[12], edges[3]), new SubdivisionEdge(12, points[0], edges[13], faces[2], edges[3], edges[11]), new SubdivisionEdge(13, points[3], edges[12], faces[3], edges[14], edges[4]), new SubdivisionEdge(14, points[0], edges[15], faces[3], edges[4], edges[13]), new SubdivisionEdge(15, points[4], edges[14], faces[4], edges[8], edges[6]), }, edges); var cycles = division.GetZeroAreaCycles(); Assert.AreEqual(0, cycles.Count); return(division); }
/// <overloads> /// Converts all <see cref="DelaunayEdges"/> to a planar <see cref="Subdivision"/>. /// </overloads> /// <summary> /// Converts all <see cref="DelaunayEdges"/> to a planar <see cref="Subdivision"/>, using /// the default <see cref="ClippingBounds"/>.</summary> /// <param name="addRegions"> /// <c>true</c> to add all <see cref="VoronoiRegions"/> with the corresponding <see /// cref="GeneratorSites"/> to the <see cref="Subdivision.VertexRegions"/> collection of the /// new <see cref="Subdivision"/>; otherwise, <c>false</c>.</param> /// <returns> /// A new <see cref="Subdivision"/> whose <see cref="Subdivision.Edges"/> correspond to the /// <see cref="DelaunayEdges"/> of the <see cref="VoronoiResults"/>.</returns> public Subdivision ToDelaunySubdivision(bool addRegions = false) { Subdivision division = Subdivision.FromLines(DelaunayEdges); if (addRegions) { for (int i = 0; i < GeneratorSites.Length; i++) { division.VertexRegions.Add(GeneratorSites[i], VoronoiRegions[i]); } } return(division); }
public void IGraph2DTest() { PointD[] points = { new PointD(0, 0), new PointD(-1, -2), new PointD(-1, 2), new PointD(1, 2),new PointD(1, -2) }; LineD[] lines = { new LineD(points[0], points[1]), new LineD(points[0], points[2]), new LineD(points[0], points[3]), new LineD(points[4], points[0]) }; var division = Subdivision.FromLines(lines); division.Validate(); var graph = division as IGraph2D <PointD>; Assert.AreEqual(4, graph.Connectivity); Assert.AreEqual(5, graph.NodeCount); foreach (PointD node in graph.Nodes) { CollectionAssert.Contains(points, node); } foreach (PointD point in points) { Assert.IsTrue(graph.Contains(point)); Assert.AreEqual(point, graph.GetWorldLocation(point)); PointD near = new PointD(point.X + 0.1, point.Y - 0.1); Assert.IsFalse(graph.Contains(near)); Assert.AreEqual(point, graph.GetNearestNode(near)); } var center = new[] { points[0] }; var neighbors = new PointD[points.Length - 1]; double distance = Math.Sqrt(5.0); for (int i = 1; i < points.Length; i++) { Assert.AreEqual(distance, graph.GetDistance(points[0], points[i])); CollectionAssert.AreEquivalent(center, graph.GetNeighbors(points[i])); neighbors[i - 1] = points[i]; } CollectionAssert.AreEquivalent(neighbors, graph.GetNeighbors(points[0])); }
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); }
public void FindEdgeEpsilon() { PointD[] points = { new PointD(0, 0), new PointD(-1, -2), new PointD(-1, 2), new PointD(1, 2),new PointD(1, -2) }; LineD[] lines = { new LineD(points[1], points[0]), new LineD(points[0], points[2]), new LineD(points[0], points[3]), new LineD(points[4], points[0]) }; var division = Subdivision.FromLines(lines, 0.2); division.Validate(); // check all existing half-edges PointD offset = new PointD(0.1, -0.1); foreach (SubdivisionEdge edge in division.Edges.Values) { Assert.AreSame(edge, division.FindEdge(edge.Origin, edge.Destination)); Assert.AreSame(edge, division.FindEdge( edge.Origin.Add(offset), edge.Destination.Add(offset))); } for (int i = 0; i < points.Length; i++) { // check half-edges including one non-existing vertex Assert.IsNull(division.FindEdge(points[i], new PointD(1, 0))); Assert.IsNull(division.FindEdge(new PointD(1, 0), points[i])); // check nonexistent half-edges between vertices if (i == 0) { continue; } for (int j = 1; j < points.Length; j++) { if (j != i) { Assert.IsNull(division.FindEdge(points[i], points[j])); } } } }
public void FromLinesVertical() { PointD[] points = { new PointD(-1, -2), new PointD(-1, 2), new PointD(1, -2), new PointD(1, 2) }; LineD[] lines = { new LineD(points[0], points[1]), new LineD(points[2], points[3]) }; var division = Subdivision.FromLines(lines); division.Validate(); 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[1], edges[1]), new VertexPair(points[3], edges[3]), }, division.Vertices); CollectionAssert.AreEqual(new[] { new SubdivisionEdge(0, points[0], edges[1], faces[0], edges[1], edges[1]), new SubdivisionEdge(1, points[1], edges[0], faces[0], edges[0], edges[0]), new SubdivisionEdge(2, points[2], edges[3], faces[0], edges[3], edges[3]), new SubdivisionEdge(3, points[3], edges[2], faces[0], edges[2], edges[2]), }, edges); CollectionAssert.AreEqual(new[] { new SubdivisionFace(division, 0, null, new[] { edges[0], edges[2] }), }, faces); CheckFace(edges[0], new[] { points[0], points[1] }, 0, PointD.Empty); CheckFace(edges[2], new[] { points[2], points[3] }, 0, PointD.Empty); var cycles = division.GetZeroAreaCycles(); Assert.AreEqual(2, cycles.Count); Assert.AreEqual(edges[0], cycles[0]); Assert.AreEqual(edges[2], cycles[1]); }
public void FromLinesSquare() { PointD[] points = { new PointD(-1, -2), new PointD(-1, 2), new PointD(1, 2), new PointD(1, -2) }; LineD[] lines = { new LineD(points[0], points[1]), new LineD(points[1], points[2]), new LineD(points[3], points[2]), new LineD(points[0], points[3]) }; var division = Subdivision.FromLines(lines); division.Validate(); CollectionAssert.AreEquivalent(lines, division.ToLines()); CheckLinesSquare(points, division); }
private void PasteCommandExecuted(object sender, ExecutedRoutedEventArgs args) { args.Handled = true; try { string text = Clipboard.GetText(); LineD[] lines = XmlSerialization.Deserialize <LineD[]>(text); Subdivision division = Subdivision.FromLines(lines); DrawSubdivision(division); } catch (Exception e) { MessageDialog.Show(this, "An error occurred while attempting to\n" + "paste a new subdivision from the clipboard.", Strings.ClipboardPasteError, e, MessageBoxButton.OK, WindowsUtility.GetSystemBitmap(MessageBoxImage.Error)); } }
public void FromLinesSquareEpsilon() { PointD[] points = { new PointD(-1, -2), new PointD(-1, 2), new PointD(1, 2), new PointD(1, -2) }; LineD[] lines = { new LineD(points[0], points[1]), new LineD(new PointD(-1.1, 1.9),points[2]), new LineD(points[3], new PointD(0.9, 2.1)), new LineD(new PointD(-0.9, -2.1),new PointD(1.1, -1.9)) }; var division = Subdivision.FromLines(lines, 0.2); division.Validate(); CollectionAssert.AreNotEquivalent(lines, division.ToLines()); CheckLinesSquare(points, division); }
/// <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); }
public void FromLinesDiamond() { PointD[] points = { new PointD(0, -4), new PointD(-6, 0), new PointD(-3, 0), new PointD(3, 0), new PointD(6, 0), new PointD(0, 4) }; LineD[] lines = { new LineD(points[0], points[1]), new LineD(points[1], points[5]), new LineD(points[0], points[2]), new LineD(points[2], points[5]), new LineD(points[0], points[3]), new LineD(points[3], points[5]), new LineD(points[0], points[4]), new LineD(points[4], points[5]) }; var division = Subdivision.FromLines(lines); division.Validate(); 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[1], edges[1]), new VertexPair(points[2], edges[5]), new VertexPair(points[3], edges[9]), new VertexPair(points[4], edges[13]), new VertexPair(points[5], edges[3]), }, division.Vertices); CollectionAssert.AreEqual(new[] { new SubdivisionEdge(0, points[0], edges[1], faces[0], edges[2], edges[13]), new SubdivisionEdge(1, points[1], edges[0], faces[1], edges[4], edges[3]), new SubdivisionEdge(2, points[1], edges[3], faces[0], edges[15], edges[0]), new SubdivisionEdge(3, points[5], edges[2], faces[1], edges[1], edges[6]), new SubdivisionEdge(4, points[0], edges[5], faces[1], edges[6], edges[1]), new SubdivisionEdge(5, points[2], edges[4], faces[2], edges[8], edges[7]), new SubdivisionEdge(6, points[2], edges[7], faces[1], edges[3], edges[4]), new SubdivisionEdge(7, points[5], edges[6], faces[2], edges[5], edges[10]), new SubdivisionEdge(8, points[0], edges[9], faces[2], edges[10], edges[5]), new SubdivisionEdge(9, points[3], edges[8], faces[3], edges[12], edges[11]), new SubdivisionEdge(10, points[3], edges[11], faces[2], edges[7], edges[8]), new SubdivisionEdge(11, points[5], edges[10], faces[3], edges[9], edges[14]), new SubdivisionEdge(12, points[0], edges[13], faces[3], edges[14], edges[9]), new SubdivisionEdge(13, points[4], edges[12], faces[0], edges[0], edges[15]), new SubdivisionEdge(14, points[4], edges[15], faces[3], edges[11], edges[12]), new SubdivisionEdge(15, points[5], edges[14], faces[0], edges[13], edges[2]), }, edges); CollectionAssert.AreEqual(new[] { new SubdivisionFace(division, 0, null, new[] { edges[0] }), new SubdivisionFace(division, 1, edges[1], null), new SubdivisionFace(division, 2, edges[5], null), new SubdivisionFace(division, 3, edges[9], null), }, faces); CheckFace(edges[0], new[] { points[0], points[1], points[5], points[4] }, -48, PointD.Empty); CheckFace(edges[1], new[] { points[1], points[0], points[2], points[5] }, +12, new PointD(-3, 0)); CheckFace(edges[5], new[] { points[2], points[0], points[3], points[5] }, +24, PointD.Empty); CheckFace(edges[9], new[] { points[3], points[0], points[4], points[5] }, +12, new PointD(3, 0)); var cycles = division.GetZeroAreaCycles(); Assert.AreEqual(0, cycles.Count); }
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); }