public static NativeArray <int> Triangulate(this PlainShape shape, NativeArray <IntVector> extraPoints, Allocator allocator) { var layout = shape.Split(0, extraPoints, Allocator.Temp); int totalCount = shape.points.Length + ((shape.layouts.Length - 2) << 1); int trianglesCount = 3 * totalCount; var triangles = new NativeArray <int>(trianglesCount, allocator); int counter = 0; for (int i = 0; i < layout.indices.Length; ++i) { int index = layout.indices[i]; Triangulate(index, ref counter, layout.links, triangles); } layout.Dispose(); if (counter == trianglesCount) { return(triangles); } else { var newTriangles = new NativeArray <int>(counter, allocator); newTriangles.Slice(0, counter).CopyFrom(triangles.Slice(0, counter)); triangles.Dispose(); return(newTriangles); } }
public static Delaunay Delaunay(this PlainShape shape, long maxEdge, NativeArray <IntVector> extraPoints, Allocator allocator) { var layout = shape.Split(maxEdge, extraPoints, Allocator.Temp); int holesCount = shape.layouts.Length; int totalCount = layout.pathCount + 2 * layout.extraCount + holesCount * 2 - 2; var triangleStack = new TriangleStack(totalCount, allocator); for (int i = 0; i < layout.indices.Length; ++i) { int index = layout.indices[i]; Triangulate(index, layout.links, ref triangleStack); triangleStack.Reset(); } var triangles = triangleStack.Convert(); var sliceBuffer = new SliceBuffer(layout.links.Length, layout.slices, Allocator.Temp); sliceBuffer.AddConnections(triangles); sliceBuffer.Dispose(); layout.Dispose(); Delaunay delaunay; if (extraPoints.Length == 0 && maxEdge == 0) { delaunay = new Delaunay(shape.points, triangles, allocator); } else { var points = new NativeArray <IntVector>(layout.links.Length, Allocator.Temp); for (int i = 0; i < layout.links.Length; ++i) { var link = layout.links[i]; points[link.vertex.index] = link.vertex.point; } delaunay = new Delaunay(points, triangles, allocator); points.Dispose(); } delaunay.Build(); return(delaunay); }
internal static ShapeNavigator GetNavigator(this PlainShape shape, long maxEdge, NativeArray <IntVector> extraPoints, Allocator allocator) { SplitLayout splitLayout; if (maxEdge == 0) { splitLayout = shape.Plain(Allocator.Temp); } else { splitLayout = shape.Split(maxEdge, Allocator.Temp); } int pathCount = splitLayout.nodes.Length; int extraCount = extraPoints.Length; int n; if (extraCount > 0) { n = pathCount + extraCount; } else { n = pathCount; } var links = new NativeArray <Link>(n, allocator); var natures = new NativeArray <LinkNature>(n, allocator); int m = splitLayout.layouts.Length; for (int j = 0; j < m; ++j) { var layout = splitLayout.layouts[j]; var prev = layout.end - 1; var self = layout.end; var next = layout.begin; var a = splitLayout.nodes[prev]; var b = splitLayout.nodes[self]; var A = a.point.BitPack; var B = b.point.BitPack; while (next <= layout.end) { var c = splitLayout.nodes[next]; var C = c.point.BitPack; var nature = LinkNature.simple; bool isCCW = IsCCW(a.point, b.point, c.point); if (layout.isClockWise) { if (A > B && B < C) { if (isCCW) { nature = LinkNature.start; } else { nature = LinkNature.split; } } if (A < B && B > C) { if (isCCW) { nature = LinkNature.end; } else { nature = LinkNature.merge; } } } else { if (A > B && B < C) { if (isCCW) { nature = LinkNature.start; } else { nature = LinkNature.split; } } if (A < B && B > C) { if (isCCW) { nature = LinkNature.end; } else { nature = LinkNature.merge; } } } var verNature = b.index < shape.points.Length ? Vertex.Nature.origin : Vertex.Nature.extraPath; links[self] = new Link(prev, self, next, new Vertex(self, verNature, b.point)); natures[self] = nature; a = b; b = c; A = B; B = C; prev = self; self = next; ++next; } } splitLayout.Dispose(); if (extraCount > 0) { for (int k = 0; k < extraPoints.Length; ++k) { var p = extraPoints[k]; var j = k + pathCount; links[j] = new Link(j, j, j, new Vertex(j, Vertex.Nature.extraInner, p)); natures[j] = LinkNature.extra; } } // sort var dataList = new NativeArray <SortData>(n, Allocator.Temp); for (int j = 0; j < n; ++j) { var p = links[j].vertex.point; dataList[j] = new SortData(j, p.BitPack, (int)natures[j]); } Sort(dataList); var indices = new NativeArray <int>(n, allocator); // filter same points var x1 = new SortData(-1, long.MinValue, int.MinValue); int i = 0; while (i < n) { var x0 = dataList[i]; indices[i] = x0.index; if (x0.factor == x1.factor) { var v = links[x1.index].vertex; do { var link = links[x0.index]; links[x0.index] = new Link(link.prev, link.self, link.next, new Vertex(v.index, v.nature, v.point)); ++i; if (i < n) { x0 = dataList[i]; indices[i] = x0.index; } else { break; } } while(x0.factor == x1.factor); } x1 = x0; ++i; } dataList.Dispose(); return(new ShapeNavigator(pathCount, extraCount, links, natures, indices)); }