private List <List <IntPoint> > ClipToRooms(List <IntPoint> roomFootprint, bool allowSplit) { _clipper.Clear(); _clipper.AddPath(roomFootprint, PolyType.ptSubject, true); _clipper.AddPaths(_rooms.Select(r => r.OuterFootprint.Select(ToPoint).ToList()).ToList(), PolyType.ptClip, true); var solution = new PolyTree(); _clipper.Execute(ClipType.ctDifference, solution); //Rooms with holes are not supported if (HasHole(solution)) { //Rooms with holes are not supported (issue #166 - Will Not Fix) return(new List <List <IntPoint> >()); } var shapes = Clipper.ClosedPathsFromPolyTree(solution); if (shapes.Count > 1 && !allowSplit) { return(new List <List <IntPoint> >()); } return(shapes); }
public List <DTPolygon> Subtract(DTPolygon subject, DTPolygon clippingPolygon) { if (!DTUtility.BoundsCheck(subject.Contour, clippingPolygon.Contour)) { // There is no overlap at all, so output a copy of the subject polygon return(new List <DTPolygon>() { new DTPolygon(new List <Vector2>(subject.Contour)) }); } clipper.Clear(); // Add subject polygon paths clipper.AddPath(subject.Contour.ToIntPointList(), PolyType.ptSubject, true); foreach (var hole in subject.Holes) { clipper.AddPath(hole.ToIntPointList(), PolyType.ptSubject, true); } // Add clipping polygon paths clipper.AddPath(clippingPolygon.Contour.ToIntPointList(), PolyType.ptClip, true); foreach (var hole in clippingPolygon.Holes) { clipper.AddPath(hole.ToIntPointList(), PolyType.ptClip, true); } // Execute subtraction and store result in a PolyTree so that we can easily identify holes PolyTree clipperOutput = new PolyTree(); clipper.Execute(ClipType.ctDifference, clipperOutput, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero); // Convert Polytree into list of DTPolygons return(clipperOutput.ToDTPolygons()); }
/// <summary> /// Clean up a proposed corridor shape (primarily removing holes, which are invalid in a floorplan) /// </summary> /// <param name="clipper"></param> /// <param name="outline"></param> /// <param name="corridor"></param> /// <param name="width"></param> /// <returns></returns> public static List <List <IntPoint> > CleanCorridorPolygon(Clipper clipper, List <IntPoint> outline, IEnumerable <Vector2> corridor, float width) { //Clean up after the previous run, just in case clipper.Clear(); //Clip this spanning tree to the footprint of the floorplan (to create a polytree) var result = new List <List <IntPoint> >(); clipper.AddPath(outline, PolyType.ptClip, true); clipper.AddPath(corridor.Select(ToPoint).ToList(), PolyType.ptSubject, true); clipper.Execute(ClipType.ctIntersection, result); //Clean up after self, to be polite clipper.Clear(); //Keep simplifying, and removing holes until nothing happens do { //merge together vertices which are very close result = Clipper.CleanPolygons(result, width / 8); //Remove holes from the result var holes = result.RemoveAll(r => !Clipper.Orientation(r)); //Once we have one single polygon, or removing holes did nothing we've finished! if (result.Count == 1 || holes == 0) { return(result); } } while (result.Count > 0); //This shouldn't ever happen unless we simplify away to nothing return(result); }
public static List <List <Vector2> > Simplify(List <Vector2> polygon, FillMode fillMode, out PolyTree tree) { Clipper.Clear(); Clipper.AddPath(polygon, PolyType.ptSubject, true); Clipper.AddPath(polygon, PolyType.ptClip, true); tree = new PolyTree(); PolyFillType fillType = fillMode.ToPolyFillType(); Clipper.Execute(ClipType.ctUnion, tree, fillType, fillType); return(Clipper.ClosedPathsFromPolyTree(tree)); }
private static IReadOnlyList <IReadOnlyList <Vector2> > CalculateCorners(IReadOnlyList <Vector2> outer, float width, IReadOnlyList <Section> sections) { const float TOLERANCE = 0.01f; //Reform inner boundary, but slightly larger than it should be (that's our error tolerance); var inner = outer.Shrink(width - TOLERANCE, 1); //Reform outer boundary, but slightly smaller than it should be (more error tolerance) var outerAdjusted = outer.Shrink(TOLERANCE, 1000); var clipper = new Clipper(); //Create a ring shape which is all the outer walls of this room (outer - inner) clipper.AddPath(outerAdjusted.Select(ToPoint).ToList(), PolyType.ptSubject, true); clipper.AddPath(inner.Select(ToPoint).ToList(), PolyType.ptClip, true); var ringResult = new List <List <IntPoint> >(); clipper.Execute(ClipType.ctDifference, ringResult); //Now subtract all the wall sections clipper.Clear(); clipper.AddPaths(ringResult, PolyType.ptSubject, true); foreach (var section in sections) { clipper.AddPath(new List <IntPoint> { ToPoint(section.Inner1), ToPoint(section.Inner2), ToPoint(section.Outer1), ToPoint(section.Outer2) }, PolyType.ptClip, true); } var result = new List <List <IntPoint> >(); clipper.Execute(ClipType.ctDifference, result); //Convert back to vectors return(result.Select(a => a.Select(ToVector).ToArray()).ToArray()); }
internal void Reset() { _aPolys.Clear(); _bPolys.Clear(); _intersectedPolys.Clear(); _clipper.Clear(); }
private List <IntPoint> CreateVoronoiRegion(Site primary) { Clipper c = new Clipper(); var solution = new List <List <IntPoint> >(); List <IntPoint> currentList = null; foreach (var site in Sites) { if (primary.Equals(site)) { continue; } var region = NearestRegion(primary, site); if (currentList == null) { currentList = region; } else { c.Clear(); c.AddPath(currentList, PolyType.ptSubject, true); c.AddPath(region, PolyType.ptClip, true); //c.AddPolygon(currentList, PolyType.ptSubject); //c.AddPolygon(region, PolyType.ptClip); c.Execute(ClipType.ctIntersection, solution); currentList = solution[0]; } } return(currentList); }
private static Ngons MSumFull(Ngon pattern, Ngons subject, bool flip_pattern) { Clipper clipper = new Clipper(); Ngons full = new Ngons(); long scale = flip_pattern ? -1 : 1; for (int i = 0; i < pattern.Count; i++) { clipper.AddPaths(subject.Clone(scale * pattern[i].X, scale * pattern[i].Y), PolyType.ptSubject, true); } clipper.Execute(ClipType.ctUnion, full, PolyFillType.pftNonZero); clipper.Clear(); clipper.AddPaths(full, PolyType.ptSubject, true); clipper.AddPaths(MinkowskiSumBoundary(pattern, subject, flip_pattern), PolyType.ptSubject, true); Ngons res = new Ngons(); clipper.Execute(ClipType.ctUnion, res, PolyFillType.pftNonZero); return(res); }
/// <summary> /// Applies the damage to affected chunks. /// </summary> /// <param name="damage">Damage.</param> private void ApplyDamage(List <IntPoint> damage) { long minX = long.MaxValue, minY = long.MaxValue, maxX = long.MinValue, maxY = long.MinValue; for (int i = 0; i < damage.Count; ++i) { if (damage[i].X < minX) { minX = damage[i].X; } if (damage[i].X > maxX) { maxX = damage[i].X; } if (damage[i].Y < minY) { minY = damage[i].Y; } if (damage[i].Y > maxY) { maxY = damage[i].Y; } } minX = Helper.NegDivision(minX, Chunk.SIZE); maxX = Helper.NegDivision(maxX, Chunk.SIZE); minY = Helper.NegDivision(minY, Chunk.SIZE); maxY = Helper.NegDivision(maxY, Chunk.SIZE); var clipper = new Clipper(); for (int y = (int)minY; y <= maxY; ++y) { for (int x = (int)minX; x <= maxX; ++x) { var chunk = GetChunk(TerrainHelper.PackCoordinates(x, y)); clipper.Clear(); clipper.AddPolygon(new List <IntPoint>() { new IntPoint(chunk.Left, chunk.Top), new IntPoint(chunk.Left + Chunk.SIZE, chunk.Top), new IntPoint(chunk.Left + Chunk.SIZE, chunk.Top + Chunk.SIZE), new IntPoint(chunk.Left, chunk.Top + Chunk.SIZE) }, PolyType.ptSubject); clipper.AddPolygon(damage, PolyType.ptClip); clipper.AddPolygons(chunk.Damage, PolyType.ptClip); clipper.Execute(ClipType.ctIntersection, chunk.Damage, PolyFillType.pftNonZero, PolyFillType.pftNonZero); chunk.Recalculate = true; if (ActiveChunks.Contains(chunk)) { Task.Run(() => { PlaceChunk(chunk); }); } } } }
public void RemoveHoles(float maxPerimiter) { Paths keep = new Paths(); PolyNode node = polyTree.GetFirst(); while (node != null) { if (node.IsHole && node.ChildCount == 0) { var line = LineStripFromPolygon(node.Contour); float length = line.Length(LineStrip.Type.Closed); if (length < maxPerimiter) { // Remove it } else { keep.Add(node.Contour); } } else { keep.Add(node.Contour); } node = node.GetNext(); } Clipper c = new Clipper(); c.Clear(); c.AddPaths(keep, PolyType.ptSubject, true); polyTree = new PolyTree(); c.Execute(ClipType.ctUnion, polyTree); }
IEnumerator RemoveHexagons(IAdminEntity[] entities) { Clipper clipper = new Clipper(); Cell[] cells = _map.cells; for (int j = 0; j < cells.Length; j++) { if (j % 100 == 0) { if (hexifyContext.progress != null) { if (hexifyContext.progress((float)j / cells.Length, hexifyContext.title, "Pass 5/6: removing cells from neighbours...")) { cancelled = true; hexifyContext.finish(true); yield break; } } yield return(null); } int entityIndex = procCells [j].entityIndex; if (entityIndex < 0) { continue; } RegionCell regionCell = procCells [j]; IAdminEntity entity = entities [entityIndex]; // Substract cell region from any other entity List <Region> otherRegions; if (entity is Country) { otherRegions = _map.GetCountryRegionsOverlap(regionCell.cellRegion); } else { otherRegions = _map.GetProvinceRegionsOverlap(regionCell.cellRegion); } int orCount = otherRegions.Count; for (int o = 0; o < orCount; o++) { Region otherRegion = otherRegions [o]; IAdminEntity otherEntity = otherRegion.entity; if (otherEntity == entity) { continue; } clipper.Clear(); clipper.AddPath(otherRegion, PolyType.ptSubject); clipper.AddPath(regionCell.cellRegion, PolyType.ptClip); clipper.Execute(ClipType.ctDifference, otherEntity); } } }
private PolyTree PolygonsToPolyTree(Paths polygons) { var tree = new PolyTree(); Clipper c = new Clipper(); c.Clear(); c.AddPaths(polygons, PolyType.ptSubject, true); c.Execute(ClipType.ctUnion, tree); return(tree); }
public void Union(Slice other) { Clipper c = new Clipper(); c.Clear(); c.AddPaths(Clipper.PolyTreeToPaths(polyTree), PolyType.ptSubject, true); c.AddPaths(Clipper.PolyTreeToPaths(other.polyTree), PolyType.ptClip, true); polyTree = new PolyTree(); c.Execute(ClipType.ctUnion, polyTree); }
public static PolyTree Combine(List <List <ControlPoint> > polygons) { Clipper.Clear(); Clipper.AddPaths(polygons, PolyType.ptSubject, true); Clipper.AddPaths(polygons, PolyType.ptClip, true); var tree = new PolyTree(); Clipper.Execute(ClipType.ctUnion, tree, PolyFillType.pftNonZero, PolyFillType.pftNonZero); return(tree); }
public void SubtractFrom(Slice other) { Clipper c = new Clipper(); c.Clear(); c.AddPaths(PolyTreeToPolygons(other.polyTree), PolyType.ptSubject, true); c.AddPaths(PolyTreeToPolygons(polyTree), PolyType.ptClip, true); polyTree = new PolyTree(); c.Execute(ClipType.ctDifference, polyTree); }
void UpdateFrontPolygon(Polygon surface, Polygon tunnel) { frontPolygons.Clear(); //Lets generate the polygons which represent the landscape. //Clipper c = new Clipper(); clipper.AddPolygon(surface, PolyType.Subject); clipper.AddPolygon(tunnel, PolyType.Clip); bool result = clipper.Execute(ClipType.Difference, frontPolygons, PolyFillType.EvenOdd, PolyFillType.EvenOdd); clipper.Clear(); }
private void BuildBackground(Path clipRect) { _clipper.AddPath(clipRect, PolyType.ptSubject, true); _clipper.AddPaths(_carRoads.Shape, PolyType.ptClip, true); _clipper.AddPaths(_walkRoads.Shape, PolyType.ptClip, true); _clipper.AddPaths(_water.Shape, PolyType.ptClip, true); _clipper.AddPaths(_surfaces.SelectMany(r => r.Shape), PolyType.ptClip, true); var solution = new Paths(); _clipper.Execute(ClipType.ctDifference, solution, PolyFillType.pftPositive, PolyFillType.pftPositive); _clipper.Clear(); _background = new MeshCanvas.Region() { Shape = solution }; }
/// <summary> /// Calculate the intersection of all given shapes /// </summary> /// <param name="clipper"></param> /// <param name="shapes"></param> /// <param name="scale"></param> /// <returns></returns> public static IEnumerable <IEnumerable <Vector2> > IntersectAll(this Clipper clipper, IEnumerable <IEnumerable <Vector2> > shapes, int scale = 1000) { //Just in case someone else made a mess, clean up before we start clipper.Clear(); //First shape is taken as the first "previous" var previous = new List <List <IntPoint> > { shapes.First().Select(a => new IntPoint(a.X * scale, a.Y * scale)).ToList() }; //Loop through each shape (except the first) intersecting reuslts of all previous intersections with this shape foreach (var shape in shapes.Skip(1)) { clipper.AddPaths(previous, PolyType.ptSubject, true); clipper.AddPath(shape.Select(a => new IntPoint(a.X * scale, a.Y * scale)).ToList(), PolyType.ptClip, true); clipper.Execute(ClipType.ctIntersection, previous); clipper.Clear(); } //Convert back into normal scale return(previous.Select(s => s.Select(v => new Vector2((float)v.X / scale, (float)v.Y / scale)))); }
private Paths ClipByRectangle(Path clipRect, Paths subjects) { Clipper clipper = _objectPool.NewObject <Clipper>(); clipper.AddPath(clipRect, PolyType.ptClip, true); clipper.AddPaths(subjects, PolyType.ptSubject, true); var solution = new Paths(); clipper.Execute(ClipType.ctIntersection, solution); clipper.Clear(); _objectPool.StoreObject(clipper); return(solution); }
IEnumerator AddHexagons(IAdminEntity[] entities) { Cell[] cells = _map.cells; Clipper clipper = new Clipper(); for (int j = 0; j < cells.Length; j++) { if (j % 100 == 0) { if (hexifyContext.progress != null) { if (hexifyContext.progress((float)j / cells.Length, hexifyContext.title, "Pass 3/6: adding hexagons to frontiers...")) { cancelled = true; hexifyContext.finish(true); yield break; } } yield return(null); } int entityIndex = procCells [j].entityIndex; if (entityIndex < 0) { continue; } Cell cell = cells [j]; // Create a region for the cell IAdminEntity entity = entities [entityIndex]; Vector2[] newPoints = new Vector2[6]; for (int k = 0; k < 6; k++) { newPoints [k].x = hexagonPoints [k].x + cell.center.x; newPoints [k].y = hexagonPoints [k].y + cell.center.y; } procCells [j].cellRegion = new Region(entity, entity.regions.Count); procCells [j].cellRegion.UpdatePointsAndRect(newPoints); // Add region to target entity's polygon - only if the entity is touching or crossing target entity frontier Region targetRegion = procCells [j].entityRegion; clipper.Clear(); clipper.AddPath(targetRegion, PolyType.ptSubject); clipper.AddPath(procCells [j].cellRegion, PolyType.ptClip); clipper.Execute(ClipType.ctUnion); } }
private static Polygon ClipPolygon(Polygon subject, Polygon clip, ClipType operation) { Paths clprResult = new Paths(); // Convert to library structure Paths clprSubject = PolygonToClprPaths(subject); Paths clprClip = PolygonToClprPaths(clip); // Execute clip action lock (ClipperEngine) { ClipperEngine.Clear(); ClipperEngine.AddPaths(clprSubject, PolyType.ptSubject, true); ClipperEngine.AddPaths(clprClip, PolyType.ptClip, true); ClipperEngine.Execute(operation, clprResult); } // Convert back to common polygon return(ClprPathsToPolygon(clprResult)); }
/// <summary> /// Inverts the selection. /// </summary> /// <param name="surface"> /// Surface for the selection path. /// </param> /// <param name='imageSize'> /// The size of the document. /// </param> public void Invert(Surface surface, Gdk.Size imageSize) { List <List <IntPoint> > resultingPolygons = new List <List <IntPoint> > (); var documentPolygon = CreateRectanglePolygon(new Rectangle(0, 0, imageSize.Width, imageSize.Height)); // Create a rectangle that is the size of the entire image, // and subtract all of the polygons in the current selection from it. SelectionClipper.AddPolygon(documentPolygon, PolyType.ptSubject); SelectionClipper.AddPolygons(SelectionPolygons, PolyType.ptClip); SelectionClipper.Execute(ClipType.ctDifference, resultingPolygons); SelectionClipper.Clear(); SelectionPolygons = resultingPolygons; MarkDirty(); }
/// <summary> /// 使用Clipper将阻挡裁剪出来 /// </summary> private static List <List <IntPoint> > ClipPolygons(List <List <IntPoint> > walkablePolygons, List <List <IntPoint> > blockedPolygons) { //合并可走区域 List <List <IntPoint> > result = new List <List <IntPoint> >(); Clipper clipper = new Clipper(); clipper.AddPolygons(walkablePolygons, PolyType.ptClip); clipper.Execute(ClipType.ctUnion, result, PolyFillType.pftNonZero, PolyFillType.pftNonZero); clipper.Clear(); //去掉不可走区域 clipper.AddPolygons(result, PolyType.ptSubject); clipper.AddPolygons(blockedPolygons, PolyType.ptClip); clipper.Execute(ClipType.ctDifference, result); return(result); }
private PolyTree GetPolyTree(IEnumerable <LineStrip> lines, PolyFillType pft) { Paths polygons = new Paths(); Clipper c = new Clipper(); c.Clear(); foreach (var line in lines) { polygons.Add(LineStripToPolygon(line)); } polygons = Clipper.SimplifyPolygons(polygons, pft); c.AddPaths(polygons, PolyType.ptSubject, true); PolyTree tree = new PolyTree(); c.Execute(ClipType.ctUnion, tree); return(tree); }
public static Ngons MinkowskiSumBoundary(Ngon pattern, Ngons path, bool flip_pattern) { Clipper clipper = new Clipper(); Ngons full = new Ngons(); for (int i = 0; i < path.Count; i++) { Ngons seg = MinkowskiSumBoundary(pattern, path[i], flip_pattern); clipper.AddPaths(full, PolyType.ptSubject, true); clipper.AddPaths(seg, PolyType.ptSubject, true); Ngons res = new Ngons(); clipper.Execute(ClipType.ctUnion, res, PolyFillType.pftNonZero); full = res; clipper.Clear(); } return(full); }
public bool Contains(Slice other) { // To contain another slice: // 1. Area of the union must be the same // 2. Area of this - other must be less float thisArea = this.Area(); Paths otherPolygons = Clipper.PolyTreeToPaths(other.polyTree); Paths thesePolygons = Clipper.PolyTreeToPaths(polyTree); Slice s = new Slice(this); Clipper c = new Clipper(); c.Clear(); c.AddPaths(thesePolygons, PolyType.ptSubject, true); c.AddPaths(otherPolygons, PolyType.ptClip, true); s.polyTree = new PolyTree(); c.Execute(ClipType.ctUnion, s.polyTree); float area_union = s.Area(); if (area_union > thisArea) { return(false); } return(true); //c.Clear(); //c.AddPaths(thesePolygons, PolyType.ptSubject, true); //c.AddPaths(otherPolygons, PolyType.ptClip, true); //s.polyTree = new PolyTree(); //c.Execute(ClipType.ctDifference, s.polyTree); //float area_difference = s.Area(); //if (area_difference < thisArea) //{ // return true; //} //return false; }
private bool Intersects(Tile tile, GeoReference elem) { var element = FindGeoElement(elem); // do the clipping var tb = GM.TileBounds(tile.TileTms, tile.Zoom); var tilePoints = AdaptToClipper(new List <Vector2d> { tb.Min, tb.Min + new Vector2d(tb.Width, 0), tb.Min + new Vector2d(tb.Width, tb.Height), tb.Min + new Vector2d(0, tb.Height) }.ConvertAll(p => GM.MetersToLatLon(p))); var geoPoints = AdaptToClipper(element.Geometry.Points); var solution = new List <List <IntPoint> >(); clipper.Clear(); clipper.AddPath(tilePoints, PolyType.ptSubject, true); clipper.AddPath(geoPoints, PolyType.ptSubject, true); return(clipper.Execute(ClipType.ctIntersection, solution) && solution.Count > 0); }
PushPolygonToArray(List <List <IntPoint> > subjects, List <List <IntPoint> > clips) { Polygons nextClip = new Polygons(); Polygons currentSubject = new Polygons(); Polygons currentClip = new Polygons(); Polygons currentArrayDraw = new Polygons(); Polygons currentArrayInvisible = new Polygons(); Clipper cTupleDraw = new Clipper(); Clipper cTupleInvisible = new Clipper(); //find polygons to be drawn currentSubject.Clear(); currentClip.Clear(); currentSubject = subjects; currentClip = clips; cTupleDraw.Clear(); cTupleDraw.AddPaths(currentSubject, PolyType.ptSubject, true); cTupleDraw.AddPaths(currentClip, PolyType.ptClip, true); currentArrayDraw.Clear(); bool succeededDraw = cTupleDraw.Execute(ClipType.ctDifference, currentArrayDraw, PolyFillType.pftNonZero, PolyFillType.pftNonZero); //find next clipped polygon nextClip.Clear(); bool succeededNextClip = cTupleDraw.Execute(ClipType.ctUnion, nextClip, PolyFillType.pftNonZero, PolyFillType.pftNonZero); //find invisible polygons cTupleInvisible.Clear(); cTupleInvisible.AddPaths(currentSubject, PolyType.ptSubject, true); cTupleInvisible.AddPaths(currentClip, PolyType.ptClip, true); currentArrayInvisible.Clear(); bool succeededInvisible = cTupleInvisible.Execute(ClipType.ctIntersection, currentArrayInvisible, PolyFillType.pftNonZero, PolyFillType.pftNonZero); return(new Tuple <List <List <IntPoint> >, List <List <IntPoint> >, List <List <IntPoint> > > (currentArrayDraw, currentArrayInvisible, nextClip)); }
public void Calculate() { Debug.Log("Calculate"); c.Clear(); subj[0].Clear(); clip[0].Clear(); solution.Clear(); for (int i = listSolutionPolygon.Count - 1; i >= 0; --i) { Destroy(listSolutionPolygon[i]); } listSolutionPolygon.Clear(); var roomShapeSubject = listPolygon[0].GetComponent <RoomShape> (); foreach (var pointData in roomShapeSubject.Points) { subj[0].Add(new IntPoint(pointData.point.vec.x, pointData.point.vec.y)); } var roomShapeClip = listPolygon[1].GetComponent <RoomShape> (); foreach (var pointData in roomShapeClip.Points) { clip[0].Add(new IntPoint(pointData.point.vec.x, pointData.point.vec.y)); } c.AddPaths(subj, PolyType.ptSubject, true); c.AddPaths(clip, PolyType.ptClip, true); c.Execute(clipType, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd); Debug.Log("solution count:" + solution.Count + " points count: " + (solution.Count > 0 ? solution[0].Count.ToString() : "0")); DrawPolygons(solution, "0xFF00009A".hexToColor(), "0xFF00669A".hexToColor(), true); }
internal static void ClipGeometry(VectorUtils.Geometry geom) { UnityEngine.Profiling.Profiler.BeginSample("ClipGeometry"); var clipper = new Clipper(); foreach (var clipperPaths in m_ClipStack) { var vertices = new List <Vector2>(geom.Vertices.Length); var indices = new List <UInt16>(geom.Indices.Length); var paths = BuildTriangleClipPaths(geom); var result = new List <List <IntPoint> >(); UInt16 maxIndex = 0; foreach (var path in paths) { clipper.AddPaths(clipperPaths, PolyType.ptClip, true); clipper.AddPath(path, PolyType.ptSubject, true); clipper.Execute(ClipType.ctIntersection, result, PolyFillType.pftNonZero, PolyFillType.pftNonZero); if (result.Count > 0) { BuildGeometryFromClipPaths(geom, result, vertices, indices, ref maxIndex); } clipper.Clear(); result.Clear(); } geom.Vertices = vertices.ToArray(); geom.Indices = indices.ToArray(); } UnityEngine.Profiling.Profiler.EndSample(); }