use crate::*;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(C)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Ellipse<T> {
pub center: Point<T>,
pub radius: Vector<T>,
}
impl<T> Ellipse<T> {
#[inline]
pub fn new(center: impl Into<Point<T>>, radius: impl Into<Vector<T>>) -> Self {
Self {
center: center.into(),
radius: radius.into(),
}
}
}
impl<T: ToPrimitive> Ellipse<T> {
#[inline]
pub fn cast<U: NumCast>(self) -> Option<Ellipse<U>> {
Some(Ellipse::new(
self.center.cast::<U>()?,
self.radius.cast::<U>()?,
))
}
}
impl<T> Ellipse<T>
where
T: std::ops::Add<T, Output = T> + Copy,
{
#[inline]
pub fn translate(&self, v: impl Into<Vector<T>>) -> Self {
let v = v.into();
Self::new(self.center + v, self.radius)
}
}
impl<T> Ellipse<T>
where
T: std::ops::Mul<T, Output = T> + Copy,
{
#[inline]
pub fn scale(&self, s: T) -> Self {
Self::new(self.center, self.radius * s)
}
}
#[inline]
pub fn ellipse<T>(center: impl Into<Point<T>>, radius: impl Into<Vector<T>>) -> Ellipse<T> {
Ellipse::new(center, radius)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn eq_test() {
assert!(ellipse((10, 20), (3, 4)) == ellipse((10, 20), (3, 4)));
}
#[test]
fn translate_test() {
assert!(ellipse((10, 20), (3, 4)).translate((1, 2)) == ellipse((11, 22), (3, 4)));
}
#[test]
fn scale_test() {
assert!(ellipse((10, 20), (3, 4)).scale(2) == ellipse((10, 20), (6, 8)));
}
}