gecl 0.2.0

geometry types and a color type
Documentation
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)));
    }
}