summaryrefslogtreecommitdiff
path: root/src/geometry/point.rs
diff options
context:
space:
mode:
authorJustin Worthe <justin@worthe-it.co.za>2019-04-22 14:38:40 +0200
committerJustin Worthe <justin@worthe-it.co.za>2019-04-22 14:38:40 +0200
commit3e54b01003aa9d27de8f4ca13c9240fe785ec0e1 (patch)
tree0dfe803ba790951e29cba25f791e31418eff5b05 /src/geometry/point.rs
parent29a323e0a3bd3ab3e6109b23e15bb5f9e88398e3 (diff)
Structures representing game state
Diffstat (limited to 'src/geometry/point.rs')
-rw-r--r--src/geometry/point.rs84
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.);
+ }
+}