// 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
}
}