public static IEnumerable <int> ConvertToTriangulation(TriangulationGraph graph, IReadOnlyList <SortedVertex> vertices, IReadOnlyCollection <IEnumerable <int> > holeVertices) { var triangles = new HashSet <Triangle>(); foreach (var graphItem in graph.Items) { var edge = graphItem.Key; var twoVertices = graphItem.Value; if (twoVertices.Vertex2 < 0) { continue; } var edgeV1 = vertices[edge.Vertex1]; var edgeV2 = vertices[edge.Vertex2]; var v1 = vertices[twoVertices.Vertex1]; var v2 = vertices[twoVertices.Vertex2]; AddQuad(edgeV1, edgeV2, v1, v2, triangles, holeVertices); } return(triangles.SelectMany(t => t.Vertices)); }
private static void AddVertexToTriangulation(int vertexId, List <SortedVertex> vertices, HullEdgesList convexHull, TriangulationGraph graph) { FixTriangulationIteratively(vertexId, vertices, convexHull, HullEdge.IterationDirections.Right, (v1, v2) => TriangulationHelper.CrossProduct(v1, v2) > -DelaunayTriangulationValidator.Eps, (left, right, outer) => FixTriangulation(left, right, outer, vertices, graph)); var hullVertex = FixTriangulationIteratively(vertexId, vertices, convexHull, HullEdge.IterationDirections.Left, (v1, v2) => TriangulationHelper.CrossProduct(v1, v2) < DelaunayTriangulationValidator.Eps, (left, right, outer) => FixTriangulation(right, left, outer, vertices, graph)); convexHull[convexHull[vertexId].Right].Set(HullEdge.IterationDirections.Left, vertexId); convexHull[hullVertex].Set(HullEdge.IterationDirections.Right, vertexId); }
private static void FixTriangulation(int left, int right, int outer, IReadOnlyList <SortedVertex> vertices, TriangulationGraph graph) { var recursionStack = new Edge[vertices.Count]; recursionStack[0] = new Edge(left, right); var stackSize = 1; while (stackSize > 0) { left = recursionStack[stackSize - 1].Vertex1; right = recursionStack[stackSize - 1].Vertex2; --stackSize; var inner = graph[new Edge(Mathf.Min(left, right), Mathf.Max(left, right))].Min(); if (DelaunayTriangulationValidator.Validate(left, right, outer, inner, vertices)) { graph[new Edge(right, outer)].Insert(left); graph[new Edge(left, outer)].Insert(right); if (right < left) { TriangulationHelper.Swap(ref left, ref right); } graph[new Edge(left, right)].Insert(outer); continue; } graph[new Edge(right, outer)].Replace(left, inner); graph[new Edge(left, outer)].Replace(right, inner); graph[new Edge(Mathf.Min(inner, left), Mathf.Max(inner, left))].Replace(right, outer); graph[new Edge(Mathf.Min(inner, right), Mathf.Max(inner, right))].Replace(left, outer); graph.Remove(new Edge(Mathf.Min(left, right), Mathf.Max(left, right))); recursionStack[stackSize++] = new Edge(left, inner); recursionStack[stackSize++] = new Edge(inner, right); } }
public IEnumerable <int> Build(IEnumerable <Vector2> vertices, IReadOnlyCollection <IEnumerable <int> > holeVertices) { var sortedVertices = vertices.Select((v, index) => new SortedVertex(index, v)) .OrderBy(v => v.Vertex.x).ThenBy(v => v.Vertex.y).ToList(); if (sortedVertices.Count < 3) { throw new ArgumentException($"Minimum vertices count for triangulation is 3, but was {sortedVertices.Count}"); } var convexHull = new HullEdgesList(sortedVertices.Count); var graph = new TriangulationGraph(); convexHull.Add(new HullEdge(1, 1)); convexHull.Add(new HullEdge(0, 0)); graph[new Edge(0, 1)].Insert(2); for (var i = 2; i < sortedVertices.Count; i++) { AddVertexToTriangulation(i, sortedVertices, convexHull, graph); } return(DelaunayTriangulationConverter.ConvertToTriangulation(graph, sortedVertices, holeVertices)); }