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 |