Skip to content

Commit 802e07e

Browse files
committed
Add rotation functions to DirectedPos
1 parent 6fde86d commit 802e07e

File tree

1 file changed

+110
-13
lines changed

1 file changed

+110
-13
lines changed

src/grid/directed_pos.rs

Lines changed: 110 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,6 @@ pub struct DirectedPos {
66
dir: Direction,
77
}
88

9-
#[repr(u8)]
10-
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
11-
pub enum Direction {
12-
North = 0,
13-
NorthEast = 1,
14-
East = 2,
15-
SouthEast = 3,
16-
South = 4,
17-
SouthWest = 5,
18-
West = 6,
19-
NorthWest = 7,
20-
}
21-
229
impl DirectedPos {
2310
pub fn new(pos: Pos, dir: Direction) -> Self {
2411
Self { pos, dir }
@@ -48,6 +35,46 @@ impl DirectedPos {
4835
self.pos.col()
4936
}
5037

38+
/// Rotate direction by 90 degrees clockwise
39+
pub fn cw(self) -> Self {
40+
Self {
41+
pos: self.pos,
42+
dir: self.dir.cw(),
43+
}
44+
}
45+
46+
/// Rotate direction by 90 degrees counter-clockwise
47+
pub fn ccw(self) -> Self {
48+
Self {
49+
pos: self.pos,
50+
dir: self.dir.ccw(),
51+
}
52+
}
53+
54+
/// Rotate direction by 45 degrees clockwise
55+
pub fn cw45(self) -> Self {
56+
Self {
57+
pos: self.pos,
58+
dir: self.dir.cw45(),
59+
}
60+
}
61+
62+
/// Rotate direction by 45 degrees counter-clockwise
63+
pub fn ccw45(self) -> Self {
64+
Self {
65+
pos: self.pos,
66+
dir: self.dir.ccw45(),
67+
}
68+
}
69+
70+
/// Rotate direction by 180 degrees
71+
pub fn reverse(self) -> Self {
72+
Self {
73+
pos: self.pos,
74+
dir: self.dir.reverse(),
75+
}
76+
}
77+
5178
pub fn north(&self, grid: &Grid) -> Option<DirectedPos> {
5279
self.pos.north(grid).map(|p| Self::new(p, self.dir))
5380
}
@@ -81,9 +108,66 @@ impl DirectedPos {
81108
}
82109
}
83110

111+
#[repr(u8)]
112+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
113+
pub enum Direction {
114+
North = 0,
115+
NorthEast = 1,
116+
East = 2,
117+
SouthEast = 3,
118+
South = 4,
119+
SouthWest = 5,
120+
West = 6,
121+
NorthWest = 7,
122+
}
123+
124+
impl Direction {
125+
/// Rotate by 90 degrees clockwise
126+
pub fn cw(self) -> Self {
127+
Self::cast((self as u8) + 2)
128+
}
129+
130+
/// Rotate by 90 degrees counter-clockwise
131+
pub fn ccw(self) -> Self {
132+
Self::cast((self as u8) + 6)
133+
}
134+
135+
/// Rotate by 45 degrees clockwise
136+
pub fn cw45(self) -> Self {
137+
Self::cast((self as u8) + 1)
138+
}
139+
140+
/// Rotate by 45 degrees counter-clockwise
141+
pub fn ccw45(self) -> Self {
142+
Self::cast((self as u8) + 7)
143+
}
144+
145+
/// Rotate by 180 degrees
146+
pub fn reverse(self) -> Self {
147+
Self::cast((self as u8) + 4)
148+
}
149+
150+
fn cast(val: u8) -> Self {
151+
let mask = 7;
152+
153+
match val & mask {
154+
0 => Self::North,
155+
1 => Self::NorthEast,
156+
2 => Self::East,
157+
3 => Self::SouthEast,
158+
4 => Self::South,
159+
5 => Self::SouthWest,
160+
6 => Self::West,
161+
7 => Self::NorthWest,
162+
_ => unreachable!(),
163+
}
164+
}
165+
}
166+
84167
#[cfg(test)]
85168
mod test {
86169
use super::*;
170+
use std::iter;
87171

88172
#[test]
89173
fn test_pos() {
@@ -97,4 +181,17 @@ mod test {
97181
DirectedPos::new(grid.pos(1), Direction::North)
98182
);
99183
}
184+
185+
#[test]
186+
fn test_rotations() {
187+
let grid = Grid::new("012\n345\n678".to_string());
188+
let first_pos = DirectedPos::new(grid.pos(4), Direction::North);
189+
190+
for pos in iter::successors(Some(first_pos), |p| Some(p.cw45())).take(8) {
191+
assert_eq!(pos, pos.cw().ccw());
192+
assert_eq!(pos, pos.cw().ccw45().ccw45());
193+
assert_eq!(pos, pos.ccw().cw45().cw45());
194+
assert_eq!(pos.cw().cw(), pos.reverse());
195+
}
196+
}
100197
}

0 commit comments

Comments
 (0)