diff options
Diffstat (limited to 'src/geometry/vec.rs')
-rw-r--r-- | src/geometry/vec.rs | 182 |
1 files changed, 42 insertions, 140 deletions
diff --git a/src/geometry/vec.rs b/src/geometry/vec.rs index c99cf5e..375a0f9 100644 --- a/src/geometry/vec.rs +++ b/src/geometry/vec.rs @@ -1,160 +1,62 @@ use std::ops::*; -use num_traits::{NumOps, NumAssignOps, Signed}; -use num_traits::pow::Pow; -use num_traits::real::Real; -macro_rules! fold_array { - ($method:ident, { $x:expr }) => { $x }; - ($method:ident, { $x:expr, $y:expr }) => { $x.$method($y) }; - ($method:ident, { $x:expr, $y:expr, $z:expr }) => { $x.$method($y).$method($z) }; +#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)] +pub struct Vec2d { + pub x: i8, + pub y: i8, } -macro_rules! impl_vector { - ($VecN:ident { $($field:ident),+ }) => { - #[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)] - pub struct $VecN<T> { - $(pub $field: T),+ - } - - impl<T> $VecN<T> { - pub const fn new($($field: T),+) -> $VecN<T> { - $VecN { $($field),+ } - } - } - - impl<T: NumOps + Ord + Signed + Copy> $VecN<T> { - pub fn walking_distance(&self) -> T { - fold_array!(max, { $(self.$field.abs()),+ }) - } - } - - impl<T: NumOps + Pow<u8, Output=T> + Copy> $VecN<T> { - pub fn magnitude_squared(&self) -> T { - fold_array!(add, { $(self.$field.pow(2)),+ }) - } - } - - impl<T: Real + Pow<u8, Output=T>> $VecN<T> { - pub fn magnitude(&self) -> T { - self.magnitude_squared().sqrt() - } - - pub fn unit(&self) -> $VecN<T> { - let mag = self.magnitude(); - $VecN { - $($field: self.$field / mag),+ - } - } - } - - impl<T: NumOps + Copy> $VecN<T> { - pub fn dot(&self, other: $VecN<T>) -> T { - fold_array!(add, { $(self.$field * other.$field),+ }) - } - } - - impl<T: NumOps> Add for $VecN<T> { - type Output = Self; - - fn add(self, other: Self) -> Self { - $VecN { - $($field: self.$field + other.$field),+ - } - } - } - - impl<T: NumAssignOps> AddAssign for $VecN<T> { - fn add_assign(&mut self, other: Self) { - $(self.$field += other.$field);+ - } - } - - impl<T: NumOps> Sub for $VecN<T> { - type Output = Self; - - fn sub(self, other: Self) -> Self { - $VecN { - $($field: self.$field - other.$field),+ - } - } - } - - impl<T: NumOps + Copy> Mul<T> for $VecN<T> { - type Output = Self; - - fn mul(self, rhs: T) -> Self { - $VecN { - $($field: self.$field * rhs),+ - } - } - } - - impl<T: Neg<Output=T>> Neg for $VecN<T> { - type Output = Self; - - fn neg(self) -> Self { - $VecN { - $($field: -self.$field),+ - } - } - } - +impl Vec2d { + pub const fn new(x: i8, y: i8) -> Vec2d { + Vec2d { x, y } + } + pub fn magnitude_squared(&self) -> i8 { + self.x + .saturating_pow(2) + .saturating_add(self.y.saturating_pow(2)) } } -impl_vector!(Vec2d { x, y }); -impl_vector!(Vec3d { x, y, z }); +impl Add for Vec2d { + type Output = Self; -impl<T: Real + Pow<u8, Output=T>> Vec2d<T> { - pub fn angle(&self) -> T { - self.y.atan2(self.x) + fn add(self, other: Self) -> Self { + Vec2d { + x: self.x.saturating_add(other.x), + y: self.y.saturating_add(other.y), + } } } +impl Sub for Vec2d { + type Output = Self; -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn right_angles_in_2d_vectors() { - use std::f32::consts::{FRAC_PI_2, PI}; - - assert_eq!(0., Vec2d::new(1., 0.).angle()); - assert_eq!(FRAC_PI_2, Vec2d::new(0., 1.).angle()); - assert_eq!(PI, Vec2d::new(-1., 0.).angle()); - assert_eq!(-FRAC_PI_2, Vec2d::new(0., -1.).angle()); + fn sub(self, other: Self) -> Self { + Vec2d { + x: self.x.saturating_sub(other.x), + y: self.y.saturating_sub(other.y), + } } +} - #[test] - fn unit_normalizes_2d_vector() { - let before = Vec2d::new(2., 10.); - let after = before.unit(); +impl Mul<i8> for Vec2d { + type Output = Self; - assert_eq!(1., after.magnitude()); - assert_eq!(before.angle(), after.angle()); + fn mul(self, other: i8) -> Self { + Vec2d { + x: self.x.saturating_mul(other), + y: self.y.saturating_mul(other), + } } +} - #[test] - fn unit_normalizes_3d_vector() { - let before = Vec3d::new(2., 10., -5.); - let after = before.unit(); - - assert_eq!(1., after.magnitude()); - // How to define 3d angle? 2 angles I suppose? - // assert_eq!(before.angle(), after.angle()); - } - - #[test] - fn dot_product_example_2d() { - let a = Vec2d::new(-6., 8.); - let b = Vec2d::new(5., 12.); - assert_eq!(66., a.dot(b)); - } +impl Neg for Vec2d { + type Output = Self; - #[test] - fn magnitude_squared_of_an_integer() { - let a = Vec2d::new(3, 4); - assert_eq!(25, a.magnitude_squared()); + fn neg(self) -> Self { + Vec2d { + x: -self.x, + y: -self.y, + } } } |