axgeom 1.13.2

Library that provides ability to extract 1d ranges out of 2d objects.
Documentation
use crate::Axis;
use core::convert::TryInto;
use core::ops::*;
use num_traits::float::FloatCore;
use num_traits::Zero;
#[cfg(feature="serde")]
use serde::{Deserialize, Serialize};

///Convenience function to create a vector.
#[inline(always)]
pub const fn vec2<N>(x: N, y: N) -> Vec2<N> {
    Vec2 { x, y }
}

///Convenience function to create a vector where both component are the same.
#[inline(always)]
pub fn vec2same<N: Copy>(a: N) -> Vec2<N> {
    Vec2 { x: a, y: a }
}

///A 2D vector.
#[derive(Default, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[must_use]
pub struct Vec2<N> {
    pub x: N,
    pub y: N,
}

impl<N> AsRef<[N; 2]> for Vec2<N> {
    #[inline(always)]
    fn as_ref(&self) -> &[N; 2] {
        unsafe { &*(self as *const _ as *const _) }
    }
}

impl<N> AsMut<[N; 2]> for Vec2<N> {
    #[inline(always)]
    fn as_mut(&mut self) -> &mut [N; 2] {
        unsafe { &mut *(self as *mut _ as *mut _) }
    }
}

#[inline(always)]
pub fn absdiff<T>(x: T, y: T) -> T
where
    T: Sub<Output = T> + PartialOrd,
{
    if x < y {
        y - x
    } else {
        x - y
    }
}

fn gen_abs<S: Neg<Output = S> + PartialOrd + Zero>(num: S) -> S {
    if num < S::zero() {
        -num
    } else {
        num
    }
}
impl<S: Copy + Neg<Output = S> + PartialOrd + Zero> Vec2<S> {
    #[inline(always)]
    pub fn abs(&self) -> Vec2<S> {
        vec2(gen_abs(self.x), gen_abs(self.y))
    }
    #[inline(always)]
    pub fn rotate_90deg_right(&self) -> Vec2<S> {
        vec2(-self.y, self.x)
    }
    #[inline(always)]
    pub fn rotate_90deg_left(&self) -> Vec2<S> {
        vec2(self.y, self.x)
    }

    #[inline(always)]
    pub fn split_into_components(&self) -> [Vec2<S>; 2] {
        [vec2(self.x, S::zero()), vec2(S::zero(), self.y)]
    }
}

impl<S: Add<Output = S> + Sub<Output = S> + PartialOrd + Copy> Vec2<S> {
    #[inline(always)]
    pub fn manhattan_dis(&self, other: Vec2<S>) -> S {
        absdiff(self.x, other.x) + absdiff(self.y, other.y)
    }
}

impl<
        T: Copy
            + PartialOrd
            + core::ops::Sub<Output = T>
            + core::ops::Mul<Output = T>
            + core::ops::Add<Output = T>,
    > Vec2<T>
{
    ///If the point is outside the rectangle, returns the squared distance from a point to a rectangle.
    ///If the point is inside the rectangle, it will return None.
    #[inline(always)]
    #[must_use]
    pub fn distance_squared_to_point(&self, point: Vec2<T>) -> T {
        (point.x - self.x) * (point.x - self.x) + (point.y - self.y) * (point.y - self.y)
    }
}

#[test]
fn test_rotate() {
    let b = vec2(1, 1).rotate_90deg_right();
    assert_eq!(b, vec2(-1, 1));

    let b = vec2(1, 0).rotate_90deg_right();
    assert_eq!(b, vec2(0, 1));
}

impl<S: Mul<Output = S> + Div<Output = S> + Add<Output = S> + Copy> Vec2<S> {
    #[inline(always)]
    pub fn scale(&self, other: Vec2<S>) -> Vec2<S> {
        vec2(self.x * other.x, self.y * other.y)
    }

    #[inline(always)]
    pub fn inv_scale(&self, other: Vec2<S>) -> Vec2<S> {
        vec2(self.x / other.x, self.y / other.y)
    }

    #[inline(always)]
    #[must_use]
    pub fn magnitude2(&self) -> S {
        self.x * self.x + self.y * self.y
    }
    #[inline(always)]
    #[must_use]
    pub fn dot(&self, other: Vec2<S>) -> S {
        self.x * other.x + self.y * other.y
    }
}
impl<S: FloatCore> Vec2<S> {
    #[inline(always)]
    pub fn is_nan(&self) -> bool {
        self.x.is_nan() || self.y.is_nan()
    }
}

#[cfg(feature = "std")]
impl<S: num_traits::Float> Vec2<S> {
    #[inline(always)]
    pub fn truncate_at(&self, mag: S) -> Vec2<S> {
        if self.magnitude() > mag {
            self.normalize_to(mag)
        } else {
            *self
        }
    }

    #[inline(always)]
    pub fn normalize_to(&self, mag: S) -> Vec2<S> {
        let l = self.magnitude2().sqrt();
        (*self) * (mag / l)
    }

    #[inline(always)]
    pub fn magnitude(&self) -> S {
        self.magnitude2().sqrt()
    }
}

