// // 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; public struct Ellipse : IEquatable { /// /// The center point. /// private Point center; /// /// Represents a that has X and Y values set to zero. /// public static readonly Ellipse Empty = default(Ellipse); public Ellipse(Point center, float radiusX, float radiusY) { this.center = center; this.RadiusX = radiusX; this.RadiusY = radiusY; } /// /// Gets the x-radius of this . /// public float RadiusX { get; } /// /// Gets the y-radius of this . /// public float RadiusY { get; } /// /// Gets a value indicating whether this is empty. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool IsEmpty => this.Equals(Empty); /// /// 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 ==(Ellipse left, Ellipse 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 !=(Ellipse left, Ellipse right) { return !left.Equals(right); } /// /// Returns the center point of the given /// /// The ellipse /// public static Vector2 Center(Ellipse ellipse) { return new Vector2(ellipse.center.X, ellipse.center.Y); } /// /// Determines if the specfied point is contained within the rectangular region defined by /// this . /// /// The x-coordinate of the given point. /// The y-coordinate of the given point. /// The public bool Contains(int x, int y) { if (this.RadiusX <= 0 || this.RadiusY <= 0) { return false; } // TODO: SIMD? // This is a more general form of the circle equation // X^2/a^2 + Y^2/b^2 <= 1 Point normalized = new Point(x - this.center.X, y - this.center.Y); int nX = normalized.X; int nY = normalized.Y; return (double)(nX * nX) / (this.RadiusX * this.RadiusX) + (double)(nY * nY) / (this.RadiusY * this.RadiusY) <= 1.0; } /// public override int GetHashCode() { return this.GetHashCode(this); } /// public override string ToString() { if (this.IsEmpty) { return "Ellipse [ Empty ]"; } return $"Ellipse [ RadiusX={this.RadiusX}, RadiusY={this.RadiusX}, Centre={this.center.X},{this.center.Y} ]"; } /// public override bool Equals(object obj) { if (obj is Ellipse) { return this.Equals((Ellipse)obj); } return false; } /// public bool Equals(Ellipse other) { return this.center.Equals(other.center) && this.RadiusX.Equals(other.RadiusX) && this.RadiusY.Equals(other.RadiusY); } /// /// 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(Ellipse ellipse) { unchecked { int hashCode = ellipse.center.GetHashCode(); hashCode = (hashCode * 397) ^ ellipse.RadiusX.GetHashCode(); hashCode = (hashCode * 397) ^ ellipse.RadiusY.GetHashCode(); return hashCode; } } } }