| 24 Indirect { destination : Face, intermediate : Face }, |
24 Indirect { destination : Face, intermediate : Face }, |
| 25 } |
25 } |
| 26 |
26 |
| 27 /// An iterator over paths on a cube, from a source face to a destination face. |
27 /// An iterator over paths on a cube, from a source face to a destination face. |
| 28 #[derive(Clone, Debug)] |
28 #[derive(Clone, Debug)] |
| 29 pub struct PathIter { |
29 pub enum PathIter { |
| 30 destination : Face, |
30 Same { |
| 31 intermediate : AdjacentFaces, |
31 destination : Face, |
| 32 current : usize |
32 exhausted : bool |
| |
33 }, |
| |
34 Indirect { |
| |
35 destination : Face, |
| |
36 intermediate : AdjacentFaces, |
| |
37 current : usize |
| |
38 } |
| 33 } |
39 } |
| 34 |
40 |
| 35 impl std::iter::Iterator for PathIter { |
41 impl std::iter::Iterator for PathIter { |
| 36 type Item = Path; |
42 type Item = Path; |
| 37 |
43 |
| 38 fn next(&mut self) -> Option<Self::Item> { |
44 fn next(&mut self) -> Option<Self::Item> { |
| 39 let PathIter { destination, intermediate : ref i, ref mut current } = *self; |
45 match *self { |
| 40 while *current < i.len() { |
46 PathIter::Same { destination, ref mut exhausted } => { |
| 41 let intermediate = i[*current]; |
47 if !*exhausted { |
| 42 *current += 1; |
48 *exhausted = true; |
| 43 if intermediate == destination { |
49 return Some(Path::Direct { destination }) |
| 44 return Some(Path::Direct { destination }) |
50 } |
| 45 } else if intermediate != destination.opposing_face() { |
51 None |
| 46 return Some(Path::Indirect{ destination, intermediate }) |
52 }, |
| 47 } |
53 PathIter::Indirect { destination, intermediate : ref i, ref mut current } => { |
| 48 // Paths should never go through a face opposing the destination. |
54 while *current < i.len() { |
| 49 } |
55 let intermediate = i[*current]; |
| 50 None |
56 *current += 1; |
| |
57 if intermediate == destination { |
| |
58 return Some(Path::Direct { destination }) |
| |
59 } else if intermediate != destination.opposing_face() { |
| |
60 return Some(Path::Indirect{ destination, intermediate }) |
| |
61 } |
| |
62 // Paths should never go through a face opposing the destination. |
| |
63 } |
| |
64 None |
| |
65 } |
| |
66 } |
| 51 } |
67 } |
| 52 } |
68 } |
| 53 |
69 |
| 54 impl std::fmt::Display for Face { |
70 impl std::fmt::Display for Face { |
| 55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 164 } |
180 } |
| 165 |
181 |
| 166 |
182 |
| 167 /// Returns an iterator over all the paths from `self` to `other`. |
183 /// Returns an iterator over all the paths from `self` to `other`. |
| 168 fn paths(&self, other : Face) -> PathIter { |
184 fn paths(&self, other : Face) -> PathIter { |
| 169 PathIter { |
185 if other == *self { |
| 170 intermediate : self.adjacent_faces(), |
186 PathIter::Same { |
| 171 destination : other, |
187 destination : other, |
| 172 current : 0 |
188 exhausted : false |
| |
189 } |
| |
190 } else { |
| |
191 PathIter::Indirect { |
| |
192 intermediate : self.adjacent_faces(), |
| |
193 destination : other, |
| |
194 current : 0 |
| |
195 } |
| 173 } |
196 } |
| 174 } |
197 } |
| 175 |
198 |
| 176 /// Indicates whether an unfolded point `p` is on this face, i.e., |
199 /// Indicates whether an unfolded point `p` is on this face, i.e., |
| 177 /// has coordinates in [0,1]². |
200 /// has coordinates in [0,1]². |