public static int[] TesselatePolygon(V[] vertices) { var count = vertices.Length; if (count < 3) { throw new ArgumentException("Tesselator needs at least 3 vertices"); } var result = new int[(count - 2) * 3]; var resInd = 0; var tessVerts = TessVertex.CircularList(count); foreach (var tv in tessVerts) { UpdateVertexAngle(tv, vertices); } foreach (var tv in tessVerts) { UpdateIsEar(tv, vertices); } while (count > 3) { var curr = tessVerts.Where(v => v.IsEar).MinItems(v => v.Angle).First(); var prev = curr.Previous; var next = curr.Next; result[resInd++] = prev.Index; result[resInd++] = curr.Index; result[resInd++] = next.Index; curr.Delete(); UpdateVertexAngle(prev, vertices); UpdateVertexAngle(next, vertices); UpdateIsEar(prev, vertices); UpdateIsEar(next, vertices); tessVerts = next; count--; } foreach (var tv in tessVerts) { result[resInd++] = tv.Index; } return(result); }
private static void UpdateIsEar(TessVertex current, V[] vertices) { if (current.IsReflex) { current.IsEar = false; } else { var prev = current.Previous; var next = current.Next; var p0 = vertices[prev.Index].position; var p1 = vertices[current.Index].position; var p2 = vertices[next.Index].position; current.IsEar = current.Where(v => v != current && v != prev && v != next && v.IsReflex) .All(cv => !PointInTriangle(vertices[cv.Index].position, p0, p1, p2)); } }
private static void UpdateVertexAngle(TessVertex tessVert, V[] vertices) { tessVert.Angle = AngleBetweenEdges( tessVert.Previous.Index, tessVert.Index, tessVert.Next.Index, vertices); }