// // 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; /// /// Represents an ordered pair of integer x- and y-coordinates that defines a point in /// a two-dimensional plane. /// /// /// 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 Point : IEquatable { /// /// Represents a that has X and Y values set to zero. /// public static readonly Point Empty = default(Point); /// /// The backing vector for SIMD support. /// private Vector2 backingVector; /// /// Initializes a new instance of the struct. /// /// The horizontal position of the point. /// The vertical position of the point. public Point(int x, int y) : this() { this.backingVector = new Vector2(x, y); } /// /// Initializes a new instance of the struct. /// /// /// The vector representing the width and height. /// public Point(Vector2 vector) { this.backingVector = new Vector2(vector.X, vector.Y); } /// /// 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; } } /// /// Gets a value indicating whether this is empty. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool IsEmpty => this.Equals(Empty); /// /// Computes the sum of adding two points. /// /// The point on the left hand of the operand. /// The point on the right hand of the operand. /// /// The /// public static Point operator +(Point left, Point right) { return new Point(left.backingVector + right.backingVector); } /// /// Computes the difference left by subtracting one point from another. /// /// The point on the left hand of the operand. /// The point on the right hand of the operand. /// /// The /// public static Point operator -(Point left, Point right) { return new Point(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 ==(Point left, Point 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 !=(Point left, Point right) { return !left.Equals(right); } /// /// Gets a representation for this . /// /// A representation for this object. public Vector2 ToVector2() { return new Vector2(this.X, this.Y); } /// /// Creates a rotation matrix for the given point and angle. /// /// The origin point to rotate around /// Rotation in degrees /// The rotation public static Matrix3x2 CreateRotation(Point origin, float degrees) { float radians = ImageMaths.DegreesToRadians(degrees); return Matrix3x2.CreateRotation(radians, origin.backingVector); } /// /// Rotates a point around a given a rotation matrix. /// /// The point to rotate /// Rotation matrix used /// The rotated public static Point Rotate(Point point, Matrix3x2 rotation) { return new Point(Vector2.Transform(point.backingVector, rotation)); } /// /// Rotates a point around a given origin by the specified angle in degrees. /// /// The point to rotate /// The center point to rotate around. /// The angle in degrees. /// The rotated public static Point Rotate(Point point, Point origin, float degrees) { return new Point(Vector2.Transform(point.backingVector, CreateRotation(origin, degrees))); } /// /// Creates a skew matrix for the given point and angle. /// /// The origin point to rotate around /// The x-angle in degrees. /// The y-angle in degrees. /// The rotation public static Matrix3x2 CreateSkew(Point origin, float degreesX, float degreesY) { float radiansX = ImageMaths.DegreesToRadians(degreesX); float radiansY = ImageMaths.DegreesToRadians(degreesY); return Matrix3x2.CreateSkew(radiansX, radiansY, origin.backingVector); } /// /// Skews a point using a given a skew matrix. /// /// The point to rotate /// Rotation matrix used /// The rotated public static Point Skew(Point point, Matrix3x2 skew) { return new Point(Vector2.Transform(point.backingVector, skew)); } /// /// Skews a point around a given origin by the specified angles in degrees. /// /// The point to skew. /// The center point to rotate around. /// The x-angle in degrees. /// The y-angle in degrees. /// The skewed public static Point Skew(Point point, Point origin, float degreesX, float degreesY) { return new Point(Vector2.Transform(point.backingVector, CreateSkew(origin, degreesX, degreesY))); } /// public override int GetHashCode() { return this.GetHashCode(this); } /// public override string ToString() { if (this.IsEmpty) { return "Point [ Empty ]"; } return $"Point [ X={this.X}, Y={this.Y} ]"; } /// public override bool Equals(object obj) { if (obj is Point) { return this.Equals((Point)obj); } return false; } /// public bool Equals(Point 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(Point point) { return point.backingVector.GetHashCode(); } } }