// MIT License - Copyright (C) The Mono.Xna Team // This file is subject to the terms and conditions defined in // file 'LICENSE.txt', which is part of this source code package. using System; using System.Runtime.Serialization; using System.Diagnostics; namespace CommonLang.Geometry { /// /// Describes a 2D-rectangle. /// public struct Rectangle : IEquatable { #region Private Fields private static Rectangle emptyRectangle = new Rectangle(); #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 Public Properties /// /// Returns a with X=0, Y=0, Width=0, Height=0. /// public static Rectangle Empty { get { return emptyRectangle; } } /// /// Returns the x coordinate of the left edge of this . /// public int Left { get { return this.X; } } /// /// Returns the x coordinate of the right edge of this . /// public int Right { get { return (this.X + this.Width); } } /// /// Returns the y coordinate of the top edge of this . /// public int Top { get { return this.Y; } } /// /// Returns the y coordinate of the bottom edge of this . /// public int Bottom { get { return (this.Y + this.Height); } } /// /// Whether or not this has a and /// of 0, and a of (0, 0). /// public bool IsEmpty { get { return ((((this.Width == 0) && (this.Height == 0)) && (this.X == 0)) && (this.Y == 0)); } } /// /// The top-left coordinates of this . /// public Point Location { get { return new Point(this.X, this.Y); } set { X = value.X; Y = value.Y; } } /// /// The width-height coordinates of this . /// public Point Size { get { return new Point(this.Width,this.Height); } set { Width = value.X; Height = value.Y; } } /// /// A located in the center of this . /// /// /// If or is an odd number, /// the center point will be rounded down. /// public Point Center { get { return new Point(this.X + (this.Width / 2), this.Y + (this.Height / 2)); } } #endregion #region Internal Properties internal string DebugDisplayString { get { return string.Concat( this.X, " ", this.Y, " ", this.Width, " ", this.Height ); } } #endregion #region Constructors /// /// Creates a new instance of struct, 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) { this.X = x; this.Y = y; this.Width = width; this.Height = height; } /// /// Creates a new instance of struct, with the specified /// location and size. /// /// The x and y coordinates of the top-left corner of the created . /// The width and height of the created . public Rectangle(Point location,Point size) { this.X = location.X; this.Y = location.Y; this.Width = size.X; this.Height = size.Y; } #endregion #region Operators /// /// Compares whether two instances are equal. /// /// instance on the left of the equal sign. /// instance on the right of the equal sign. /// true if the instances are equal; false otherwise. 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)); } /// /// Compares whether two instances are not equal. /// /// instance on the left of the not equal sign. /// instance on the right of the not equal sign. /// true if the instances are not equal; false otherwise. public static bool operator !=(Rectangle a, Rectangle b) { return !(a == b); } #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 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(float x, float 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 coordinates to check for inclusion in this . /// true if the provided lies inside this ; false otherwise. As an output parameter. 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))); } /// /// 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(Vector2 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 coordinates to check for inclusion in this . /// true if the provided lies inside this ; false otherwise. As an output parameter. public void Contains(ref Vector2 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))); } /// /// 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))); } /// /// 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. As an output parameter. 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))); } /// /// Compares whether current instance is equal to specified . /// /// The to compare. /// true if the instances are equal; false otherwise. public override bool Equals(object obj) { return (obj is Rectangle) && this == ((Rectangle)obj); } /// /// Compares whether current instance is equal to specified . /// /// The to compare. /// true if the instances are equal; false otherwise. public bool Equals(Rectangle other) { return this == other; } /// /// Gets the hash code of this . /// /// Hash code of this . public override int GetHashCode() { return (X ^ Y ^ Width ^ Height); } /// /// Adjusts the edges of this by specified horizontal and vertical amounts. /// /// Value to adjust the left and right edges. /// Value to adjust the top and bottom edges. public void Inflate(int horizontalAmount, int verticalAmount) { X -= horizontalAmount; Y -= verticalAmount; Width += horizontalAmount * 2; Height += verticalAmount * 2; } /// /// Adjusts the edges of this by specified horizontal and vertical amounts. /// /// Value to adjust the left and right edges. /// Value to adjust the top and bottom edges. public void Inflate(float horizontalAmount, float verticalAmount) { X -= (int)horizontalAmount; Y -= (int)verticalAmount; Width += (int)horizontalAmount * 2; Height += (int)verticalAmount * 2; } /// /// Gets whether or not a specified intersects with this . /// /// Other . /// true if other intersects with this ; false otherwise. public bool Intersects(Rectangle value) { return value.Left < Right && Left < value.Right && value.Top < Bottom && Top < value.Bottom; } /// /// Gets whether or not a specified intersects with this . /// /// Other . /// true if other intersects with this ; 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; } /// /// Creates a new that contains overlapping region of two other rectangles. /// /// The first . /// The second . /// Overlapping region of the two rectangles. public static Rectangle Intersect(Rectangle value1, Rectangle value2) { Rectangle rectangle; Intersect(ref value1, ref value2, out rectangle); return rectangle; } /// /// Creates a new that contains overlapping region of two other rectangles. /// /// The first . /// The second . /// Overlapping region of the two rectangles as an output parameter. public static void Intersect(ref Rectangle value1, ref Rectangle value2, out Rectangle result) { if (value1.Intersects(value2)) { int right_side = Math.Min(value1.X + value1.Width, value2.X + value2.Width); int left_side = Math.Max(value1.X, value2.X); int top_side = Math.Max(value1.Y, value2.Y); int bottom_side = 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); } } /// /// Changes the of this . /// /// The x coordinate to add to this . /// The y coordinate to add to this . public void Offset(int offsetX, int offsetY) { X += offsetX; Y += offsetY; } /// /// Changes the of this . /// /// The x coordinate to add to this . /// The y coordinate to add to this . public void Offset(float offsetX, float offsetY) { X += (int)offsetX; Y += (int)offsetY; } /// /// Changes the of this . /// /// The x and y components to add to this . public void Offset(Point amount) { X += amount.X; Y += amount.Y; } /// /// Changes the of this . /// /// The x and y components to add to this . public void Offset(Vector2 amount) { X += (int)amount.X; Y += (int)amount.Y; } /// /// Returns a representation of this in the format: /// {X:[] Y:[] Width:[] Height:[]} /// /// representation of this . public override string ToString() { return "{X:" + X + " Y:" + Y + " Width:" + Width + " Height:" + Height + "}"; } /// /// Creates a new that completely contains two other rectangles. /// /// The first . /// The second . /// The union of the two rectangles. public static Rectangle Union(Rectangle value1, Rectangle value2) { int x = Math.Min(value1.X, value2.X); int y = Math.Min(value1.Y, value2.Y); return new Rectangle(x, y, Math.Max(value1.Right, value2.Right) - x, Math.Max(value1.Bottom, value2.Bottom) - y); } /// /// Creates a new that completely contains two other rectangles. /// /// The first . /// The second . /// The union of the two rectangles as an output parameter. public static void Union(ref Rectangle value1, ref Rectangle value2, out Rectangle result) { result.X = Math.Min(value1.X, value2.X); result.Y = Math.Min(value1.Y, value2.Y); result.Width = Math.Max(value1.Right, value2.Right) - result.X; result.Height = Math.Max(value1.Bottom, value2.Bottom) - result.Y; } #endregion } }