Example #1
0
        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);
        }
Example #2
0
        private static Double2[] FillPolygon(Curve[] contour)
        {
            // "Guess" a capacity for the list, add the first point
            var list = new List <Double2>((int)(1.4 * contour.Length));

            // Check first if the last and first curve aren't joinable
            bool lastFirstJoin = FillFace.AreCurvesFusable(contour[contour.Length - 1], contour[0]);

            if (lastFirstJoin)
            {
                list.Add(contour[0].At(1));
            }

            // Now, scan the curve list for pairs of scannable curves
            var k = lastFirstJoin ? 1 : 0;

            for (int i = k; i < contour.Length - k; i++)
            {
                if (i < contour.Length - 1 && FillFace.AreCurvesFusable(contour[i], contour[i + 1]))
                {
                    // If they describe a positive winding on the plane, add only its endpoint
                    var endp0 = contour[i].At(0);
                    var endp1 = contour[i + 1].At(1);
                    var pth   = (endp0 + endp1) / 2;
                    if (contour[i].WindingRelativeTo(pth) + contour[i + 1].WindingRelativeTo(pth) > 0)
                    {
                        list.Add(endp1);
                    }
                    else
                    {
                        // Else, compute the convex hull and add the correct point sequence
                        var points = contour[i].EnclosingPolygon.Concat(contour[i + 1].EnclosingPolygon).ToArray();
                        var hull   = GeometricUtils.ConvexHull(points);
                        var hl     = hull.Length;

                        // We have to go through the hull clockwise. Find the first point
                        int ik;
                        for (ik = 0; ik < hl; ik++)
                        {
                            if (hull[ik] == endp0)
                            {
                                break;
                            }
                        }

                        // And run through it
                        for (int i0 = ik; i0 != (ik + 1) % hl; i0 = (i0 + hl - 1) % hl)
                        {
                            list.Add(hull[i0]);
                        }
                    }
                    i++;
                }
                else if (contour[i].Type == CurveType.Line || contour[i].IsConvex)
                {
                    list.Add(contour[i].At(1));
                }
                else
                {
                    list.AddRange(contour[i].EnclosingPolygon.Skip(1));
                }
            }

            // Sanitize the list; identical vertices
            var indices = new List <int>();

            for (int i = 0; i < list.Count; i++)
            {
                if (DoubleUtils.RoughlyEquals(list[i], list[(i + 1) % list.Count]))
                {
                    indices.Add(i);
                }
            }

            list.ExtractIndices(indices.ToArray());
            return(list.ToArray());
        }