///Cast an array of 2 elements of primitive type to another primitive type using "as" on each element.
#[must_use]
pub fn arr2_as<B: 'static + Copy, A: num_traits::AsPrimitive<B>>(a: [A; 2]) -> [B; 2] {
    let [a, b] = a;
    [a.as_(), b.as_()]
}

impl<T> Vec2<T> {
    #[inline(always)]
    pub fn inner_as<B: 'static + Copy>(self) -> Vec2<B>
    where
        T: num_traits::AsPrimitive<B>,
    {
        vec2(self.x.as_(), self.y.as_())
    }
}

impl<'a, B: Copy> From<&'a [B; 2]> for Vec2<B> {
    fn from(a: &'a [B; 2]) -> Self {
        let [a, b] = *a;
        vec2(a, b)
    }
}

impl<B> From<[B; 2]> for Vec2<B> {
    fn from(a: [B; 2]) -> Self {
        let [a, b] = a;
        vec2(a, b)
    }
}

impl<B> From<Vec2<B>> for [B; 2] {
    fn from(a: Vec2<B>) -> Self {
        [a.x, a.y]
    }
}

impl<'a, B> From<&'a Vec2<B>> for &'a [B; 2] {
    fn from(a: &'a Vec2<B>) -> Self {
        a.as_ref()
    }
}

impl<B> Vec2<B> {
    ///Get the range of one axis.
    #[inline(always)]
    #[must_use]
    pub fn get_axis(&self, axis: impl Axis) -> &B {
        if axis.is_xaxis() {
            &self.x
        } else {
            &self.y
        }
    }

    ///Get the mutable range of one axis.
    #[inline(always)]
    #[must_use]
    pub fn get_axis_mut(&mut self, axis: impl Axis) -> &mut B {
        if axis.is_xaxis() {
            &mut self.x
        } else {
            &mut self.y
        }
    }

    #[inline(always)]
    pub fn inner_into<A>(self) -> Vec2<A>
    where
        B: Into<A>,
    {
        let x = self.x.into();
        let y = self.y.into();
        vec2(x, y)
    }

    #[inline(always)]
    pub fn inner_try_into<A>(self) -> Result<Vec2<A>, B::Error>
    where
        B: TryInto<A>,
    {
        let x = self.x.try_into();
        let y = self.y.try_into();
        match (x, y) {
            (Ok(x), Ok(y)) => Ok(vec2(x, y)),
            (Ok(_), Err(e)) => Err(e),
            (Err(e), Ok(_)) => Err(e),
            (Err(e), Err(_)) => Err(e),
        }
    }
}

impl<S: Add<Output = S> + Copy> Add<Self> for Vec2<S> {
    type Output = Self;
    #[inline(always)]
    fn add(self, rhs: Self) -> Self {
        vec2(self.x + rhs.x, self.y + rhs.y)
    }
}

impl<S: Sub<Output = S> + Copy> Sub<Self> for Vec2<S> {
    type Output = Self;
    #[inline(always)]
    fn sub(self, rhs: Self) -> Self {
        vec2(self.x - rhs.x, self.y - rhs.y)
    }
}

impl<S: Mul<Output = S> + Copy> Mul<S> for Vec2<S> {
    type Output = Self;
    #[inline(always)]
    fn mul(self, rhs: S) -> Self {
        vec2(self.x * rhs, self.y * rhs)
    }
}

impl<S: Div<Output = S> + Copy> Div<S> for Vec2<S> {
    type Output = Self;
    #[inline(always)]
    fn div(self, rhs: S) -> Self {
        vec2(self.x / rhs, self.y / rhs)
    }
}

impl<S: DivAssign<S> + Copy> DivAssign<S> for Vec2<S> {
    #[inline(always)]
    fn div_assign(&mut self, scalar: S) {
        self.x /= scalar;
        self.y /= scalar;
    }
}
impl<S: MulAssign<S> + Copy> MulAssign<S> for Vec2<S> {
    #[inline(always)]
    fn mul_assign(&mut self, scalar: S) {
        self.x *= scalar;
        self.y *= scalar;
    }
}

impl<S: AddAssign<S> + Copy> AddAssign<Self> for Vec2<S> {
    #[inline(always)]
    fn add_assign(&mut self, rhs: Self) {
        self.x += rhs.x;
        self.y += rhs.y;
    }
}
impl<S: SubAssign<S> + Copy> SubAssign<Self> for Vec2<S> {
    #[inline(always)]
    fn sub_assign(&mut self, rhs: Self) {
        self.x -= rhs.x;
        self.y -= rhs.y;
    }
}

impl<S: Neg<Output = S>> Neg for Vec2<S> {
    type Output = Vec2<S>;

    #[inline]
    fn neg(self) -> Vec2<S> {
        vec2(-self.x, -self.y)
    }
}

impl<S: Zero + Eq + Copy> Zero for Vec2<S> {
    #[inline(always)]
    fn zero() -> Vec2<S> {
        vec2(S::zero(), S::zero())
    }

    #[inline(always)]
    #[must_use]
    fn is_zero(&self) -> bool {
        *self == Vec2::zero()
    }
}