gee 0.3.0

A convenience-first geometry library tailor-made for 2D games! 📐
Documentation
use crate::{Angle, Cardinal, Direction, Point, Size, Transform};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::ops::{
    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
};

#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(C)]
pub struct Vector<T = f32> {
    pub dx: T,
    pub dy: T,
}

impl<T: en::Num> Vector<T> {
    pub fn new(dx: T, dy: T) -> Self {
        Self { dx, dy }
    }

    pub fn uniform(d: T) -> Self {
        Self::new(d, d)
    }

    pub fn from_dx(dx: T) -> Self {
        Self { dx, dy: T::zero() }
    }

    pub fn from_dy(dy: T) -> Self {
        Self { dx: T::zero(), dy }
    }

    pub fn zero() -> Self {
        Self::uniform(T::zero())
    }

    pub fn one() -> Self {
        Self::uniform(T::one())
    }

    pub fn from_array([dx, dy]: [T; 2]) -> Self {
        Self::new(dx, dy)
    }

    pub fn from_tuple((dx, dy): (T, T)) -> Self {
        Self::new(dx, dy)
    }

    pub fn with_dx(self, dx: T) -> Self {
        Self::new(dx, self.dy)
    }

    pub fn with_dy(self, dy: T) -> Self {
        Self::new(self.dx, dy)
    }

    pub fn dot_product(self, rhs: Self) -> T {
        self.dx * rhs.dx + self.dy * rhs.dy
    }

    pub fn magnitude_squared(self) -> T {
        self.dot_product(self)
    }

    pub fn magnitude(self) -> T
    where
        T: en::Float,
    {
        self.magnitude_squared().sqrt()
    }

    pub fn normalize(self) -> Self
    where
        T: en::Float,
    {
        self / self.magnitude()
    }

    pub fn angle(self) -> Angle<T>
    where
        T: en::Float,
    {
        Angle::from_xy(self.dx, self.dy)
    }

    pub fn scaled(self, rhs: Size<T>) -> Self {
        Self::new(self.dx * rhs.width(), self.dy * rhs.height())
    }

    pub fn perpendicular(self) -> Self
    where
        T: Neg<Output = T>,
    {
        Self::new(-self.dy, self.dx)
    }

    pub fn yx(self) -> Self {
        Self::new(self.dy, self.dx)
    }

    pub fn transform(&self, transform: Transform<T>) -> Self {
        Self::new(
            self.dx * transform.m11 + self.dy * transform.m21 + transform.m31,
            self.dx * transform.m12 + self.dy * transform.m22 + transform.m32,
        )
    }

    pub fn map<U: en::Num>(&self, mut f: impl FnMut(T) -> U) -> Vector<U> {
        Vector::new(f(self.dx), f(self.dy))
    }

    pub fn map_dx(&self, mut f: impl FnMut(T) -> T) -> Self {
        self.with_dx(f(self.dx))
    }

    pub fn map_dy(&self, mut f: impl FnMut(T) -> T) -> Self {
        self.with_dy(f(self.dy))
    }

    impl_casts_and_cast!(Vector);

    pub fn to_array(self) -> [T; 2] {
        [self.dx, self.dy]
    }

    pub fn to_tuple(self) -> (T, T) {
        (self.dx, self.dy)
    }

    pub fn to_point(self) -> Point<T> {
        Point::zero() + self
    }

    pub fn to_size(self) -> Size<T> {
        self.into()
    }
}

impl<T: en::Num> From<Size<T>> for Vector<T> {
    fn from(size: Size<T>) -> Self {
        Self::new(size.width(), size.height())
    }
}

impl<T: en::Num> Add for Vector<T> {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output {
        Self::new(self.dx + rhs.dx, self.dy + rhs.dy)
    }
}

impl<T: en::Num> AddAssign for Vector<T> {
    fn add_assign(&mut self, rhs: Self) {
        *self = *self + rhs
    }
}

impl<T: en::Num> Sub for Vector<T> {
    type Output = Self;
    fn sub(self, rhs: Self) -> Self::Output {
        Self::new(self.dx - rhs.dx, self.dy - rhs.dy)
    }
}

impl<T: en::Num> SubAssign for Vector<T> {
    fn sub_assign(&mut self, rhs: Self) {
        *self = *self - rhs
    }
}

impl<T: en::Num> Mul for Vector<T> {
    type Output = Self;

    fn mul(self, rhs: Self) -> Self::Output {
        Self::new(self.dx * rhs.dx, self.dy * rhs.dy)
    }
}

impl<T: en::Num> MulAssign for Vector<T> {
    fn mul_assign(&mut self, rhs: Self) {
        *self = *self * rhs
    }
}

impl<T: en::Num> Mul<T> for Vector<T> {
    type Output = Self;
    fn mul(self, rhs: T) -> Self::Output {
        self.map(move |x| x * rhs)
    }
}

impl<T: en::Num> MulAssign<T> for Vector<T> {
    fn mul_assign(&mut self, rhs: T) {
        *self = *self * rhs
    }
}

impl<T: en::Num> Div for Vector<T> {
    type Output = Self;

    fn div(self, rhs: Self) -> Self::Output {
        Self::new(self.dx / rhs.dx, self.dy / rhs.dy)
    }
}

impl<T: en::Num> DivAssign for Vector<T> {
    fn div_assign(&mut self, rhs: Self) {
        *self = *self / rhs
    }
}

impl<T: en::Num> Div<T> for Vector<T> {
    type Output = Self;
    fn div(self, rhs: T) -> Self::Output {
        self.map(move |x| x / rhs)
    }
}

impl<T: en::Num> DivAssign<T> for Vector<T> {
    fn div_assign(&mut self, rhs: T) {
        *self = *self / rhs
    }
}

impl<T: en::Num> Rem for Vector<T> {
    type Output = Self;

    fn rem(self, rhs: Self) -> Self::Output {
        Self::new(self.dx % rhs.dx, self.dy % rhs.dy)
    }
}

impl<T: en::Num> RemAssign for Vector<T> {
    fn rem_assign(&mut self, rhs: Self) {
        *self = *self % rhs
    }
}

impl<T: en::Num> Rem<T> for Vector<T> {
    type Output = Self;
    fn rem(self, rhs: T) -> Self::Output {
        self.map(move |x| x % rhs)
    }
}

impl<T: en::Num> RemAssign<T> for Vector<T> {
    fn rem_assign(&mut self, rhs: T) {
        *self = *self % rhs
    }
}

impl<T: Neg<Output = T> + en::Num> Neg for Vector<T> {
    type Output = Self;
    fn neg(self) -> Self::Output {
        self.map(move |x| -x)
    }
}

impl<T: en::Float> From<Direction> for Vector<T> {
    fn from(direction: Direction) -> Self {
        direction.angle().unit_vector()
    }
}

impl<T: en::Float> From<Cardinal> for Vector<T> {
    fn from(cardinal: Cardinal) -> Self {
        cardinal.angle().unit_vector()
    }
}

#[cfg(feature = "euclid")]
impl<T, U> From<Vector<T>> for euclid::Vector2D<T, U> {
    fn from(v: Vector<T>) -> euclid::Vector2D<T, U> {
        Self::new(v.dx, v.dy)
    }
}

#[cfg(feature = "euclid")]
impl<T, U> From<euclid::Vector2D<T, U>> for Vector<T> {
    fn from(v: euclid::Vector2D<T, U>) -> Vector<T> {
        Self { dx: v.x, dy: v.y }
    }
}