WIP: Wall intersection
[kaka/rust-sdl-test.git] / src / common / geometry.rs
index 5a03ffb..455e600 100644 (file)
@@ -1,5 +1,7 @@
 use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign, Neg};
 
+////////// POINT ///////////////////////////////////////////////////////////////
+
 #[macro_export]
 macro_rules! point {
     ( $x:expr, $y:expr ) => {
@@ -181,6 +183,36 @@ impl Radians {
     }
 }
 
+////////// INTERSECTION ////////////////////////////////////////////////////////
+
+#[derive(Debug)]
+pub enum Intersection {
+    Point(Point<f64>),
+    //Line(Point<f64>, Point<f64>), // TODO: overlapping collinear
+    None,
+}
+
+impl Intersection {
+    pub fn lines(p1: Point<f64>, p2: Point<f64>, p3: Point<f64>, p4: Point<f64>) -> Intersection {
+       let s1 = p2 - p1;
+       let s2 = p4 - p3;
+
+       let denomimator = -s2.x * s1.y + s1.x * s2.y;
+       if denomimator != 0.0 {
+           let s = (-s1.y * (p1.x - p3.x) + s1.x * (p1.y - p3.y)) / denomimator;
+           let t = ( s2.x * (p1.y - p3.y) - s2.y * (p1.x - p3.x)) / denomimator;
+
+           if s >= 0.0 && s <= 1.0 && t >= 0.0 && t <= 1.0 {
+               return Intersection::Point(p1 + (s1 * t))
+           }
+       }
+
+       Intersection::None
+    }
+}
+
+////////// DIMENSION ///////////////////////////////////////////////////////////
+
 #[macro_export]
 macro_rules! dimen {
     ( $w:expr, $h:expr ) => {
@@ -210,16 +242,7 @@ impl<T> From<(T, T)> for Dimension<T> {
     }
 }
 
-#[macro_export]
-macro_rules! hashmap {
-    ($($k:expr => $v:expr),*) => {
-       {
-           let mut map = std::collections::HashMap::new();
-           $(map.insert($k, $v);)*
-           map
-       }
-    }
-}
+////////// TESTS ///////////////////////////////////////////////////////////////
 
 #[cfg(test)]
 mod tests {
@@ -296,4 +319,18 @@ mod tests {
         assert_eq!(r.area(), 30 * 20);
         // let a = Dimension::from(("a".to_string(), "b".to_string())).area(); // this doesn't work, because area() is not implemented for String
     }
+
+    #[test]
+    fn intersection_of_lines() {
+        let p1 = point!(0.0, 0.0);
+        let p2 = point!(2.0, 2.0);
+        let p3 = point!(0.0, 2.0);
+        let p4 = point!(2.0, 0.0);
+       let r = Intersection::lines(p1, p2, p3, p4);
+       if let Intersection::Point(p) = r {
+            assert_eq!(p, point!(1.0, 1.0));
+       } else {
+           panic!();
+       }
+    }
 }