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