// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
using System.Numerics;
namespace SixLabors.ImageSharp.Drawing {
///
/// A pie sector polygon defined by a center point, radii, rotation, and arc sweep.
///
public sealed class PiePolygon : Polygon
{
///
/// Initializes a new instance of the class.
///
/// The center point of the pie sector.
/// The x and y radii of the pie ellipse.
/// The ellipse rotation in degrees.
/// The pie start angle in degrees.
/// The pie sweep angle in degrees.
public PiePolygon(PointF center, SizeF radius, float rotation, float startAngle, float sweepAngle)
: base(CreateSegments(center, radius, rotation, startAngle, sweepAngle))
{
}
///
/// Initializes a new instance of the class.
///
/// The center point of the pie sector.
/// The x and y radii of the pie ellipse.
/// The pie start angle in degrees.
/// The pie sweep angle in degrees.
public PiePolygon(PointF center, SizeF radius, float startAngle, float sweepAngle)
: this(center, radius, 0F, startAngle, sweepAngle)
{
}
///
/// Initializes a new instance of the class.
///
/// The x-coordinate of the pie center.
/// The y-coordinate of the pie center.
/// The x-radius of the pie ellipse.
/// The y-radius of the pie ellipse.
/// The ellipse rotation in degrees.
/// The pie start angle in degrees.
/// The pie sweep angle in degrees.
public PiePolygon(float x, float y, float radiusX, float radiusY, float rotation, float startAngle, float sweepAngle)
: this(new PointF(x, y), new SizeF(radiusX, radiusY), rotation, startAngle, sweepAngle)
{
}
///
/// Initializes a new instance of the class.
///
/// The x-coordinate of the pie center.
/// The y-coordinate of the pie center.
/// The x-radius of the pie ellipse.
/// The y-radius of the pie ellipse.
/// The pie start angle in degrees.
/// The pie sweep angle in degrees.
public PiePolygon(float x, float y, float radiusX, float radiusY, float startAngle, float sweepAngle)
: this(x, y, radiusX, radiusY, 0F, startAngle, sweepAngle)
{
}
private PiePolygon(ILineSegment[] segments)
: base(segments, true)
{
}
///
public override IPath Transform(Matrix4x4 matrix)
{
if (matrix.IsIdentity)
{
return this;
}
ILineSegment[] segments = new ILineSegment[this.LineSegments.Count];
for (int i = 0; i < segments.Length; i++)
{
segments[i] = this.LineSegments[i].Transform(matrix);
}
return new PiePolygon(segments);
}
private static ILineSegment[] CreateSegments(PointF center, SizeF radius, float rotation, float startAngle, float sweepAngle)
{
Guard.MustBeGreaterThan(radius.Width, 0, "radiusX");
Guard.MustBeGreaterThan(radius.Height, 0, "radiusY");
PointF arcStart = GetArcPoint(center, radius, rotation, startAngle);
ArcLineSegment arc = new(center, radius, rotation, startAngle, sweepAngle);
return
[
new LinearLineSegment(center, arcStart),
arc,
new LinearLineSegment(arc.EndPoint, center)
];
}
private static PointF GetArcPoint(PointF center, SizeF radius, float rotation, float angle)
{
float rotationRadians = rotation * (MathF.PI / 180F);
float angleRadians = angle * (MathF.PI / 180F);
float cosRotation = MathF.Cos(rotationRadians);
float sinRotation = MathF.Sin(rotationRadians);
float cosAngle = MathF.Cos(angleRadians);
float sinAngle = MathF.Sin(angleRadians);
return new PointF(
center.X + (radius.Width * cosRotation * cosAngle) - (radius.Height * sinRotation * sinAngle),
center.Y + (radius.Width * sinRotation * cosAngle) + (radius.Height * cosRotation * sinAngle));
}
}
}