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