Пример #1
0
        private static SplitLayout Split(this PlainShape self, long maxEgeSize, Allocator allocator)
        {
            var originalCount = self.points.Length;
            var nodes         = new DynamicArray <Node>(originalCount, allocator);
            var layouts       = new DynamicArray <PathLayout>(originalCount, allocator);
            var sqrMaxSize    = maxEgeSize * maxEgeSize;

            var begin         = 0;
            var originalIndex = 0;
            var extraIndex    = originalCount;

            for (int j = 0; j < self.layouts.Length; ++j)
            {
                var layout = self.layouts[j];
                var last   = layout.end;
                var a      = self.points[last];
                var length = 0;

                for (int i = layout.begin; i <= layout.end; ++i)
                {
                    var b       = self.points[i];
                    var dx      = b.x - a.x;
                    var dy      = b.y - a.y;
                    var sqrSize = dx * dx + dy * dy;
                    if (sqrSize > sqrMaxSize)
                    {
                        var    l  = (long)Mathf.Sqrt(sqrSize);
                        int    s  = (int)(l / maxEgeSize);
                        double ds = s;
                        double sx = dx / ds;
                        double sy = dy / ds;
                        double fx = 0;
                        double fy = 0;
                        for (int k = 1; k < s; ++k)
                        {
                            fx += sx;
                            fy += sy;

                            long x = a.x + (long)fx;
                            long y = a.y + (long)fy;
                            nodes.Add(new Node(extraIndex, new IntVector(x, y)));
                            extraIndex += 1;
                        }

                        length += s - 1;
                    }

                    length += 1;
                    nodes.Add(new Node(originalIndex, b));
                    originalIndex += 1;
                    a              = b;
                }

                layouts.Add(new PathLayout(begin, length, layout.isClockWise));
                begin += length;
            }

            return(new SplitLayout(layouts.Convert(), nodes.Convert()));
        }
Пример #2
0
        public NativeArray <Hexagon> HexagonDivide(NativeArray <Triangle> triangles, Allocator allocator)
        {
            var result = new DynamicArray <Hexagon>(maxCount, allocator);

            var bufferA = new DynamicArray <Triangle>(maxCount / 3, tempAllocator);
            var bufferB = new DynamicArray <Triangle>(maxCount / 3, tempAllocator);


            bufferA.Add(triangles);
            do
            {
                for (int i = 0; i < bufferA.Count; ++i)
                {
                    var triangle = bufferA[i];
                    if (hexagonDivide(triangle, out var hexagon, ref bufferB))
                    {
                        result.Add(hexagon);
                        if (result.Count >= maxCount)
                        {
                            goto onFinish;
                        }
                    }
                }

                bufferA.RemoveAll();

                if (bufferB.Count > 0)
                {
                    for (int i = 0; i < bufferB.Count; ++i)
                    {
                        var triangle = bufferB[i];
                        if (hexagonDivide(triangle, out var hexagon, ref bufferA))
                        {
                            result.Add(hexagon);
                            if (result.Count >= maxCount)
                            {
                                goto onFinish;
                            }
                        }
                    }
                }

                bufferB.RemoveAll();
            } while (bufferA.Count > 0);

onFinish:

            bufferA.Dispose();
            bufferB.Dispose();

            return(result.Convert());
        }
