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