public static Mesh DelaunayTriangulate(this PlainShape shape, IntGeom iGeom) { int n = shape.points.Length; var vertices = new Vector3[n]; for (int i = 0; i < n; ++i) { var v = iGeom.Float(shape.points[i]); vertices[i] = new Vector3(v.x, v.y, 0); } var extraPoints = new NativeArray <IntVector>(0, Allocator.Temp); var delaunay = shape.Delaunay(0, extraPoints, Allocator.Temp); extraPoints.Dispose(); var nTriangles = delaunay.Indices(Allocator.Temp); delaunay.Dispose(); var mesh = new Mesh { vertices = vertices, triangles = nTriangles.ToArray() }; nTriangles.Dispose(); return(mesh); }
public IntShape(PlainShape plainShape) { var hullLayout = plainShape.layouts[0]; this.hull = new IntVector[hullLayout.end - 1]; for (int i = 0; i < hullLayout.end; ++i) { this.hull[i] = plainShape.points[i]; } int holesCount = plainShape.layouts.Length - 1; this.holes = new IntVector[holesCount][]; for (int i = 0; i < holesCount; ++i) { var layout = plainShape.layouts[i + 1]; int n = layout.end - layout.begin + 1; var points = new IntVector[n]; for (int j = 0; j < n; ++j) { points[j] = plainShape.points[j + layout.begin]; } this.holes[i] = points; } }
private NativeArray <int> Triangulate(int index) { var iGeom = IntGeom.DefGeom; var data = ComplexTests.data[index]; var hull = iGeom.Int(data[0]); var holes = new IntVector[data.Length - 1][]; for (int i = 1; i < data.Length; ++i) { holes[i - 1] = iGeom.Int(data[i]); } var iShape = new IntShape(hull, holes); var pShape = new PlainShape(iShape, Allocator.Temp); var triangles = pShape.Triangulate(Allocator.Temp); Assert.IsTrue(Triangle.IsCCW(pShape.points, triangles)); pShape.Dispose(); return(triangles); }
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); } }
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())); }
public static List ConvexPolygons(this PlainShape self, Allocator allocator, IntGeom intGeom) { var delaunay = self.Delaunay(Allocator.Temp); var list = delaunay.ConvexPolygons(intGeom, allocator); delaunay.Dispose(); return(list); }
public static Delaunay Delaunay(this PlainShape shape, Allocator allocator) { var extraPoints = new NativeArray <IntVector>(0, Allocator.Temp); var delaunay = shape.Delaunay(0, extraPoints, allocator); extraPoints.Dispose(); return(delaunay); }
public static NativeArray <int> Triangulate(this PlainShape shape, Allocator allocator) { var extraPoints = new NativeArray <IntVector>(0, Allocator.Temp); var triangles = Triangulate(shape, extraPoints, allocator); extraPoints.Dispose(); return(triangles); }
public static NativeArray <int> DelaunayTriangulate(this PlainShape shape, Allocator allocator, NativeArray <IntVector> extraPoints) { var delaunay = shape.Delaunay(0, extraPoints, allocator); var triangles = delaunay.Indices(allocator); delaunay.Dispose(); return(triangles); }
private static SplitLayout Plain(this PlainShape self, Allocator allocator) { var nodes = new NativeArray <Node>(self.points.Length, allocator); for (int i = 0; i < self.points.Length; ++i) { nodes[i] = new Node(i, self.points[i]); } var layouts = new NativeArray <PathLayout>(self.layouts, allocator); return(new SplitLayout(layouts, nodes)); }
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); }
private NativeArray <int> Triangulate(int index) { var iGeom = IntGeom.DefGeom; var data = MonotoneTests.data[index]; var iPoints = iGeom.Int(data); var iShape = new IntShape(iPoints, new IntVector[0][]); var pShape = new PlainShape(iShape, Allocator.Temp); var triangles = pShape.Triangulate(Allocator.Temp); Assert.IsTrue(Triangle.IsCCW(pShape.points, triangles)); pShape.Dispose(); return(triangles); }
public static List MakeCentroidNet(this PlainShape self, Allocator allocator, IntGeom intGeom, float maxEdge, float maxArea = 0, float minArea = 0, bool onlyConvex = false) { long iEdge = intGeom.Int(maxEdge); var delaunay = self.Delaunay(iEdge, Allocator.Temp); float aMaxArea; if (maxArea > 0) { aMaxArea = maxArea; } else { aMaxArea = 0.4f * maxEdge * maxEdge; } delaunay.Tessellate(intGeom, aMaxArea); var iMinArea = intGeom.SqrInt(minArea); var shape = delaunay.MakeCentroidNet(Allocator.Temp, iMinArea, onlyConvex); delaunay.Dispose(); int n = shape.layouts.Length; var dynamicList = new DynamicList(8 * n, n, allocator); for (int i = 0; i < n; ++i) { var iPath = shape.Get(i); var path = intGeom.Float(iPath, Allocator.Temp); var polygon = new Polygon(path, Allocator.Temp); dynamicList.Add(polygon); } shape.Dispose(); return(dynamicList.Convert()); }
public void Invoke(NativeArray <Vector2> hull, NativeArray <Vector2> hole, bool isDelaunay) { var iGeom = IntGeom.DefGeom; var iHull = iGeom.Int(hull.ToArray()); var iHoles = new[] { iGeom.Int(hole.ToArray()) }; var iShape = new IntShape(iHull, iHoles); var pShape = new PlainShape(iShape, Allocator.TempJob); int totalCount = pShape.points.Length * 3; var triangles = new NativeArray <int>(totalCount, Allocator.TempJob); var length = new NativeArray <int>(1, Allocator.TempJob); this.job = new TriangulationJob { plainShape = pShape, isDelaunay = isDelaunay, triangles = triangles, length = length }; this.jobHandle = this.job.Schedule(); }
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())); }
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)); }
public void Test_01() { var data = BreakerTestData.data[1]; var nPoints = new NativeArray <Vector2>(data, allocator); var iPoints = iGeom.Int(nPoints, allocator); var pShape = new PlainShape(iPoints, true, allocator); iPoints.Dispose(); var indices = pShape.DelaunayTriangulate(allocator); pShape.Dispose(); var triangles = TrianglesBuilder.build(nPoints, indices, allocator); indices.Dispose(); nPoints.Dispose(); var breaker = new BreakSolver(20, 20, BreakSolver.SmallSpawnStrategy.no); var polygons = breaker.Divide(triangles, allocator); triangles.Dispose(); Assert.AreEqual(polygons.Count, 4); Assert.AreEqual(polygons.Get(0, allocator).Convert().isEqual(new[] { new Vector2(-1.0173526f, 5.988432f), new Vector2(-3.1394918f, 4.5736723f), new Vector2(-6.684741f, 6.6305175f), new Vector2(-5.5441256f, 8.911749f), new Vector2(-3.8257403f, 10.0f), new Vector2(-1.2752466f, 10.0f) }, 0.001f), true); Assert.AreEqual(polygons.Get(1, allocator).Convert().isEqual(new[] { new Vector2(6.31049f, 7.3790197f), new Vector2(8.128133f, 3.7437348f), new Vector2(4.760133f, 0.0f), new Vector2(0.6957607f, 0.0f), new Vector2(-1.3489046f, 5.767397f), new Vector2(2.0328574f, 8.021905f) }, 0.001f), true); Assert.AreEqual(polygons.Get(2, allocator).Convert().isEqual(new[] { new Vector2(-2.0710678f, 0.0f), new Vector2(2.0710678f, 0.0f), new Vector2(5.0f, -5.0f), new Vector2(2.0710678f, -7.928932f), new Vector2(-2.0710678f, -7.928932f), new Vector2(-5.0f, -5.0f) }, 0.001f), true); Assert.AreEqual(polygons.Get(3, allocator).Convert().isEqual(new[] { new Vector2(-0.7366932f, 4.0405293f), new Vector2(0.02077043f, 1.9039481f), new Vector2(-1.8329408f, 0.0f), new Vector2(-4.0998178f, 0.0f), new Vector2(-5.1286488f, 3.2475674f), new Vector2(-3.2424932f, 4.5050044f) }, 0.001f), true); polygons.Dispose(); }
public void Test_00() { var data = BreakerTestData.data[0]; var nPoints = new NativeArray <Vector2>(data, allocator); var iPoints = iGeom.Int(nPoints, allocator); var pShape = new PlainShape(iPoints, true, allocator); iPoints.Dispose(); var indices = pShape.DelaunayTriangulate(allocator); pShape.Dispose(); var triangles = TrianglesBuilder.build(nPoints, indices, allocator); indices.Dispose(); nPoints.Dispose(); var breaker0 = new BreakSolver(5, 300, BreakSolver.SmallSpawnStrategy.no); var polygons0 = breaker0.Divide(triangles, allocator); Assert.AreEqual(polygons0.Count, 3); Assert.AreEqual(polygons0.Get(0, allocator).Convert().isEqual(new[] { new Vector2(2.0710678f, 0.0f), new Vector2(-2.0710678f, 0.0f), new Vector2(-5.0f, 5.0f), new Vector2(-2.0710678f, 7.928932f), new Vector2(2.0710678f, 7.928932f), new Vector2(5.0f, 5.0f) }, 0.001f), true); Assert.AreEqual(polygons0.Get(1, allocator).Convert().isEqual(new[] { new Vector2(-4.1628227f, 3.570849f), new Vector2(-3.1991942f, 1.9258323f), new Vector2(-4.597563f, 0.0f), new Vector2(-6.504041f, 0.0f), new Vector2(-7.6229224f, 2.3770776f), new Vector2(-6.2748384f, 3.7251613f) }, 0.001f), true); Assert.AreEqual(polygons0.Get(2, allocator).Convert().isEqual(new[] { new Vector2(3.199194f, 1.925832f), new Vector2(4.1628222f, 3.5708487f), new Vector2(6.2748384f, 3.7251616f), new Vector2(7.622922f, 2.3770778f), new Vector2(6.504041f, 0.0f), new Vector2(4.597563f, 0.0f) }, 0.001f), true); polygons0.Dispose(); var breaker1 = new BreakSolver(1.5f, 10, BreakSolver.SmallSpawnStrategy.no); var polygons1 = breaker1.Divide(triangles, allocator); Assert.AreEqual(polygons1.Count > 3, true); triangles.Dispose(); }