// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; using System.Runtime.CompilerServices; namespace SixLabors.PolygonClipper { /// /// Represents a bounding box. /// public readonly struct Box2 : IEquatable { /// /// Gets the minimum xy-coordinate. /// #pragma warning disable CA1051 // Do not declare visible instance fields public readonly Vertex Min; /// /// Gets the maximum xy-coordinate. /// public readonly Vertex Max; #pragma warning restore CA1051 // Do not declare visible instance fields /// /// Initializes a new instance of the struct. /// /// The xy-coordinate. [MethodImpl(MethodImplOptions.AggressiveInlining)] public Box2(in Vertex vector) : this(vector, vector) { } /// /// Initializes a new instance of the struct. /// /// The minimum xy-coordinate. /// The maximum xy-coordinate. public Box2(in Vertex min, in Vertex max) { this.Min = min; this.Max = max; } /// /// Gets an invalid bounds instance. /// public static Box2 Invalid { get; } = new( new Vertex(double.MaxValue, double.MaxValue), new Vertex(-double.MaxValue, -double.MaxValue)); /// /// Compares two instances for equality. /// /// The left object. /// The right object. /// true if both boxes are equal; otherwise, false. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(in Box2 left, in Box2 right) => left.Equals(right); /// /// Determines whether two instances are not equal. /// /// The left object. /// The right object. /// true if the boxes are not equal; otherwise, false. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(in Box2 left, in Box2 right) => !(left == right); /// /// Returns true if the box is empty. /// /// if the box is empty; otherwise, . public bool IsEmpty() => this.Max.X <= this.Min.X || this.Max.Y <= this.Min.Y; /// /// Returns true if the point lies within the box. /// /// The point to test. /// if the point lies within the box; otherwise, . public bool Contains(in Vertex point) => point.X > this.Min.X && point.X < this.Max.X && point.Y > this.Min.Y && point.Y < this.Max.Y; /// /// Returns true if the box contains another box. /// /// The other box. /// if the box contains the other box; otherwise, . public bool Contains(in Box2 bounds) => bounds.Min.X >= this.Min.X && bounds.Max.X <= this.Max.X && bounds.Min.Y >= this.Min.Y && bounds.Max.Y <= this.Max.Y; /// /// Returns true if the boxes intersect. /// /// The other box. /// if the boxes intersect; otherwise, . public bool Intersects(in Box2 bounds) => Math.Max(this.Min.X, bounds.Min.X) <= Math.Min(this.Max.X, bounds.Max.X) && Math.Max(this.Min.Y, bounds.Min.Y) <= Math.Min(this.Max.Y, bounds.Max.Y); /// /// Returns the midpoint of the box. /// /// The midpoint. public Vertex MidPoint() => new((this.Min.X + this.Max.X) / 2D, (this.Min.Y + this.Max.Y) / 2D); /// /// Adds another bounding box to this instance. /// /// The other box. /// The summed . [MethodImpl(MethodImplOptions.AggressiveInlining)] public Box2 Add(in Box2 other) => new(Vertex.Min(this.Min, other.Min), Vertex.Max(this.Max, other.Max)); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public override bool Equals(object? obj) => obj is Box2 box && this.Equals(box); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(Box2 other) => this.Min == other.Min && this.Max == other.Max; /// public override int GetHashCode() => HashCode.Combine(this.Min, this.Max); } }