diff options
Diffstat (limited to 'src/geometry/point.rs')
-rw-r--r-- | src/geometry/point.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/geometry/point.rs b/src/geometry/point.rs new file mode 100644 index 0000000..c34d00f --- /dev/null +++ b/src/geometry/point.rs @@ -0,0 +1,84 @@ +use crate::geometry::vec::*; + +use std::ops::*; +use num_traits::{NumOps, NumAssignOps}; +use num_traits::pow::Pow; +use num_traits::real::Real; + +macro_rules! impl_point { + ($PointN:ident { $($field:ident),+ }, $VecN:ident) => { + #[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)] + pub struct $PointN<T> { + $(pub $field: T),+ + } + + impl<T> $PointN<T> { + pub fn new($($field: T),+) -> $PointN<T> { + $PointN { $($field),+ } + } + } + + impl<T: NumOps + Pow<u8, Output=T> + Copy> $PointN<T> { + pub fn distance_squared(self, other: $PointN<T>) -> T { + (self - other).magnitude_squared() + } + } + + + impl<T: Real + Pow<u8, Output=T>> $PointN<T> { + pub fn distance(self, other: $PointN<T>) -> T { + (self - other).magnitude() + } + } + + impl<T: NumOps> Add<$VecN<T>> for $PointN<T> { + type Output = Self; + + fn add(self, other: $VecN<T>) -> Self { + $PointN { + $($field: self.$field + other.$field),+ + } + } + } + + impl<T: NumAssignOps> AddAssign<$VecN<T>> for $PointN<T> { + fn add_assign(&mut self, other: $VecN<T>) { + $(self.$field += other.$field);+ + } + } + + impl<T: NumOps> Sub for $PointN<T> { + type Output = $VecN<T>; + + fn sub(self, other: Self) -> $VecN<T> { + $VecN { + $($field: self.$field - other.$field),+ + } + } + } + } +} + +impl_point!(Point2d { x, y }, Vec2d); +impl_point!(Point3d { x, y, z }, Vec3d); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn distance_in_x_dimension_example() { + let a = Point2d::new(1., 1.); + let b = Point2d::new(3., 1.); + assert_eq!(a.distance(b), 2.); + assert_eq!(a.distance_squared(b), 4.); + } + + #[test] + fn distance_in_y_dimension_example() { + let a = Point2d::new(1., 1.); + let b = Point2d::new(1., 3.); + assert_eq!(b.distance(a), 2.); + assert_eq!(b.distance_squared(a), 4.); + } +} |