src/cube.rs

changeset 0
989e2fe08db2
child 3
ff4656da04af
equal deleted inserted replaced
-1:000000000000 0:989e2fe08db2
1
2 use core::f64;
3
4 use alg_tools::loc::Loc;
5 use alg_tools::norms::{Norm, L2};
6 use crate::manifold::ManifoldPoint;
7
8 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
9 pub enum Face {F1, F2, F3, F4, F5, F6}
10 use Face::*;
11
12 pub type Point = Loc<f64, 2>;
13
14 pub type AdjacentFaces = [Face; 4];
15
16 pub enum Path {
17 Direct { destination : Face },
18 Indirect { destination : Face, intermediate : Face },
19 }
20
21 /// An iterator over paths on a cube, from a source face to a destination face.
22 #[derive(Clone, Debug)]
23 pub enum PathIter {
24 Direct(Face),
25 Indirect{ destination : Face, intermediate : AdjacentFaces, current : usize},
26 Exhausted,
27 }
28
29 impl std::iter::Iterator for PathIter {
30 type Item = Path;
31
32 fn next(&mut self) -> Option<Self::Item> {
33 use PathIter::*;
34 match self {
35 &mut Exhausted => None,
36 &mut Direct(destination) => {
37 *self = Exhausted;
38 Some(Path::Direct { destination })
39 },
40 &mut Indirect{destination, intermediate : ref i, ref mut current} => {
41 if *current < i.len() {
42 let intermediate = i[*current];
43 *current += 1;
44 Some(Path::Indirect{ destination, intermediate })
45 } else {
46 *self = Exhausted;
47 None
48 }
49 }
50 }
51 }
52 }
53
54
55 impl Face {
56 /// Returns an array of the four faces adjacent to `self`.
57 pub fn adjacent_faces(&self) -> AdjacentFaces {
58 match *self {
59 F1 => [F2, F3, F4, F5],
60 F2 => [F1, F4, F5, F6],
61 F3 => [F1, F4, F5, F6],
62 F4 => [F1, F2, F3, F6],
63 F5 => [F1, F2, F3, F6],
64 F6 => [F2, F3, F4, F5],
65 }
66 }
67
68 /// Returns the face opposing `self`.
69 pub fn opposing_face(&self) -> Face {
70 match *self {
71 F1 => F6,
72 F2 => F3,
73 F3 => F2,
74 F4 => F6,
75 F5 => F4,
76 F6 => F1,
77 }
78 }
79
80 /// Converts a point on an adjacent face to the coordinate system of `self`.
81 pub fn convert_adjacent(&self, adjacent : Face, p: &Point) -> Option<Point> {
82 let Loc([x, y]) = *p;
83 let mk = |x, y| Some(Loc([x, y]));
84 match adjacent {
85 F1 => match *self {
86 F2 => mk(y, x - 1.0),
87 F3 => mk(1.0 - y, -x),
88 F4 => mk(x, -y),
89 F5 => mk(1.0 - x, y - 1.0),
90 F1 => mk(x, y),
91 F6 => None,
92 },
93 F2 => match *self {
94 F1 => mk(y + 1.0, x),
95 F4 => mk(x + 1.0, y),
96 F5 => mk(x - 1.0, y),
97 F6 => mk(2.0 - y, x),
98 F2 => mk(x, y),
99 F3 => None,
100 },
101 F3 => match *self {
102 F1 => mk(-y, 1.0 - x),
103 F4 => mk(x - 1.0, y),
104 F5 => mk(x + 1.0, y),
105 F6 => mk(y - 1.0, 1.0 - x),
106 F3 => mk(x, y),
107 F2 => None,
108 },
109 F4 => match *self {
110 F1 => mk(x, -y),
111 F2 => mk(x - 1.0, y),
112 F3 => mk(x + 1.0, y),
113 F6 => mk(x, y - 1.0),
114 F4 => mk(x, y),
115 F5 => None,
116 },
117 F5 => match *self {
118 F1 => mk(1.0 -x, y + 1.0),
119 F2 => mk(x + 1.0, y),
120 F3 => mk(x - 1.0, y),
121 F6 => mk(1.0 -x, 2.0 - y),
122 F5 => mk(x, y),
123 F4 => None,
124 },
125 F6 => match *self {
126 F2 => mk(y, 2.0 - x),
127 F3 => mk(1.0 - y, x + 1.0),
128 F4 => mk(x, y + 1.0),
129 F5 => mk(1.0 - x, 2.0 - y),
130 F6 => mk(x, y),
131 F1 => None,
132 }
133 }
134 }
135
136 /// Converts a point behind a path to the coordinate system of `self`.
137 pub fn convert(&self, path : &Path, p: &Point) -> Point {
138 use Path::*;
139 match path {
140 &Direct{ destination : d} => self.convert_adjacent(d, p),
141 &Indirect{ destination : d, intermediate : i }
142 => {dbg!((d,i)); dbg!(self.convert_adjacent(i, dbg!(&i.convert_adjacent(d, p).unwrap())))}
143 }.unwrap()
144 }
145
146
147 /// Returns an iterator over all the paths from `self` to `other`.
148 fn paths(&self, other : Face) -> PathIter {
149 if self.opposing_face() == other {
150 PathIter::Indirect {
151 intermediate : self.adjacent_faces(),
152 destination : other,
153 current : 0
154 }
155 } else {
156 PathIter::Direct(other)
157 }
158 }
159 }
160
161 #[derive(Clone, Debug, PartialEq)]
162 pub struct OnCube {
163 face : Face,
164 point : Point,
165 }
166
167 impl ManifoldPoint for OnCube {
168 type Tangent = Point;
169
170 fn exp(&self, tangent : &Self::Tangent) -> Self {
171 unimplemented!();
172 }
173
174 fn log(&self, other : &Self) -> Self::Tangent {
175 let mut best_len = f64::INFINITY;
176 let mut best_tan = Loc([0.0, 0.0]);
177 for path in self.face.paths(other.face) {
178 let tan = self.face.convert(&path, &other.point) - &self.point;
179 let len = tan.norm(L2);
180 if len < best_len {
181 best_tan = tan;
182 best_len = len;
183 }
184 }
185 best_tan
186 }
187 }
188
189 #[cfg(test)]
190 mod tests {
191 use super::*;
192
193 #[test]
194 fn log_test_adjacent() {
195 let p1 = OnCube{ face : F1, point : Loc([0.5, 0.5])};
196 let p2 = OnCube{ face : F2, point : Loc([0.5, 0.5])};
197
198 assert_eq!(p1.log(&p2).norm(L2), 1.0);
199 }
200
201 #[test]
202 fn log_test_opposing_equal() {
203 let p1 = OnCube{ face : F1, point : Loc([0.5, 0.5])};
204 let p2 = OnCube{ face : F6, point : Loc([0.5, 0.5])};
205
206 assert_eq!(p1.log(&p2).norm(L2), 2.0);
207 }
208
209 #[test]
210 fn log_test_opposing_unique_shortest() {
211 let p1 = OnCube{ face : F1, point : Loc([0.3, 0.25])};
212 let p2 = OnCube{ face : F6, point : Loc([0.3, 0.25])};
213
214 assert_eq!(p1.log(&p2).norm(L2), 1.5);
215 }
216 }
217

mercurial