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())); }