private SectorPolygon EarClip(List <Vector2> polygon) { SectorPolygon output = new SectorPolygon(); // Early out for convex polygons int conv = IsConvex(polygon); if (conv != 0) { if (conv == -1) { polygon.Reverse(); } output.points = polygon; for (int t = 0; t < polygon.Count - 2; t++) { output.triangles.Add(0); output.triangles.Add(t + 1); output.triangles.Add(t + 2); } return(output); } // Now we earclip List <int> clippedIndexes = new List <int>(); int polygonCount = polygon.Count; int i = 0; int i1, i2, i3; int safe = 5000; while (clippedIndexes.Count < polygonCount - 2 && safe >= 0) // be careful!!! { i1 = i % polygonCount; while (clippedIndexes.Contains(i1)) { i1 = (i1 + 1) % polygonCount; } i2 = (i1 + 1) % polygonCount; while (clippedIndexes.Contains(i2) || i2 == i1) { i2 = (i2 + 1) % polygonCount; } i3 = (i2 + 1) % polygonCount; while (clippedIndexes.Contains(i3) || i3 == i2) { i3 = (i3 + 1) % polygonCount; } bool clipped = false; bool intersects = false; bool straightLine = false; if (PointOnLine(polygon[i1], polygon[i2], polygon[i3])) { straightLine = true; } if (straightLine == false) { for (int j = 0; j < polygonCount; j++) { int j1 = (j + 1) % polygonCount; if (!Vector2.Equals(polygon[i1], polygon[j]) && !Vector2.Equals(polygon[i3], polygon[j])) { if (LinesIntersect(polygon, i1, i3, j, j1) && !Vector2.Equals(polygon[i1], polygon[j1]) && !Vector2.Equals(polygon[i3], polygon[j1])) { intersects = true; break; } List <Vector2> testPoly = new List <Vector2>() { polygon[i1], polygon[i2], polygon[i3] }; if (!Vector2.Equals(polygon[i2], polygon[j]) && PointInPolygon(polygon[j], testPoly)) { intersects = true; break; } } } } if (intersects == false && straightLine == false) { Vector2 midpoint = new Vector2((polygon[i3].x + polygon[i1].x) / 2f, (polygon[i3].y + polygon[i1].y) / 2f); if (PointInPolygon(midpoint, polygon)) { // Clippit!!! clippedIndexes.Add(i2); output.triangles.Add(i1); output.triangles.Add(i2); output.triangles.Add(i3); clipped = true; } } if (clipped == false) { i += 1; safe -= 1; } } if (!IsClockwise(polygon)) { output.triangles.Reverse(); } output.points = polygon; if (safe <= 0) { // OPTIMISATION: Every time this is hit, the polygon is triangulated but we didn't catch it had finished // If we can succeessfully detect when it is done it'll hit this less and triangulation will be faster // Edit: i think we don't hit this any more Debug.LogWarning("EarClip: while loop broke safety net. Clipped Indexes :" + clippedIndexes.Count + " polygonCount: " + polygonCount); System.IO.File.WriteAllText("outputtriangles.json", JsonUtility.ToJson(output, true)); } return(output); }
public List <SectorPolygon> Triangulate(int sector) { if (benchmark) { debugTime = Time.realtimeSinceStartup; } int i; // Trace sector lines List <List <Vector2> > polygons; try { polygons = TraceLines(sector); } catch { Debug.LogError("Error tracing lines on sector: " + sector.ToString()); return(null); } if (benchmark) { traceLinesTime += Time.realtimeSinceStartup - debugTime; debugTime = Time.realtimeSinceStartup; } if (polygons == null) { return(null); } // Remove points on straight lines for (i = 0; i < polygons.Count; i++) { polygons[i] = CleanLines(polygons[i]); } if (benchmark) { cleanLinesTime += Time.realtimeSinceStartup - debugTime; debugTime = Time.realtimeSinceStartup; } // Determine islands if (polygons.Count == 0) { return(null); } List <SectorIsland> islands = BuildIslands(polygons); if (benchmark) { buildIslandsTime += Time.realtimeSinceStartup - debugTime; debugTime = Time.realtimeSinceStartup; } // Cut islands List <List <Vector2> > cutPolygons = new List <List <Vector2> >(); for (i = 0; i < islands.Count; i++) { List <Vector2> cut = islands[i].Cut(); if (cut != null) { cutPolygons.Add(cut); } } if (benchmark) { cutPolygonsTime += Time.realtimeSinceStartup - debugTime; debugTime = Time.realtimeSinceStartup; } // Ear clip List <SectorPolygon> output = new List <SectorPolygon>(); for (i = 0; i < cutPolygons.Count; i++) { SectorPolygon sp = EarClip(cutPolygons[i]); if (sp != null) { output.Add(sp); } } if (benchmark) { earClipTime += Time.realtimeSinceStartup - debugTime; debugTime = Time.realtimeSinceStartup; } // Output return(output); }