// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.PolygonClipper; using System; using System.Collections.Generic; using PCPolygon = SixLabors.PolygonClipper.Polygon; namespace SixLabors.ImageSharp.Drawing.PolygonGeometry { /// /// Builders for from ImageSharp paths. /// Converts ImageSharp paths to the format required by PolygonClipper. /// /// /// PolygonClipper computes parent-child relationships, depth, and orientation during its /// sweep line algorithm, so we only need to provide contours with vertices. /// internal static class PolygonClipperFactory { /// /// Creates a polygon from multiple paths. /// /// The paths to convert. /// A containing all flattened paths as contours. public static PCPolygon FromClosedPaths(IEnumerable paths) { PCPolygon polygon = []; foreach (IPath path in paths) { polygon = FromSimpleClosedPaths(path.Flatten(), polygon); } return polygon; } /// /// Converts closed simple paths to PolygonClipper contours. /// /// Closed simple paths. /// Optional existing polygon to populate. /// The constructed . /// /// This method simply converts ImageSharp paths to PolygonClipper contours by copying vertices. /// PolygonClipper's sweep line algorithm will determine parent-child relationships, depth, /// and proper orientation during clipping operations. We only need to ensure paths are /// closed and have sufficient vertices. /// public static PCPolygon FromSimpleClosedPaths(IEnumerable paths, PCPolygon? polygon = null) { polygon ??= []; foreach (ISimplePath p in paths) { if (!p.IsClosed) { continue; } ReadOnlySpan points = p.Points.Span; if (points.Length < 3) { continue; } Contour contour = []; // Copy all vertices for (int i = 0; i < points.Length; i++) { contour.Add(new Vertex(points[i].X, points[i].Y)); } // Add the contour - PolygonClipper will determine parent/depth/orientation during sweep polygon.Add(contour); } return polygon; } } }