// 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;
}
}
}