// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedMember.Global
using System;
using System.Diagnostics;
namespace RGB.NET.Core;
///
/// Represents a point consisting of a X- and a Y-position.
///
[DebuggerDisplay("[X: {X}, Y: {Y}]")]
public readonly struct Point : IEquatable
{
#region Constants
private static readonly Point INVALID = new(float.NaN, float.NaN);
///
/// Gets a [NaN,NaN]-Point.
///
public static ref readonly Point Invalid => ref INVALID;
#endregion
#region Properties & Fields
///
/// Gets the X-position of this .
///
public float X { get; }
///
/// Gets the Y-position of this .
///
public float Y { get; }
#endregion
#region Constructors
///
/// Initializes a new instance of the class using the provided values.
///
/// The value used for the X-position.
/// The value used for the Y-position.
public Point(float x, float y)
{
this.X = x;
this.Y = y;
}
#endregion
#region Methods
///
/// Converts the - and -position of this to a human-readable string.
///
/// A string that contains the and of this . For example "[X: 100, Y: 20]".
public override string ToString() => $"[X: {X}, Y: {Y}]";
///
/// Tests whether the specified is equivalent to this .
///
/// The point to test.
/// true if is equivalent to this ; otherwise, false.
public bool Equals(Point other) => ((float.IsNaN(X) && float.IsNaN(other.X)) || X.EqualsInTolerance(other.X))
&& ((float.IsNaN(Y) && float.IsNaN(other.Y)) || Y.EqualsInTolerance(other.Y));
///
/// Tests whether the specified object is a and is equivalent to this .
///
/// The object to test.
/// true if is a equivalent to this ; otherwise, false.
public override bool Equals(object? obj) => obj is Point other && Equals(other);
///
/// Returns a hash code for this .
///
/// An integer value that specifies the hash code for this .
public override int GetHashCode() => HashCode.Combine(X, Y);
#endregion
#region Operators
///
/// Returns a value that indicates whether two specified are equal.
///
/// The first to compare.
/// The second to compare.
/// true if and are equal; otherwise, false.
public static bool operator ==(in Point point1, in Point point2) => point1.Equals(point2);
///
/// Returns a value that indicates whether two specified are equal.
///
/// The first to compare.
/// The second to compare.
/// true if and are not equal; otherwise, false.
public static bool operator !=(in Point point1, in Point point2) => !(point1 == point2);
///
/// Returns a new representing the addition of the two provided .
///
/// The first .
/// The second .
/// A new representing the addition of the two provided .
public static Point operator +(in Point point1, in Point point2) => new(point1.X + point2.X, point1.Y + point2.Y);
///
/// Returns a new created from the provided and .
///
/// The of the rectangle.
/// The of the rectangle.
/// The rectangle created from the provided and .
public static Rectangle operator +(in Point point, in Size size) => new(point, size);
///
/// Returns a new representing the subtraction of the two provided .
///
/// The first .
/// The second .
/// A new representing the subtraction of the two provided .
public static Point operator -(in Point point1, in Point point2) => new(point1.X - point2.X, point1.Y - point2.Y);
///
/// Returns a new representing the multiplication of the two provided .
///
/// The first .
/// The second .
/// A new representing the multiplication of the two provided .
public static Point operator *(in Point point1, in Point point2) => new(point1.X * point2.X, point1.Y * point2.Y);
///
/// Returns a new representing the division of the two provided .
///
/// The first .
/// The second .
/// A new representing the division of the two provided .
public static Point operator /(in Point point1, in Point point2)
{
if (point2.X.EqualsInTolerance(0) || point2.Y.EqualsInTolerance(0)) return Invalid;
return new Point(point1.X / point2.X, point1.Y / point2.Y);
}
///
/// Returns a new representing the multiplication of the and the provided .
///
/// The .
/// The .
/// A new representing the multiplication of the and the provided .
public static Point operator *(in Point point, in Scale scale) => new(point.X * scale.Horizontal, point.Y * scale.Vertical);
#endregion
}