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);
            }
        }
Example #2
0
        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);
        }
Example #3
0
        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));
        }