// ----------------------------------------------------------------------- // // Copyright 2014 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex { using System; using System.Globalization; /// /// Defines a rectangle. /// public struct Rect { /// /// The X position. /// private double x; /// /// The Y position. /// private double y; /// /// The width. /// private double width; /// /// The height. /// private double height; /// /// Initializes a new instance of the structure. /// /// The X position. /// The Y position. /// The width. /// The height. public Rect(double x, double y, double width, double height) { this.x = x; this.y = y; this.width = width; this.height = height; } /// /// Initializes a new instance of the structure. /// /// The size of the rectangle. public Rect(Size size) { this.x = 0; this.y = 0; this.width = size.Width; this.height = size.Height; } /// /// Initializes a new instance of the structure. /// /// The position of the rectangle. /// The size of the rectangle. public Rect(Point position, Size size) { this.x = position.X; this.y = position.Y; this.width = size.Width; this.height = size.Height; } /// /// Initializes a new instance of the structure. /// /// The top left position of the rectangle. /// The bottom right position of the rectangle. public Rect(Point topLeft, Point bottomRight) { this.x = topLeft.X; this.y = topLeft.Y; this.width = bottomRight.X - topLeft.X; this.height = bottomRight.Y - topLeft.Y; } /// /// Gets the X position. /// public double X { get { return this.x; } } /// /// Gets the Y position. /// public double Y { get { return this.y; } } /// /// Gets the width. /// public double Width { get { return this.width; } } /// /// Gets the height. /// public double Height { get { return this.height; } } /// /// Gets the position of the rectangle. /// public Point Position { get { return new Point(this.x, this.y); } } /// /// Gets the size of the rectangle. /// public Size Size { get { return new Size(this.width, this.height); } } /// /// Gets the right position of the rectangle. /// public double Right { get { return this.x + this.width; } } /// /// Gets the bottom position of the rectangle. /// public double Bottom { get { return this.y + this.height; } } /// /// Gets the top left point of the rectangle. /// public Point TopLeft { get { return new Point(this.x, this.y); } } /// /// Gets the top right point of the rectangle. /// public Point TopRight { get { return new Point(this.Right, this.y); } } /// /// Gets the bottom left point of the rectangle. /// public Point BottomLeft { get { return new Point(this.x, this.Bottom); } } /// /// Gets the bottom right point of the rectangle. /// public Point BottomRight { get { return new Point(this.Right, this.Bottom); } } /// /// Gets the center point of the rectangle. /// public Point Center { get { return new Point(this.x + (this.width / 2), this.y + (this.height / 2)); } } /// /// Gets a value that indicates whether the rectangle is empty. /// public bool IsEmpty { get { return this.width == 0 && this.height == 0; } } /// /// Checks for equality between two s. /// /// The first rect. /// The second rect. /// True if the rects are equal; otherwise false. public static bool operator ==(Rect left, Rect right) { return left.Position == right.Position && left.Size == right.Size; } /// /// Checks for unequality between two s. /// /// The first rect. /// The second rect. /// True if the rects are unequal; otherwise false. public static bool operator !=(Rect left, Rect right) { return !(left == right); } public static Rect operator *(Rect rect, Vector scale) { double centerX = rect.x + (rect.width / 2); double centerY = rect.y + (rect.height / 2); double width = rect.width * scale.X; double height = rect.height * scale.Y; return new Rect( centerX - (width / 2), centerY - (height / 2), width, height); } public static Rect operator *(Rect rect, Matrix matrix) { return new Rect(rect.TopLeft * matrix, rect.BottomRight * matrix); } public static Rect operator /(Rect rect, Vector scale) { double centerX = rect.x + (rect.width / 2); double centerY = rect.y + (rect.height / 2); double width = rect.width / scale.X; double height = rect.height / scale.Y; return new Rect( centerX - (width / 2), centerY - (height / 2), width, height); } /// /// Determines whether a points in in the bounds of the rectangle. /// /// The point. /// true if the point is in the bounds of the rectangle; otherwise false. public bool Contains(Point p) { return p.X >= this.x && p.X < this.x + this.width && p.Y >= this.y && p.Y < this.y + this.height; } public Rect CenterIn(Rect rect) { return new Rect( this.x + ((this.width - rect.width) / 2), this.y + ((this.height - rect.height) / 2), rect.width, rect.height); } /// /// Inflates the rectangle. /// /// The thickness. /// The inflated rectangle. public Rect Inflate(double thickness) { return this.Inflate(thickness); } /// /// Inflates the rectangle. /// /// The thickness. /// The inflated rectangle. public Rect Inflate(Thickness thickness) { return new Rect( new Point(this.x - thickness.Left, this.y - thickness.Top), this.Size.Inflate(thickness)); } /// /// Deflates the rectangle. /// /// The thickness. /// The deflated rectangle. /// The deflated rectangle size cannot be less than 0. public Rect Deflate(double thickness) { return this.Deflate(new Thickness(thickness / 2)); } /// /// Deflates the rectangle by a . /// /// The thickness. /// The deflated rectangle. /// The deflated rectangle size cannot be less than 0. public Rect Deflate(Thickness thickness) { return new Rect( new Point(this.x + thickness.Left, this.y + thickness.Top), this.Size.Deflate(thickness)); } public override bool Equals(object obj) { if (obj is Rect) { return this == (Rect)obj; } return false; } public override int GetHashCode() { unchecked { int hash = 17; hash = (hash * 23) + this.X.GetHashCode(); hash = (hash * 23) + this.Y.GetHashCode(); hash = (hash * 23) + this.Width.GetHashCode(); hash = (hash * 23) + this.Height.GetHashCode(); return hash; } } public Rect Intersect(Rect rect) { double x = Math.Max(this.x, rect.x); double y = Math.Max(this.y, rect.y); double width = Math.Min(this.Right, rect.Right) - x; double height = Math.Min(this.Bottom, rect.Bottom) - y; if (width < 0 || height < 0) { return new Rect( double.PositiveInfinity, double.PositiveInfinity, double.NegativeInfinity, double.NegativeInfinity); } else { return new Rect(x, y, width, height); } } /// /// Returns the string representation of the rectangle. /// /// The string representation of the rectangle. public override string ToString() { return string.Format( CultureInfo.InvariantCulture, "{0}, {1}, {2}, {3}", this.x, this.y, this.width, this.height); } } }