// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // namespace ImageProcessorCore { using System; using System.ComponentModel; using System.Numerics; /// /// Stores a set of four integers that represent the location and size of a rectangle. /// /// /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, /// as it avoids the need to create new values for modification operations. /// public struct Rectangle : IEquatable { /// /// Represents a that has X, Y, Width, and Height values set to zero. /// public static readonly Rectangle Empty = default(Rectangle); /// /// The backing vector for SIMD support. /// private Vector4 backingVector; /// /// Initializes a new instance of the struct. /// /// The horizontal position of the rectangle. /// The vertical position of the rectangle. /// The width of the rectangle. /// The height of the rectangle. public Rectangle(int x, int y, int width, int height) { this.backingVector = new Vector4(x, y, width, height); } /// /// Initializes a new instance of the struct. /// /// /// The which specifies the rectangles point in a two-dimensional plane. /// /// /// The which specifies the rectangles height and width. /// public Rectangle(Point point, Size size) { this.backingVector = new Vector4(point.X, point.Y, size.Width, size.Height); } /// /// Initializes a new instance of the struct. /// /// The vector. public Rectangle(Vector4 vector) { this.backingVector = vector; } /// /// The x-coordinate of this . /// public int X { get { return (int)this.backingVector.X; } set { this.backingVector.X = value; } } /// /// The y-coordinate of this . /// public int Y { get { return (int)this.backingVector.Y; } set { this.backingVector.Y = value; } } /// /// The width of this . /// public int Width { get { return (int)this.backingVector.Z; } set { this.backingVector.Z = value; } } /// /// The height of this . /// public int Height { get { return (int)this.backingVector.W; } set { this.backingVector.W = value; } } /// /// Gets a value indicating whether this is empty. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool IsEmpty => this.Equals(Empty); /// /// Gets the y-coordinate of the top edge of this . /// public int Top => this.Y; /// /// Gets the x-coordinate of the right edge of this . /// public int Right => this.X + this.Width; /// /// Gets the y-coordinate of the bottom edge of this . /// public int Bottom => this.Y + this.Height; /// /// Gets the x-coordinate of the left edge of this . /// public int Left => this.X; /// /// Computes the sum of adding two rectangles. /// /// The rectangle on the left hand of the operand. /// The rectangle on the right hand of the operand. /// /// The /// public static Rectangle operator +(Rectangle left, Rectangle right) { return new Rectangle(left.backingVector + right.backingVector); } /// /// Computes the difference left by subtracting one rectangle from another. /// /// The rectangle on the left hand of the operand. /// The rectangle on the right hand of the operand. /// /// The /// public static Rectangle operator -(Rectangle left, Rectangle right) { return new Rectangle(left.backingVector - right.backingVector); } /// /// Compares two objects for equality. /// /// /// The on the left side of the operand. /// /// /// The on the right side of the operand. /// /// /// True if the current left is equal to the parameter; otherwise, false. /// public static bool operator ==(Rectangle left, Rectangle right) { return left.Equals(right); } /// /// Compares two objects for inequality. /// /// /// The on the left side of the operand. /// /// /// The on the right side of the operand. /// /// /// True if the current left is unequal to the parameter; otherwise, false. /// public static bool operator !=(Rectangle left, Rectangle right) { return !left.Equals(right); } /// /// Determines if the specfied point is contained within the rectangular region defined by /// this . /// /// The x-coordinate of the given point. /// The y-coordinate of the given point. /// The public bool Contains(int x, int y) { // TODO: SIMD? return this.X <= x && x < this.Right && this.Y <= y && y < this.Bottom; } /// /// Returns the center point of the given /// /// The rectangle /// public static Point Center(Rectangle rectangle) { return new Point(rectangle.Left + rectangle.Width / 2, rectangle.Top + rectangle.Height / 2); } /// public override int GetHashCode() { return this.GetHashCode(this); } /// public override string ToString() { if (this.IsEmpty) { return "Rectangle [ Empty ]"; } return $"Rectangle [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; } /// public override bool Equals(object obj) { if (obj is Rectangle) { return this.Equals((Rectangle)obj); } return false; } /// public bool Equals(Rectangle other) { return this.backingVector.Equals(other.backingVector); } /// /// Returns the hash code for this instance. /// /// /// The instance of to return the hash code for. /// /// /// A 32-bit signed integer that is the hash code for this instance. /// private int GetHashCode(Rectangle rectangle) { return rectangle.backingVector.GetHashCode(); } } }