using System; using Robust.Shared.Maths; namespace Robust.Shared.Physics.Collision { /// /// A rectangle that is always axis-aligned. /// [Serializable] internal readonly struct AlignedRectangle : IEquatable { /// /// Center point of the rectangle in world space. /// public readonly Vector2 Center; /// /// Half of the total width and height of the rectangle. /// public readonly Vector2 HalfExtents; /// /// A 1x1 unit rectangle with the origin centered on the world origin. /// public static readonly AlignedRectangle UnitCentered = new(new Vector2(0.5f, 0.5f)); /// /// The lower X coordinate of the left edge of the box. /// public float Left => Center.X - HalfExtents.X; /// /// The higher X coordinate of the right edge of the box. /// public float Right => Center.X + HalfExtents.X; /// /// The lower Y coordinate of the top edge of the box. /// public float Bottom => Center.Y - HalfExtents.Y; /// /// The higher Y coordinate of the bottom of the box. /// public float Top => Center.Y + HalfExtents.Y; public AlignedRectangle(Box2 box) { var halfWidth = box.Width / 2; var halfHeight = box.Height / 2; HalfExtents = new Vector2(halfWidth, halfHeight); Center = new Vector2(box.Left + halfWidth, box.Height + halfHeight); } public AlignedRectangle(Vector2 halfExtents) { Center = default; HalfExtents = halfExtents; } public AlignedRectangle(Vector2 center, Vector2 halfExtents) { Center = center; HalfExtents = halfExtents; } /// /// Given a point, returns the closest point to it inside the box. /// public Vector2 ClosestPoint(in Vector2 position) { // clamp the point to the border of the box var cx = MathHelper.Clamp(position.X, Left, Right); var cy = MathHelper.Clamp(position.Y, Bottom, Top); return new Vector2(cx, cy); } #region Equality members public bool Equals(AlignedRectangle other) { return Center.Equals(other.Center) && HalfExtents.Equals(other.HalfExtents); } public override bool Equals(object? obj) { return obj is AlignedRectangle other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(Center, HalfExtents); } public static bool operator ==(AlignedRectangle left, AlignedRectangle right) { return left.Equals(right); } public static bool operator !=(AlignedRectangle left, AlignedRectangle right) { return !left.Equals(right); } #endregion /// /// Returns the string representation of this object. /// public override string ToString() { return $"({Left}, {Bottom}, {Right}, {Top})"; } } }