ga2 0.3.0

Common types for 2D geometric algebra
Documentation
use crate::*;

use derive_more::{Add, AddAssign, Neg, Sub, SubAssign};
use num_traits::{real::Real, Inv, One, Zero};
use std::ops::{Div, DivAssign, Mul, MulAssign};
use vector_space::{DotProduct, InnerSpace, VectorSpace};

/// The 2D bivector type.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Add, AddAssign, Sub, SubAssign, Neg)]
pub struct Rotor<T> {
    /// The scalar component.
    pub scalar: T,
    /// The component representing the xy plane.
    pub xy: T,
}

impl<T> Rotor<T> {
    /// Creates a new rotor from its components.
    pub fn new(scalar: T, xy: T) -> Self {
        Self { scalar, xy }
    }
}

impl<T: Real> Rotor<T> {
    /// Rotates a vector by the rotor.
    pub fn rotate(self, vector: Vector<T>) -> Vector<T> {
        self.normalize().rotate_normalized(vector)
    }

    /// Rotates a vector by the rotor.
    /// The rotor has to be normalized already.
    pub fn rotate_normalized(self, vector: Vector<T>) -> Vector<T> {
        let Self { scalar, xy } = self * self;

        Vector {
            x: scalar * vector.x + xy * vector.y,
            y: scalar * vector.y - xy * vector.x,
        }
    }

    /// The reverse of the rotor.
    pub fn reverse(self) -> Self {
        Self {
            scalar: self.scalar,
            xy: -self.xy,
        }
    }
}

impl<T: Zero> Rotor<T> {
    /// Creates a new scalar rotor.
    pub fn scalar(scalar: T) -> Self {
        Self {
            scalar,
            xy: T::zero(),
        }
    }

    /// Creates a new rotor along the xy plane.
    pub fn xy(xy: T) -> Self {
        Self {
            scalar: T::zero(),
            xy,
        }
    }
}

impl<T: Zero> Zero for Rotor<T> {
    fn zero() -> Self {
        Self {
            scalar: T::zero(),
            xy: T::zero(),
        }
    }

    fn is_zero(&self) -> bool {
        self.scalar.is_zero() && self.xy.is_zero()
    }
}

impl<T: Real> One for Rotor<T> {
    fn one() -> Self {
        Self {
            scalar: T::one(),
            xy: T::zero(),
        }
    }

    fn is_one(&self) -> bool {
        self.scalar.is_one() && self.xy.is_zero()
    }
}

impl<T: Real> Inv for Rotor<T> {
    type Output = Self;

    fn inv(self) -> Self {
        let rev = self.reverse();
        rev / self.dot(rev)
    }
}

impl<T: Real> From<T> for Rotor<T> {
    fn from(scalar: T) -> Self {
        Self::scalar(scalar)
    }
}

impl<T> Mul<T> for Rotor<T>
where
    T: Mul<Output = T> + Copy,
{
    type Output = Self;
    fn mul(self, other: T) -> Self {
        Self {
            scalar: self.scalar * other,
            xy: self.xy * other,
        }
    }
}

impl<T> MulAssign<T> for Rotor<T>
where
    T: MulAssign + Copy,
{
    fn mul_assign(&mut self, other: T) {
        self.scalar *= other;
        self.xy *= other;
    }
}

impl<T> Div<T> for Rotor<T>
where
    T: Div<Output = T> + Copy,
{
    type Output = Self;
    fn div(self, other: T) -> Self {
        Self {
            scalar: self.scalar / other,
            xy: self.xy / other,
        }
    }
}

impl<T> DivAssign<T> for Rotor<T>
where
    T: DivAssign + Copy,
{
    fn div_assign(&mut self, other: T) {
        self.scalar /= other;
        self.xy /= other;
    }
}

impl<T: Real> VectorSpace for Rotor<T> {
    type Scalar = T;
}

impl<T: Real> DotProduct for Rotor<T> {
    type Output = Self::Scalar;
    fn dot(self, other: Self) -> T {
        self.scalar * other.scalar - self.xy * other.xy
    }
}

impl<T: Real> DotProduct<Vector<T>> for Rotor<T> {
    type Output = Vector<T>;
    #[inline]
    fn dot(self, other: Vector<T>) -> Vector<T> {
        other.dot(self)
    }
}

impl<T: Real> DotProduct<Bivector<T>> for Rotor<T> {
    type Output = Self;
    #[inline]
    fn dot(self, other: Bivector<T>) -> Self {
        other.dot(self)
    }
}

impl<T: Real> InnerSpace for Rotor<T> {
    fn scalar(self, other: Self) -> T {
        self.dot(other)
    }

    fn magnitude2(self) -> T {
        self.dot(self.reverse())
    }
}

impl<T: Real> Mul for Rotor<T> {
    type Output = Self;
    fn mul(self, other: Self) -> Self {
        Self {
            scalar: self.dot(other),
            xy: self.scalar * other.xy + other.scalar * self.xy,
        }
    }
}

impl<T: Real> MulAssign for Rotor<T> {
    fn mul_assign(&mut self, other: Self) {
        *self = *self * other;
    }
}

impl<T: Real> Div for Rotor<T> {
    type Output = Self;
    fn div(self, other: Self) -> Self {
        self * other.inv()
    }
}

impl<T: Real> DivAssign for Rotor<T> {
    fn div_assign(&mut self, other: Self) {
        *self = *self / other;
    }
}