// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
namespace SixLabors.ImageSharp.Drawing {
///
/// Enumerates the derived linear segments in a .
///
///
/// The enumerator derives segments from and .
/// Segments are yielded in contour order. Within each contour, adjacent stored points form segments in point order,
/// and a closed contour contributes one additional closing segment from its last stored point back to its first.
///
public ref struct SegmentEnumerator
{
private readonly LinearGeometry geometry;
private int contourIndex;
private int segmentIndexInContour;
private LinearSegment current;
internal SegmentEnumerator(LinearGeometry geometry)
{
this.geometry = geometry;
this.contourIndex = 0;
this.segmentIndexInContour = 0;
this.current = default;
}
///
/// Gets the current derived linear segment.
///
public readonly LinearSegment Current => this.current;
///
/// Advances to the next derived segment.
///
///
/// if a segment was produced; otherwise .
///
public bool MoveNext()
{
while (this.contourIndex < this.geometry.Contours.Count)
{
LinearContour contour = this.geometry.Contours[this.contourIndex];
if (this.segmentIndexInContour < contour.SegmentCount)
{
int pointStart = contour.PointStart;
int pointIndex = pointStart + this.segmentIndexInContour;
PointF start = this.geometry.Points[pointIndex];
PointF end = this.segmentIndexInContour == contour.PointCount - 1
? this.geometry.Points[pointStart]
: this.geometry.Points[pointIndex + 1];
this.current = CreateSegment(start, end);
this.segmentIndexInContour++;
return true;
}
this.contourIndex++;
this.segmentIndexInContour = 0;
}
return false;
}
private static LinearSegment CreateSegment(PointF start, PointF end)
=> new()
{
Start = start,
End = end,
MinY = MathF.Min(start.Y, end.Y),
MaxY = MathF.Max(start.Y, end.Y),
IsHorizontal = start.Y == end.Y
};
}
}