public static CompiledDrawing FromFace(FillFace face) { var fill = new CompiledDrawing(); // Simplify the face by subdividing overlapping curves var newFace = face.SubdivideOverlapping(); // Build the fill polygons and triangulate them fill.Triangles = Triangulator.YMonotone.Triangulate(newFace.Contours.Select(FillPolygon).ToArray()); // Collect all curve triangles var curves = newFace.Contours.SelectMany(v => v.Where(c => c.Type != CurveType.Line)).ToArray(); var curveTriangles = new List <CurveTriangle>(); var doubleCurveTriangles = new List <DoubleCurveTriangle>(); if (curves.Length > 0) { // Check first if the last and first curve aren't joinable bool lastFirstJoin = curves.Length > 1 && FillFace.AreCurvesFusable(curves[curves.Length - 1], curves[0]); if (lastFirstJoin) { doubleCurveTriangles.AddRange(FuseCurveTriangles(curves[curves.Length - 1], curves[0])); } else { curveTriangles.AddRange(CurveVertex.MakeTriangleFan(curves[0].CurveVertices)); } // Now, scan the curve list for pairs of scannable curves var k = lastFirstJoin ? 1 : 0; for (int i = k; i < curves.Length - k; i++) { if (i < curves.Length - 1 && FillFace.AreCurvesFusable(curves[i], curves[i + 1])) { doubleCurveTriangles.AddRange(FuseCurveTriangles(curves[i], curves[i + 1])); i++; } else { curveTriangles.AddRange(CurveVertex.MakeTriangleFan(curves[i].CurveVertices)); } } } fill.CurveTriangles = curveTriangles.ToArray(); fill.DoubleCurveTriangles = doubleCurveTriangles.ToArray(); return(fill); }