mutils 12.7.0

Mathematical-like utilities. Points, Sizes, Colours, maths operating on them. Things like that.
Documentation
use std::convert::From;
use std::ops::Add;

use num_traits::sign::Signed;

use crate::geom::Line;
use crate::geom::Point;
use crate::geom::Size;
use crate::num::Num;
use crate::num::NumIdentity;

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Transform<N: Num = f32> {
    scale: Size<N>,
    position: Point<N>,
    rotation: f32,
}

impl<N: Num> Transform<N> {
    #[must_use]
    pub fn new() -> Self {
        Self {
            position: Point::new_zero_value(),
            scale: Size::new_one_value(),
            rotation: 0.0,
        }
    }

    #[must_use]
    pub fn set_position(mut self, position: Point<N>) -> Self {
        self.position = position;
        self
    }

    pub fn position(&self) -> Point<N> {
        self.position
    }

    #[must_use]
    pub fn set_rotation(mut self, rotation: f32) -> Self {
        self.rotation = rotation;
        self
    }

    pub fn rotation(&self) -> f32 {
        self.rotation
    }

    #[must_use]
    fn set_scale_width(mut self, scale_width: N) -> Self {
        self.scale.set_width(scale_width);
        self
    }

    #[must_use]
    fn set_scale_height(mut self, scale_height: N) -> Self {
        self.scale.set_height(scale_height);
        self
    }

    #[must_use]
    pub fn set_scale(mut self, scale: Size<N>) -> Self {
        self.scale = scale;
        self
    }

    pub fn scale(self) -> Size<N> {
        self.scale
    }
}

impl<N> Transform<N>
where
    N: Num + Signed,
{
    pub fn set_flip_x_from_dir_num(self, dir: f32) -> Self {
        self.set_flip_x_from_bool(dir < 0.0)
    }

    pub fn set_flip_y_from_dir_num(self, dir: f32) -> Self {
        self.set_flip_y_from_bool(dir < 0.0)
    }

    pub fn set_flip_x_from_bool(self, is_flipped: bool) -> Self {
        if is_flipped {
            self.set_scale_width(-<N as NumIdentity>::one())
        } else {
            self.set_scale_width(<N as NumIdentity>::one())
        }
    }

    pub fn set_flip_y_from_bool(self, is_flipped: bool) -> Self {
        if is_flipped {
            self.set_scale_height(-<N as NumIdentity>::one())
        } else {
            self.set_scale_height(<N as NumIdentity>::one())
        }
    }
}

impl<N> Add<Line<N>> for Transform<N>
where
    N: Num,
{
    type Output = Line<N>;

    fn add(self, line: Self::Output) -> Self::Output {
        line.rotate_around_zero(self.rotation()) * self.scale() + self.position()
    }
}

impl<N> Add<Point<N>> for Transform<N>
where
    N: Num,
{
    type Output = Point<N>;

    fn add(self, point: Self::Output) -> Self::Output {
        point.rotate_around_zero(self.rotation()) * self.scale() + self.position()
    }
}

impl<N> From<Point<N>> for Transform<N>
where
    N: Num,
{
    fn from(p: Point<N>) -> Self {
        Self::new().set_position(p)
    }
}

impl<N> From<Size<N>> for Transform<N>
where
    N: Num,
{
    fn from(s: Size<N>) -> Self {
        Self::new().set_scale(s)
    }
}