Пример #3
0
        public static MonotoneLayout Split(this PlainShape shape, long maxEdge, NativeArray <IntVector> extraPoints, Allocator allocator)
        {
            var navigator   = shape.GetNavigator(maxEdge, extraPoints, Allocator.Temp);
            var links       = new DynamicArray <Link>(navigator.links, allocator);
            var natures     = navigator.natures;
            var sortIndices = navigator.indices;

            int n = sortIndices.Length;

            var subs    = new DynamicArray <Sub>(8, Allocator.Temp);
            var dSubs   = new DynamicArray <DualSub>(8, Allocator.Temp);
            var indices = new DynamicArray <int>(16, allocator);
            var slices  = new DynamicArray <Slice>(16, allocator);

            int i = 0;

nextNode:
            while (i < n)
            {
                int sortIndex = sortIndices[i];
                var node      = links[sortIndex];
                var nature    = natures[sortIndex];

                int j;
                switch (nature)
                {
                case LinkNature.start:
                    subs.Add(new Sub(node));
                    ++i;
                    goto nextNode;

                case LinkNature.extra:
                    j = 0;

                    while (j < dSubs.Count)
                    {
                        var dSub = dSubs[j];
                        var pA   = dSub.next.vertex.point;
                        var pB   = links[dSub.next.next].vertex.point;
                        var pC   = links[dSub.prev.prev].vertex.point;
                        var pD   = dSub.prev.vertex.point;

                        var p = node.vertex.point;

                        if (IsTetragonContain(p, pA, pB, pC, pD))
                        {
                            var hand = links[dSub.middle];
                            slices.Add(new Slice(hand.vertex.index, node.vertex.index));
                            links.ConnectExtraPrev(hand.self, node.self);

                            dSubs[j] = new DualSub(links[dSub.next.self], node.self, links[dSub.prev.self]);

                            i += 1;
                            goto nextNode;
                        }

                        j += 1;
                    }   //  while dSubs

                    j = 0;

                    while (j < subs.Count)
                    {
                        var sub = subs[j];

                        var pA = sub.next.vertex.point;
                        var pB = links[sub.next.next].vertex.point;
                        var pC = links[sub.prev.prev].vertex.point;
                        var pD = sub.prev.vertex.point;

                        var p = node.vertex.point;

                        if (IsTetragonContain(p, pA, pB, pC, pD))
                        {
                            if (!sub.isEmpty)
                            {
                                if (pA.x > pD.x)
                                {
                                    var hand = sub.next;
                                    slices.Add(new Slice(hand.vertex.index, node.vertex.index));
                                    var newHandIndex = links.ConnectExtraNext(hand.self, node.self);
                                    dSubs.Add(new DualSub(links[newHandIndex], node.self, links[sub.prev.self]));
                                }
                                else
                                {
                                    var hand = sub.prev;
                                    slices.Add(new Slice(hand.vertex.index, node.vertex.index));
                                    var newHandIndex = links.ConnectExtraPrev(hand.self, node.self);
                                    dSubs.Add(new DualSub(links[sub.next.self], node.self, links[newHandIndex]));
                                }
                            }
                            else
                            {
                                var hand = links[sub.next.self];
                                slices.Add(new Slice(hand.vertex.index, b: node.vertex.index));
                                var newPrev = links.ConnectExtraPrev(hand.self, node.self);
                                dSubs.Add(new DualSub(links[hand.self], node.self, links[newPrev]));
                            }
                            subs.Exclude(j);
                            i += 1;
                            goto nextNode;
                        }

                        j += 1;
                    }
                    break;

                case LinkNature.merge:

                    var newNextSub = new Sub(true);
                    var newPrevSub = new Sub(true);

                    j = 0;

                    while (j < dSubs.Count)
                    {
                        var dSub = dSubs[j];

                        if (dSub.next.next == node.self)
                        {
                            var a      = node.self;
                            var b      = dSub.middle;
                            var bridge = links.Connect(a, b);

                            indices.Add(links.FindStart(bridge.a.self));

                            slices.Add(bridge.Slice);

                            var prevSub = new Sub(links[a], dSub.prev);

                            if (!newNextSub.isEmpty)
                            {
                                dSubs[j] = new DualSub(newNextSub, prevSub);
                                ++i;
                                goto nextNode;
                            }

                            dSubs.Exclude(j);

                            newPrevSub = prevSub;
                            continue;
                        }
                        else if (dSub.prev.prev == node.self)
                        {
                            var a = dSub.middle;
                            var b = node.self;

                            var bridge = links.Connect(a, b);

                            indices.Add(links.FindStart(bridge.a.self));
                            slices.Add(bridge.Slice);

                            var nextSub = new Sub(dSub.next, links[b]);

                            if (!newPrevSub.isEmpty)
                            {
                                dSubs[j] = new DualSub(nextSub, newPrevSub);
                                ++i;
                                goto nextNode;
                            }
                            dSubs.Exclude(j);

                            newNextSub = nextSub;
                            continue;
                        }

                        ++j;
                    }       //  while dSubs

                    j = 0;

                    while (j < subs.Count)
                    {
                        var sub = subs[j];

                        if (sub.next.next == node.self)
                        {
                            sub.next = node;

                            subs.Exclude(j);

                            if (!newNextSub.isEmpty)
                            {
                                dSubs.Add(new DualSub(newNextSub, sub));
                                ++i;
                                goto nextNode;
                            }

                            newPrevSub = sub;
                            continue;
                        }
                        else if (sub.prev.prev == node.self)
                        {
                            sub.prev = node;
                            subs.Exclude(j);

                            if (!newPrevSub.isEmpty)
                            {
                                dSubs.Add(new DualSub(sub, newPrevSub));
                                ++i;
                                goto nextNode;
                            }

                            newNextSub = sub;
                            continue;
                        }

                        ++j;
                    }
                    break;

                case LinkNature.split:

                    j = 0;

                    while (j < subs.Count)
                    {
                        var sub = subs[j];


                        var pA = sub.next.vertex.point;

                        var pB = links[sub.next.next].vertex.point;

                        var pC = links[sub.prev.prev].vertex.point;

                        var pD = sub.prev.vertex.point;


                        var p = node.vertex.point;

                        if (IsTetragonContain(p, pA, pB, pC, pD))
                        {
                            var a0 = sub.next.self;
                            var a1 = sub.prev.self;
                            var b  = node.self;

                            if (pA.x > pD.x)
                            {
                                var bridge = links.Connect(a0, b);

                                subs.Add(new Sub(bridge.b, links[a1]));

                                slices.Add(bridge.Slice);
                            }
                            else
                            {
                                var bridge = links.Connect(a1, b);

                                subs.Add(new Sub(bridge.b, bridge.a));
                                slices.Add(bridge.Slice);
                            }
                            subs[j] = new Sub(links[a0], links[b]);
                            ++i;
                            goto nextNode;
                        }

                        ++j;
                    }

                    j = 0;

                    while (j < dSubs.Count)
                    {
                        var dSub = dSubs[j];

                        var pA = dSub.next.vertex.point;

                        var pB = links[dSub.next.next].vertex.point;
                        var pC = links[dSub.prev.prev].vertex.point;
                        var pD = dSub.prev.vertex.point;
                        var p  = node.vertex.point;

                        if (IsTetragonContain(p, pA, pB, pC, pD))
                        {
                            var a = dSub.middle;

                            var b      = node.self;
                            var bridge = links.Connect(a, b);

                            subs.Add(new Sub(dSub.next, links[b]));
                            subs.Add(new Sub(bridge.b, dSub.prev));
                            slices.Add(bridge.Slice);
                            dSubs.Exclude(j);

                            ++i;
                            goto nextNode;
                        }

                        ++j;
                    }       //  while dSubs

                    break;

                case LinkNature.end:

                    j = 0;

                    while (j < subs.Count)
                    {
                        var sub = subs[j];

                        // second condition is useless because it repeats the first
                        if (sub.next.next == node.self)    /* || sub.prev.prev.index == node.this */
                        {
                            indices.Add(links.FindStart(node.self));

                            subs.Exclude(j);

                            ++i;
                            goto nextNode;
                        }

                        ++j;
                    }

                    j = 0;

                    while (j < dSubs.Count)
                    {
                        var dSub = dSubs[j];

                        // second condition is useless because it repeats the first
                        if (dSub.next.next == node.self)    /*|| dSub.prevSub.prev.prev.index == node.this*/
                        {
                            var a      = dSub.middle;
                            var b      = node.self;
                            var bridge = links.Connect(a, b);

                            indices.Add(links.FindStart(a));
                            indices.Add(links.FindStart(bridge.a.self));
                            slices.Add(bridge.Slice);

                            dSubs.Exclude(j);

                            // goto next node
                            ++i;
                            goto nextNode;
                        }

                        ++j;
                    }       //  while dSubs

                    break;

                case LinkNature.simple:

                    j = 0;

                    while (j < subs.Count)
                    {
                        var sub = subs[j];

                        if (sub.next.next == node.self)
                        {
                            sub.next = node;
                            subs[j]  = sub;

                            ++i;
                            goto nextNode;
                        }
                        else if (sub.prev.prev == node.self)
                        {
                            sub.prev = node;
                            subs[j]  = sub;
                            // goto next node
                            ++i;
                            goto nextNode;
                        }

                        ++j;
                    }

                    j = 0;

                    while (j < dSubs.Count)
                    {
                        var dSub = dSubs[j];

                        if (dSub.next.next == node.self)
                        {
                            var a = dSub.middle;
                            var b = node.self;

                            var bridge = links.Connect(a, b);

                            indices.Add(links.FindStart(node.self));
                            slices.Add(bridge.Slice);

                            var newSub = new Sub(bridge.b, dSub.prev);
                            subs.Add(newSub);

                            dSubs.Exclude(j);

                            // goto next node
                            ++i;
                            goto nextNode;
                        }
                        else if (dSub.prev.prev == node.self)
                        {
                            var a = node.self;
                            var b = dSub.middle;

                            var bridge = links.Connect(a, b);

                            indices.Add(links.FindStart(node.self));
                            slices.Add(bridge.Slice);

                            var newSub = new Sub(links[dSub.next.self], bridge.a);
                            subs.Add(newSub);

                            dSubs.Exclude(j);

                            // goto next node
                            ++i;
                            goto nextNode;
                        }

                        ++j;
                    } //  while dSubs
                    break;
                }     // switch
            }

            subs.Dispose();
            dSubs.Dispose();
            navigator.Dispose();

            int pathCount  = navigator.pathCount;
            int extraCount = navigator.extraCount;

            return(new MonotoneLayout(pathCount, extraCount, links.Convert(), slices.Convert(), indices.Convert()));
        }