#region License /* MoonWorks - Game Development Framework * Copyright 2021 Evan Hemsley */ /* Derived from code by Ethan Lee (Copyright 2009-2021). * Released under the Microsoft Public License. * See fna.LICENSE for details. * Derived from code by the Mono.Xna Team (Copyright 2006). * Released under the MIT License. See monoxna.LICENSE for details. */ #endregion #region Using Statements using System; using System.Diagnostics; #endregion namespace MoonWorks.Math { /// /// Describes a 2D-rectangle. /// [Serializable] [DebuggerDisplay("{DebugDisplayString,nq}")] public struct Rectangle : IEquatable { #region Public Properties /// /// Returns the x coordinate of the left edge of this . /// public int Left { get { return X; } } /// /// Returns the x coordinate of the right edge of this . /// public int Right { get { return (X + Width); } } /// /// Returns the y coordinate of the top edge of this . /// public int Top { get { return Y; } } /// /// Returns the y coordinate of the bottom edge of this . /// public int Bottom { get { return (Y + Height); } } /// /// The top-left coordinates of this . /// public Point Location { get { return new Point(X, Y); } set { X = value.X; Y = value.Y; } } /// /// A located in the center of this 's bounds. /// /// /// If or is an odd number, /// the center point will be rounded down. /// public Point Center { get { return new Point( X + (Width / 2), Y + (Height / 2) ); } } /// /// Whether or not this has a width and /// height of 0, and a position of (0, 0). /// public bool IsEmpty { get { return ((Width == 0) && (Height == 0) && (X == 0) && (Y == 0)); } } #endregion #region Public Static Properties /// /// Returns a with X=0, Y=0, Width=0, and Height=0. /// public static Rectangle Empty { get { return emptyRectangle; } } #endregion #region Internal Properties internal string DebugDisplayString { get { return string.Concat( X.ToString(), " ", Y.ToString(), " ", Width.ToString(), " ", Height.ToString() ); } } #endregion #region Public Fields /// /// The x coordinate of the top-left corner of this . /// public int X; /// /// The y coordinate of the top-left corner of this . /// public int Y; /// /// The width of this . /// public int Width; /// /// The height of this . /// public int Height; #endregion #region Private Static Fields private static Rectangle emptyRectangle = new Rectangle(); #endregion #region Public Constructors /// /// Creates a with the specified /// position, width, and height. /// /// The x coordinate of the top-left corner of the created . /// The y coordinate of the top-left corner of the created . /// The width of the created . /// The height of the created . public Rectangle(int x, int y, int width, int height) { X = x; Y = y; Width = width; Height = height; } #endregion #region Public Methods /// /// Gets whether or not the provided coordinates lie within the bounds of this . /// /// The x coordinate of the point to check for containment. /// The y coordinate of the point to check for containment. /// true if the provided coordinates lie inside this . false otherwise. public bool Contains(int x, int y) { return ((this.X <= x) && (x < (this.X + this.Width)) && (this.Y <= y) && (y < (this.Y + this.Height))); } /// /// Gets whether or not the provided lies within the bounds of this . /// /// The coordinates to check for inclusion in this . /// true if the provided lies inside this . false otherwise. public bool Contains(Point value) { return ((this.X <= value.X) && (value.X < (this.X + this.Width)) && (this.Y <= value.Y) && (value.Y < (this.Y + this.Height))); } /// /// Gets whether or not the provided lies within the bounds of this . /// /// The to check for inclusion in this . /// true if the provided 's bounds lie entirely inside this . false otherwise. public bool Contains(Rectangle value) { return ((this.X <= value.X) && ((value.X + value.Width) <= (this.X + this.Width)) && (this.Y <= value.Y) && ((value.Y + value.Height) <= (this.Y + this.Height))); } public void Contains(ref Point value, out bool result) { result = ((this.X <= value.X) && (value.X < (this.X + this.Width)) && (this.Y <= value.Y) && (value.Y < (this.Y + this.Height))); } public void Contains(ref Rectangle value, out bool result) { result = ((this.X <= value.X) && ((value.X + value.Width) <= (this.X + this.Width)) && (this.Y <= value.Y) && ((value.Y + value.Height) <= (this.Y + this.Height))); } /// /// Increments this 's by the /// x and y components of the provided . /// /// The x and y components to add to this 's . public void Offset(Point offset) { X += offset.X; Y += offset.Y; } /// /// Increments this 's by the /// provided x and y coordinates. /// /// The x coordinate to add to this 's . /// The y coordinate to add to this 's . public void Offset(int offsetX, int offsetY) { X += offsetX; Y += offsetY; } public void Inflate(int horizontalValue, int verticalValue) { X -= horizontalValue; Y -= verticalValue; Width += horizontalValue * 2; Height += verticalValue * 2; } /// /// Checks whether or not this is equivalent /// to a provided . /// /// The to test for equality. /// /// true if this 's x coordinate, y coordinate, width, and height /// match the values for the provided . false otherwise. /// public bool Equals(Rectangle other) { return this == other; } /// /// Checks whether or not this is equivalent /// to a provided object. /// /// The to test for equality. /// /// true if the provided object is a , and this /// 's x coordinate, y coordinate, width, and height /// match the values for the provided . false otherwise. /// public override bool Equals(object obj) { return (obj is Rectangle) && this == ((Rectangle) obj); } public override string ToString() { return ( "{X:" + X.ToString() + " Y:" + Y.ToString() + " Width:" + Width.ToString() + " Height:" + Height.ToString() + "}" ); } public override int GetHashCode() { return (this.X ^ this.Y ^ this.Width ^ this.Height); } /// /// Gets whether or not the other intersects with this rectangle. /// /// The other rectangle for testing. /// true if other intersects with this rectangle; false otherwise. public bool Intersects(Rectangle value) { return (value.Left < Right && Left < value.Right && value.Top < Bottom && Top < value.Bottom); } /// /// Gets whether or not the other intersects with this rectangle. /// /// The other rectangle for testing. /// true if other intersects with this rectangle; false otherwise. As an output parameter. public void Intersects(ref Rectangle value, out bool result) { result = (value.Left < Right && Left < value.Right && value.Top < Bottom && Top < value.Bottom); } #endregion #region Public Static Methods public static bool operator ==(Rectangle a, Rectangle b) { return ((a.X == b.X) && (a.Y == b.Y) && (a.Width == b.Width) && (a.Height == b.Height)); } public static bool operator !=(Rectangle a, Rectangle b) { return !(a == b); } public static Rectangle Intersect(Rectangle value1, Rectangle value2) { Rectangle rectangle; Intersect(ref value1, ref value2, out rectangle); return rectangle; } public static void Intersect( ref Rectangle value1, ref Rectangle value2, out Rectangle result ) { if (value1.Intersects(value2)) { int right_side = System.Math.Min( value1.X + value1.Width, value2.X + value2.Width ); int left_side = System.Math.Max(value1.X, value2.X); int top_side = System.Math.Max(value1.Y, value2.Y); int bottom_side = System.Math.Min( value1.Y + value1.Height, value2.Y + value2.Height ); result = new Rectangle( left_side, top_side, right_side - left_side, bottom_side - top_side ); } else { result = new Rectangle(0, 0, 0, 0); } } public static Rectangle Union(Rectangle value1, Rectangle value2) { int x = System.Math.Min(value1.X, value2.X); int y = System.Math.Min(value1.Y, value2.Y); return new Rectangle( x, y, System.Math.Max(value1.Right, value2.Right) - x, System.Math.Max(value1.Bottom, value2.Bottom) - y ); } public static void Union(ref Rectangle value1, ref Rectangle value2, out Rectangle result) { result.X = System.Math.Min(value1.X, value2.X); result.Y = System.Math.Min(value1.Y, value2.Y); result.Width = System.Math.Max(value1.Right, value2.Right) - result.X; result.Height = System.Math.Max(value1.Bottom, value2.Bottom) - result.Y; } #endregion } }