| 12 #[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize_repr, Deserialize_repr)] |
12 #[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize_repr, Deserialize_repr)] |
| 13 #[repr(u8)] |
13 #[repr(u8)] |
| 14 pub enum Face {F1 = 1, F2 = 2, F3 = 3, F4 = 4, F5 = 5, F6 = 6} |
14 pub enum Face {F1 = 1, F2 = 2, F3 = 3, F4 = 4, F5 = 5, F6 = 6} |
| 15 use Face::*; |
15 use Face::*; |
| 16 |
16 |
| |
17 /// General point in 2D |
| 17 pub type Point = Loc<f64, 2>; |
18 pub type Point = Loc<f64, 2>; |
| 18 |
19 |
| |
20 /// Types for faces adjacent to a given face. |
| 19 pub type AdjacentFaces = [Face; 4]; |
21 pub type AdjacentFaces = [Face; 4]; |
| 20 |
22 |
| |
23 /// Types of paths on a cube |
| 21 #[derive(Clone, Debug, Serialize)] |
24 #[derive(Clone, Debug, Serialize)] |
| 22 pub enum Path { |
25 pub enum Path { |
| |
26 /// Direct path from an unindicated source face to a `destination` face. |
| 23 Direct { destination : Face }, |
27 Direct { destination : Face }, |
| |
28 /// Indirect path from an unindicated source face to a `destination` face, |
| |
29 /// via an `intermediate` face. |
| 24 Indirect { destination : Face, intermediate : Face }, |
30 Indirect { destination : Face, intermediate : Face }, |
| 25 } |
31 } |
| 26 |
32 |
| 27 /// An iterator over paths on a cube, from a source face to a destination face. |
33 /// An iterator over paths on a cube, from a source face to a destination face. |
| 28 #[derive(Clone, Debug)] |
34 #[derive(Clone, Debug)] |
| 29 pub enum PathIter { |
35 pub enum PathIter { |
| |
36 /// Direct path to a destination. |
| 30 Same { |
37 Same { |
| |
38 /// Deistination face |
| 31 destination : Face, |
39 destination : Face, |
| |
40 /// Indicator whether the only possible [`Path::Direct`] has already been returned. |
| 32 exhausted : bool |
41 exhausted : bool |
| 33 }, |
42 }, |
| |
43 /// Path via several possible intermedite faces. |
| |
44 /// This is used to generate several [`Path::Indirect`]. |
| 34 Indirect { |
45 Indirect { |
| |
46 /// Destination face |
| 35 destination : Face, |
47 destination : Face, |
| |
48 /// Possible intermediate faces |
| 36 intermediate : AdjacentFaces, |
49 intermediate : AdjacentFaces, |
| |
50 /// Intermediate face index counter. |
| 37 current : usize |
51 current : usize |
| 38 } |
52 } |
| 39 } |
53 } |
| 40 |
54 |
| 41 impl std::iter::Iterator for PathIter { |
55 impl std::iter::Iterator for PathIter { |
| 195 } |
209 } |
| 196 } |
210 } |
| 197 } |
211 } |
| 198 |
212 |
| 199 /// Indicates whether an unfolded point `p` is on this face, i.e., |
213 /// Indicates whether an unfolded point `p` is on this face, i.e., |
| 200 /// has coordinates in [0,1]². |
214 /// has coordinates in $\[0,1\]^2$. |
| 201 pub fn is_in_face(&self, p: &Point) -> bool { |
215 pub fn is_in_face(&self, p: &Point) -> bool { |
| 202 p.iter().all(|t| 0.0 <= *t && *t <= 1.0) |
216 p.iter().all(|t| 0.0 <= *t && *t <= 1.0) |
| 203 } |
217 } |
| 204 |
218 |
| 205 /// Given an unfolded point `p` and a destination point `d` in unfolded coordinates, |
219 /// Given an unfolded point `p` and a destination point `d` in unfolded coordinates, |
| 365 } |
381 } |
| 366 } |
382 } |
| 367 } |
383 } |
| 368 } |
384 } |
| 369 |
385 |
| |
386 /// Tests that the distances between points on the boundaries of distinct faces are |
| |
387 /// correctly calculated. |
| 370 #[test] |
388 #[test] |
| 371 fn boundary_distance() { |
389 fn boundary_distance() { |
| 372 let left = Loc([0.0, 0.5]); |
390 let left = Loc([0.0, 0.5]); |
| 373 let right = Loc([1.0, 0.5]); |
391 let right = Loc([1.0, 0.5]); |
| 374 let down = Loc([0.5, 0.0]); |
392 let down = Loc([0.5, 0.0]); |
| 438 // } |
457 // } |
| 439 // } |
458 // } |
| 440 // } |
459 // } |
| 441 // } |
460 // } |
| 442 |
461 |
| |
462 /// Tests that the logarithmic map is working correctly between adjacent faces. |
| 443 #[test] |
463 #[test] |
| 444 fn log_adjacent() { |
464 fn log_adjacent() { |
| 445 let p1 = OnCube{ face : F1, point : Loc([0.5, 0.5])}; |
465 let p1 = OnCube{ face : F1, point : Loc([0.5, 0.5])}; |
| 446 let p2 = OnCube{ face : F2, point : Loc([0.5, 0.5])}; |
466 let p2 = OnCube{ face : F2, point : Loc([0.5, 0.5])}; |
| 447 |
467 |
| 448 assert_eq!(p1.log(&p2).norm(L2), 1.0); |
468 assert_eq!(p1.log(&p2).norm(L2), 1.0); |
| 449 } |
469 } |
| 450 |
470 |
| |
471 /// Tests that the logarithmic map is working correctly between opposing faces. |
| 451 #[test] |
472 #[test] |
| 452 fn log_opposing_equal() { |
473 fn log_opposing_equal() { |
| 453 let p1 = OnCube{ face : F1, point : Loc([0.5, 0.5])}; |
474 let p1 = OnCube{ face : F1, point : Loc([0.5, 0.5])}; |
| 454 let p2 = OnCube{ face : F6, point : Loc([0.5, 0.5])}; |
475 let p2 = OnCube{ face : F6, point : Loc([0.5, 0.5])}; |
| 455 |
476 |
| 456 assert_eq!(p1.log(&p2).norm(L2), 2.0); |
477 assert_eq!(p1.log(&p2).norm(L2), 2.0); |
| 457 } |
478 } |
| 458 |
479 |
| |
480 /// Tests that the logarithmic map is working correctly between opposing faces when there |
| |
481 /// is a unique shortest geodesic. |
| 459 #[test] |
482 #[test] |
| 460 fn log_opposing_unique_shortest() { |
483 fn log_opposing_unique_shortest() { |
| 461 let p1 = OnCube{ face : F1, point : Loc([0.3, 0.25])}; |
484 let p1 = OnCube{ face : F1, point : Loc([0.3, 0.25])}; |
| 462 let p2 = OnCube{ face : F6, point : Loc([0.3, 0.25])}; |
485 let p2 = OnCube{ face : F6, point : Loc([0.3, 0.25])}; |
| 463 |
486 |