Last active
March 10, 2018 22:56
-
-
Save sbrl/7f8d31427dfa25af18820306b911b891 to your computer and use it in GitHub Desktop.
[Rectangle.cs] A class to represent an arbitrary rectangle in 2D space. Yes, System.Drawing contains one, but I had issues deserializing into it with JSON.NET. #microlibrary
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace SBRL.Utilities | |
{ | |
/// <summary> | |
/// Represents a rectangle in 2D space. | |
/// </summary> | |
/// <version>v0.3</version> | |
/// <changelog> | |
/// v0.1 - 1st April 2017 | |
/// - Added this changelog! | |
/// v0.2 - 4th May 2017 | |
/// - Fixed Overlap(Rectangle otherRectangle) method | |
/// v0.3 - 10th March 2018 | |
/// - Added static Dimensions(IEnumerable{Rectangle}) for calculating bounding boxes | |
/// - Added Area and Perimeter properties | |
/// - Added Position alias and Size property | |
/// </changelog> | |
public struct Rectangle | |
{ | |
/// <summary> | |
/// A rectangle with all it's properties initialised to zero. | |
/// </summary> | |
public static readonly Rectangle Zero = new Rectangle() { X = 0, Y = 0, Width = 0, Height = 0 }; | |
#region Core Data | |
/// <summary> | |
/// The X coordinate of the rectangle. | |
/// </summary> | |
public float X { get; set; } | |
/// <summary> | |
/// The Y coordinate of the rectangle. | |
/// </summary> | |
/// <value>The y.</value> | |
public float Y { get; set; } | |
/// <summary> | |
/// The width of the rectangle. | |
/// </summary> | |
public float Width { get; set; } | |
/// <summary> | |
/// The height of the rectangle. | |
/// </summary> | |
public float Height { get; set; } | |
#endregion | |
#region Corners | |
/// <summary> | |
/// The top-left corner of the rectangle. | |
/// </summary> | |
public Vector2 TopLeft { | |
get { | |
return new Vector2(X, Y); | |
} | |
} | |
/// <summary> | |
/// The top-right corner of the rectangle. | |
/// </summary> | |
public Vector2 TopRight { | |
get { | |
return new Vector2(X + Width, Y); | |
} | |
} | |
/// <summary> | |
/// The bottom-left corner of the rectangle. | |
/// </summary> | |
public Vector2 BottomLeft { | |
get { | |
return new Vector2(X, Y + Height); | |
} | |
} | |
/// <summary> | |
/// The bottom-right corner of the rectangle. | |
/// </summary> | |
public Vector2 BottomRight { | |
get { | |
return new Vector2(X + Width, Y + Height); | |
} | |
} | |
#endregion | |
#region Edges | |
/// <summary> | |
/// The Y coordinate of the top of the rectangle. | |
/// </summary> | |
public float Top { | |
get { | |
return Y; | |
} | |
set { | |
Y = value; | |
} | |
} | |
/// <summary> | |
/// The Y coordinate of the bottom of the rectangle. | |
/// </summary> | |
public float Bottom { | |
get { | |
return Y + Height; | |
} | |
set { | |
Height = value - Y; | |
} | |
} | |
/// <summary> | |
/// The X coordinate of the left side of the rectangle. | |
/// </summary> | |
public float Left { | |
get { | |
return X; | |
} | |
set { | |
X = value; | |
} | |
} | |
/// <summary> | |
/// The X coordinate of the right side of the rectangle. | |
/// </summary> | |
public float Right { | |
get { | |
return X + Width; | |
} | |
set { | |
Width = value - X; | |
} | |
} | |
#endregion | |
#region Vectors | |
/// <summary> | |
/// Alias to TopLeft. | |
/// </summary> | |
public Vector2 Position { | |
get { | |
return TopLeft; | |
} | |
} | |
/// <summary> | |
/// A Vector2 representing the size of this Rectangle. | |
/// </summary> | |
public Vector2 Size { | |
get { | |
return new Vector2(Width, Height); | |
} | |
} | |
#endregion | |
#region Statistics | |
/// <summary> | |
/// The area that this Rectangle occupies. | |
/// </summary> | |
public float Area { | |
get { | |
return Width * Height; | |
} | |
} | |
/// <summary> | |
/// The perimeter of this Rectangle. | |
/// </summary> | |
public float Perimeter { | |
get { | |
return Width * 2 + Height * 2; | |
} | |
} | |
#endregion | |
public Rectangle(float x, float y, float width, float height) | |
{ | |
X = x; | |
Y = y; | |
Width = width; | |
Height = height; | |
} | |
public Rectangle(Vector2 position, Vector2 size) : this(position.X, position.Y, size.X, size.Y) | |
{ | |
} | |
/// <summary> | |
/// Figures out whether this rectangle overlaps another rectangle. | |
/// </summary> | |
/// <param name="otherRectangle">The other rectangle to check the overlap of.</param> | |
/// <returns>Whether this rectangle overlaps another rectangle.</returns> | |
public bool Overlap(Rectangle otherRectangle) | |
{ | |
if (Top > otherRectangle.Bottom || | |
Bottom < otherRectangle.Top || | |
Left > otherRectangle.Right || | |
Right < otherRectangle.Left) | |
return false; | |
return true; | |
} | |
/// <summary> | |
/// Returns a Rectangle representing the area that this rectangle overlaps with another. | |
/// Returns an empty rectangle if the two don't overlap at all. | |
/// </summary> | |
/// <param name="otherRectangle">The other rectangle that overlaps this one.</param> | |
/// <returns>The area that this rectanagle overlaps with another.</returns> | |
public Rectangle OverlappingArea(Rectangle otherRectangle) | |
{ | |
if (!Overlap(otherRectangle)) | |
return Rectangle.Zero; | |
Rectangle result = new Rectangle(); | |
result.Top = Math.Max(Top, otherRectangle.Top); | |
result.Left = Math.Max(Left, otherRectangle.Left); | |
result.Bottom = Math.Max(Bottom, otherRectangle.Bottom); | |
result.Right = Math.Max(Right, otherRectangle.Right); | |
return result; | |
} | |
public override string ToString() | |
{ | |
return string.Format("[Rectangle: {1}x{2} @ {0}]", Position, Width, Height); | |
} | |
#region Static Methods | |
/// <summary> | |
/// Given a list of Rectangles, returns a bounding box of all the given rectangles. | |
/// </summary> | |
/// <param name="rectangles">The rectangles to calculate the bounding box for.</param> | |
/// <returns>A rectangle bounding box that covers all of the specified rectangles.</returns> | |
public static Rectangle Dimensions(IEnumerable<Rectangle> rectangles) | |
{ | |
Vector2 topLeft = new Vector2( | |
rectangles.Min((Rectangle rect) => rect.Left), | |
rectangles.Min((Rectangle rect) => rect.Top) | |
); | |
Vector2 bottomRight = new Vector2( | |
rectangles.Max((Rectangle rect) => rect.Right), | |
rectangles.Max((Rectangle rect) => rect.Bottom) | |
); | |
return new Rectangle( | |
topLeft, | |
bottomRight.Subtract(topLeft) | |
); | |
} | |
#endregion | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment