// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable
using System.Runtime.CompilerServices;
namespace SixLabors.PolygonClipper {
///
/// Represents a sweep.
///
internal sealed class SweepEvent
{
///
/// Initializes a new instance of the class.
///
/// The point associated with the event.
/// Whether the point is the left endpoint of the segment.
/// The event associated with the other endpoint of the segment.
/// The polygon type to which the segment belongs.
/// The type of the edge. Default is .
public SweepEvent(
Vertex point,
bool left,
SweepEvent otherEvent,
PolygonType polygonType = PolygonType.Subject,
EdgeType edgeType = EdgeType.Normal)
{
this.Point = point;
this.Left = left;
this.OtherEvent = otherEvent;
this.PolygonType = polygonType;
this.EdgeType = edgeType;
}
///
/// Initializes a new instance of the class.
///
/// The point associated with the event.
/// Whether the point is the left endpoint of the segment.
/// The polygon type to which the segment belongs.
public SweepEvent(Vertex point, bool left, PolygonType polygonType = PolygonType.Subject)
{
this.Point = point;
this.Left = left;
this.PolygonType = polygonType;
this.EdgeType = EdgeType.Normal;
}
///
/// Initializes a new instance of the class.
///
/// The point associated with the event.
/// Whether the point is the left endpoint of the segment.
/// The ID of the contour to which the event belongs.
public SweepEvent(Vertex point, bool left, int contourId)
{
this.Point = point;
this.Left = left;
this.ContourId = contourId;
this.PolygonType = PolygonType.Subject;
this.EdgeType = EdgeType.Normal;
}
///
/// Gets the point associated with the event.
///
public Vertex Point { get; }
///
/// Gets or sets a value indicating whether the point is the
/// left (source) endpoint of the segment (p, other->p).
///
public bool Left { get; set; }
///
/// Gets or sets the ID of the contour to which the event belongs.
///
public int ContourId { get; set; }
///
/// Gets index of the polygon to which the associated segment belongs to;
///
public PolygonType PolygonType { get; }
///
/// Gets or sets the type of the edge.
///
public EdgeType EdgeType { get; set; }
///
/// Gets or sets the event associated to the other endpoint of the segment.
///
public SweepEvent OtherEvent { get; set; }
///
/// Gets or sets a value indicating whether the segment (p, other->p) represent an
/// inside-outside transition in the polygon for a vertical ray from (p.x, -infinite)
/// that crosses the segment.
///
public bool InOut { get; set; }
///
/// Gets or sets a value indicating whether the inOut transition for the segment from
/// the other polygon preceding this segment in the sweep line.
///
public bool OtherInOut { get; set; }
///
/// Gets or sets the sorted sweep events. Only used in "left" events.
/// Position of the event (segment) in SL (status line).
///
public int PosSL { get; set; }
///
/// Gets or sets the previous segment in the sweep line belonging to the result of the
/// boolean operation.
///
public SweepEvent PrevInResult { get; set; }
///
/// Gets or sets the transition state of the event in the result.
///
public ResultTransition ResultTransition { get; set; }
///
/// Gets a value indicating whether the event contributes to the result.
///
public bool InResult => this.ResultTransition != ResultTransition.Neutral;
///
/// Gets or sets the position of the event in the sorted events.
///
public int Pos { get; set; }
///
/// Gets or sets a value indicating whether the event is a result in-out transition.
///
public bool ResultInOut { get; set; }
///
/// Gets or sets the output contour ID associated with this contour.
///
public int OutputContourId { get; set; }
///
/// Is the line segment (point, otherEvent->point) below point p.
///
/// The point to check against.
///
/// if the line segment is below the point; otherwise .
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsBelow(in Vertex p)
=> this.Left
? PolygonUtilities.SignedArea(this.Point, this.OtherEvent.Point, p) > 0D
: PolygonUtilities.SignedArea(this.OtherEvent.Point, this.Point, p) > 0D;
///
/// Is the line segment (point, otherEvent->point) above point p.
///
/// The point to check against.
///
/// if the line segment is above the point; otherwise .
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsAbove(in Vertex p) => !this.IsBelow(p);
///
/// Is the line segment (point, otherEvent->point) a vertical line segment.
///
///
/// if the line segment is vertical; otherwise .
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsVertical() => this.Point.X == this.OtherEvent.Point.X;
///
/// Determines if this sweep event comes before another sweep event.
///
/// The other sweep event to compare with.
///
/// if this event comes before the other; otherwise .
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsBefore(SweepEvent other)
{
// Compare by x-coordinate first
if (this.Point.X != other.Point.X)
{
return this.Point.X < other.Point.X;
}
// If x-coordinates are equal, compare by y-coordinate
return this.Point.Y < other.Point.Y;
}
///
/// Returns the segment associated with the sweep event.
///
/// The .
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Segment GetSegment() => new(this.Point, this.OtherEvent.Point);
}
}