using System;
using System.ComponentModel;
using System.Globalization;
using System.Numerics;
#if !BUILDTASK
using Avalonia.Animation.Animators;
#endif
using Avalonia.Utilities;
namespace Avalonia
{
///
/// Defines a point.
///
#if !BUILDTASK
[TypeConverter(typeof(PointConverter))]
public
#endif
readonly struct Point : IEquatable
{
static Point()
{
#if !BUILDTASK
Animation.Animation.RegisterAnimator(prop => typeof(Point).IsAssignableFrom(prop.PropertyType));
#endif
}
///
/// The X position.
///
private readonly double _x;
///
/// The Y position.
///
private readonly double _y;
///
/// Initializes a new instance of the structure.
///
/// The X position.
/// The Y position.
public Point(double x, double y)
{
_x = x;
_y = y;
}
///
/// Gets the X position.
///
public double X => _x;
///
/// Gets the Y position.
///
public double Y => _y;
///
/// Converts the to a .
///
/// The point.
public static implicit operator Vector(Point p)
{
return new Vector(p._x, p._y);
}
///
/// Negates a point.
///
/// The point.
/// The negated point.
public static Point operator -(Point a)
{
return new Point(-a._x, -a._y);
}
///
/// Checks for equality between two s.
///
/// The first point.
/// The second point.
/// True if the points are equal; otherwise false.
public static bool operator ==(Point left, Point right)
{
return left.Equals(right);
}
///
/// Checks for inequality between two s.
///
/// The first point.
/// The second point.
/// True if the points are unequal; otherwise false.
public static bool operator !=(Point left, Point right)
{
return !(left == right);
}
///
/// Adds two points.
///
/// The first point.
/// The second point.
/// A point that is the result of the addition.
public static Point operator +(Point a, Point b)
{
return new Point(a._x + b._x, a._y + b._y);
}
///
/// Adds a vector to a point.
///
/// The point.
/// The vector.
/// A point that is the result of the addition.
public static Point operator +(Point a, Vector b)
{
return new Point(a._x + b.X, a._y + b.Y);
}
///
/// Subtracts two points.
///
/// The first point.
/// The second point.
/// A point that is the result of the subtraction.
public static Point operator -(Point a, Point b)
{
return new Point(a._x - b._x, a._y - b._y);
}
///
/// Subtracts a vector from a point.
///
/// The point.
/// The vector.
/// A point that is the result of the subtraction.
public static Point operator -(Point a, Vector b)
{
return new Point(a._x - b.X, a._y - b.Y);
}
///
/// Multiplies a point by a factor coordinate-wise
///
/// Point to multiply
/// Factor
/// Points having its coordinates multiplied
public static Point operator *(Point p, double k) => new Point(p.X * k, p.Y * k);
///
/// Multiplies a point by a factor coordinate-wise
///
/// Point to multiply
/// Factor
/// Points having its coordinates multiplied
public static Point operator *(double k, Point p) => new Point(p.X * k, p.Y * k);
///
/// Divides a point by a factor coordinate-wise
///
/// Point to divide by
/// Factor
/// Points having its coordinates divided
public static Point operator /(Point p, double k) => new Point(p.X / k, p.Y / k);
///
/// Applies a matrix to a point.
///
/// The point.
/// The matrix.
/// The resulting point.
public static Point operator *(Point point, Matrix matrix) => matrix.Transform(point);
///
/// Parses a string.
///
/// The string.
/// The .
public static Point Parse(string s)
{
using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Point."))
{
return new Point(
tokenizer.ReadDouble(),
tokenizer.ReadDouble()
);
}
}
///
/// Returns a boolean indicating whether the point is equal to the other given point (bitwise).
///
/// The other point to test equality against.
/// True if this point is equal to other; False otherwise.
public bool Equals(Point other)
{
// ReSharper disable CompareOfFloatsByEqualityOperator
return _x == other._x &&
_y == other._y;
// ReSharper enable CompareOfFloatsByEqualityOperator
}
///
/// Returns a boolean indicating whether the point is equal to the other given point
/// (numerically).
///
/// The other point to test equality against.
/// True if this point is equal to other; False otherwise.
public bool NearlyEquals(Point other)
{
return MathUtilities.AreClose(_x, other._x) &&
MathUtilities.AreClose(_y, other._y);
}
///
/// Checks for equality between a point and an object.
///
/// The object.
///
/// True if is a point that equals the current point.
///
public override bool Equals(object? obj) => obj is Point other && Equals(other);
///
/// Returns a hash code for a .
///
/// The hash code.
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = (hash * 23) + _x.GetHashCode();
hash = (hash * 23) + _y.GetHashCode();
return hash;
}
}
///
/// Returns the string representation of the point.
///
/// The string representation of the point.
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "{0}, {1}", _x, _y);
}
///
/// Transforms the point by a matrix.
///
/// The transform.
/// The transformed point.
public Point Transform(Matrix transform) => transform.Transform(this);
///
/// Returns a new point with the specified X coordinate.
///
/// The X coordinate.
/// The new point.
public Point WithX(double x)
{
return new Point(x, _y);
}
///
/// Returns a new point with the specified Y coordinate.
///
/// The Y coordinate.
/// The new point.
public Point WithY(double y)
{
return new Point(_x, y);
}
///
/// Deconstructs the point into its X and Y coordinates.
///
/// The X coordinate.
/// The Y coordinate.
public void Deconstruct(out double x, out double y)
{
x = this._x;
y = this._y;
}
///
/// Gets a value indicating whether the X and Y coordinates are zero.
///
public bool IsDefault
{
get { return (_x == 0) && (_y == 0); }
}
}
}