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