// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; using System.ComponentModel; using System.Numerics; using System.Runtime.CompilerServices; namespace SixLabors.Primitives { /// /// Represents an ordered pair of single precision floating point 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 PointF : IEquatable { /// /// Represents a that has X and Y values set to zero. /// public static readonly PointF Empty = default; /// /// Initializes a new instance of the struct. /// /// The horizontal position of the point. /// The vertical position of the point. public PointF(float x, float y) : this() { this.X = x; this.Y = y; } /// /// Initializes a new instance of the struct from the given . /// /// The size. public PointF(SizeF size) { this.X = size.Width; this.Y = size.Height; } /// /// Gets or sets the x-coordinate of this . /// public float X { get; set; } /// /// Gets or sets the y-coordinate of this . /// public float Y { get; set; } /// /// Gets a value indicating whether this is empty. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool IsEmpty => this.Equals(Empty); /// /// Creates a with the coordinates of the specified . /// /// The vector. /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator PointF(Vector2 vector) => new PointF(vector.X, vector.Y); /// /// Creates a with the coordinates of the specified . /// /// The point. /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Vector2(PointF point) => new Vector2(point.X, point.Y); /// /// Creates a with the coordinates of the specified by truncating each of the coordinates. /// /// The point. /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static explicit operator Point(PointF point) => Point.Truncate(point); /// /// Negates the given point by multiplying all values by -1. /// /// The source point. /// The negated point. public static PointF operator -(PointF value) => new PointF(-value.X, -value.Y); /// /// Translates a by a given . /// /// The point on the left hand of the operand. /// The size on the right hand of the operand. /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static PointF operator +(PointF point, SizeF size) => Add(point, size); /// /// Translates a by the negative of a given . /// /// The point on the left hand of the operand. /// The size on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static PointF operator -(PointF point, PointF size) => Subtract(point, size); /// /// Translates a by a given . /// /// The point on the left hand of the operand. /// The size on the right hand of the operand. /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static PointF operator +(PointF point, PointF size) => Add(point, size); /// /// Translates a by the negative of a given . /// /// The point on the left hand of the operand. /// The size on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static PointF operator -(PointF point, SizeF size) => Subtract(point, size); /// /// Multiplies by a producing . /// /// Multiplier of type . /// Multiplicand of type . /// Product of type . public static PointF operator *(float left, PointF right) => Multiply(right, left); /// /// Multiplies by a producing . /// /// Multiplicand of type . /// Multiplier of type . /// Product of type . public static PointF operator *(PointF left, float right) => Multiply(left, right); /// /// Divides by a producing . /// /// Dividend of type . /// Divisor of type . /// Result of type . public static PointF operator /(PointF left, float right) => new PointF(left.X / right, left.Y / right); /// /// 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. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(PointF left, PointF right) => 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. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(PointF left, PointF right) => !left.Equals(right); /// /// Translates a by the given . /// /// The point on the left hand of the operand. /// The size on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static PointF Add(PointF point, SizeF size) => new PointF(point.X + size.Width, point.Y + size.Height); /// /// Translates a by the given . /// /// The point on the left hand of the operand. /// The point on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static PointF Add(PointF point, PointF pointb) => new PointF(point.X + pointb.X, point.Y + pointb.Y); /// /// Translates a by the negative of a given . /// /// The point on the left hand of the operand. /// The size on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static PointF Subtract(PointF point, SizeF size) => new PointF(point.X - size.Width, point.Y - size.Height); /// /// Translates a by the negative of a given . /// /// The point on the left hand of the operand. /// The point on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static PointF Subtract(PointF point, PointF pointb) => new PointF(point.X - pointb.X, point.Y - pointb.Y); /// /// Translates a by the multiplying the X and Y by the given value. /// /// The point on the left hand of the operand. /// The value on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static PointF Multiply(PointF point, float right) => new PointF(point.X * right, point.Y * right); /// /// Transforms a point by a specified 3x2 matrix. /// /// The point to transform. /// The transformation matrix used. /// The transformed . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static PointF Transform(PointF point, Matrix3x2 matrix) => Vector2.Transform(point, matrix); /// /// Deconstructs this point into two floats. /// /// The out value for X. /// The out value for Y. public void Deconstruct(out float x, out float y) { x = this.X; y = this.Y; } /// /// Translates this by the specified amount. /// /// The amount to offset the x-coordinate. /// The amount to offset the y-coordinate. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Offset(float dx, float dy) { this.X += dx; this.Y += dy; } /// /// Translates this by the specified amount. /// /// The used offset this . [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Offset(PointF point) => this.Offset(point.X, point.Y); /// public override int GetHashCode() => HashCode.Combine(this.X, this.Y); /// public override string ToString() => $"PointF [ X={this.X}, Y={this.Y} ]"; /// public override bool Equals(object obj) => obj is PointF && this.Equals((PointF)obj); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(PointF other) => this.X.Equals(other.X) && this.Y.Equals(other.Y); } }