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