Simplify crossing calculations

Tue, 22 Oct 2024 09:41:47 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Tue, 22 Oct 2024 09:41:47 -0500
changeset 15
2f4af30af476
parent 14
d0f20c6cb49c
child 16
a6efe0fafd90

Simplify crossing calculations

src/cube.rs file | annotate | diff | comparison | revisions
--- a/src/cube.rs	Tue Oct 22 09:34:12 2024 -0500
+++ b/src/cube.rs	Tue Oct 22 09:41:47 2024 -0500
@@ -211,39 +211,31 @@
         let ty = yd - y;
 
         // Move towards tangent as (x + s tx, y + s ty) for the largest s<=1.0 for which
-        // both coordinates is within [0, 1].
-        let sx = match tx.partial_cmp(&0.0) {
-            Some(Less) =>  1.0f64.min(-x/tx),
-            Some(Greater) => 1.0f64.min((1.0-x)/tx),
-            _ => 1.0,
-        };
-        let sy = match ty.partial_cmp(&0.0) {
-            Some(Less) => 1.0f64.min(-y/ty),
-            Some(Greater) => 1.0f64.min((1.0-y)/ty),
-            _ => 1.0,
+        // both coordinates is within [0, 1]. Also gives the direction of move along
+        // each coordinate.
+        let (sx, dirx) = match tx.partial_cmp(&0.0) {
+            Some(Less) =>  (1.0f64.min(-x/tx), Less),
+            Some(Greater) => (1.0f64.min((1.0-x)/tx), Greater),
+            _ => (1.0, Equal)
         };
-        // We use the point where one coordinate comes within the range to decide on
-        // the edge.
-        let s = sx.max(sy);
-        // But move such that both coordinates are within the range.
-        let c = sx.min(sy);
-        let (cx, cy) = (x + c*tx, y + c*ty);
-
-        let crossing = |t| match (0.0 <= t, t <= 1.0) {
-            (false, _) => Less,
-            (_, false) => Greater,
-            _ => Equal,
+        let (sy, diry) = match ty.partial_cmp(&0.0) {
+            Some(Less) => (1.0f64.min(-y/ty), Less),
+            Some(Greater) => (1.0f64.min((1.0-y)/ty), Greater),
+            _ => (1.0, Equal),
         };
 
         // TODO: how to properly handle corners? Just throw an error?
-        let crossing = match (crossing(x + s*tx), crossing(y + s*ty)) {
-            (Equal, Equal) => *self,
-            (Less, _) => self.adjacent_faces()[0],
-            (Greater, _) => self.adjacent_faces()[1],
-            (Equal, Less) => self.adjacent_faces()[2],
-            (Equal, Greater) => self.adjacent_faces()[3],
+        let (crossing, c) = match (sx < sy, dirx, diry) {
+            // x move is less than y move, so crossing is either on left or right edge
+            (true, Less, _)      => (self.adjacent_faces()[0], sx),
+            (true, Greater, _)   => (self.adjacent_faces()[1], sx),
+            (true, Equal, _)     => (*self, sx),
+            // y move is less than x move, so crossing is either on bottom or top edge
+            (false, _, Less)     => (self.adjacent_faces()[2], sy),
+            (false, _, Greater)  => (self.adjacent_faces()[3], sy),
+            (false, _, Equal)    => (*self, sy),
         };
-        (crossing, Loc([cx, cy]))
+        (crossing, Loc([x + c*tx, y + c*ty]))
     }
 
     /// Get embedded 3D coordinates

mercurial