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