1use coord_2d::{Coord, Size};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
4#[repr(u8)]
5pub enum Orientation {
6 Original,
10 Clockwise90,
14 Clockwise180,
18 Clockwise270,
22 DiagonallyFlipped,
26 DiagonallyFlippedClockwise90,
30 DiagonallyFlippedClockwise180,
34 DiagonallyFlippedClockwise270,
38}
39
40pub const NUM_ORIENTATIONS: usize = 8;
41
42use self::Orientation::*;
43pub const ALL: [Orientation; NUM_ORIENTATIONS] = [
44 Original,
45 Clockwise90,
46 Clockwise180,
47 Clockwise270,
48 DiagonallyFlipped,
49 DiagonallyFlippedClockwise90,
50 DiagonallyFlippedClockwise180,
51 DiagonallyFlippedClockwise270,
52];
53
54impl Orientation {
55 pub(crate) fn transform_coord(self, size: Size, coord: Coord) -> Coord {
56 match self {
57 Original => coord,
58 Clockwise90 => Coord::new(coord.y, size.x() as i32 - 1 - coord.x),
59 Clockwise180 => {
60 Coord::new(size.x() as i32 - 1 - coord.x, size.y() as i32 - 1 - coord.y)
61 }
62 Clockwise270 => Coord::new(size.y() as i32 - 1 - coord.y, coord.x),
63 DiagonallyFlipped => Coord::new(coord.y, coord.x),
64 DiagonallyFlippedClockwise90 => {
65 Coord::new(size.x() as i32 - 1 - coord.x, coord.y)
66 }
67 DiagonallyFlippedClockwise180 => {
68 Coord::new(size.y() as i32 - 1 - coord.y, size.x() as i32 - 1 - coord.x)
69 }
70 DiagonallyFlippedClockwise270 => {
71 Coord::new(coord.x, size.y() as i32 - 1 - coord.y)
72 }
73 }
74 }
75}
76
77#[derive(Debug, Clone)]
78pub struct OrientationTable<T> {
79 table: [Option<T>; NUM_ORIENTATIONS],
80}
81
82impl<T> OrientationTable<T> {
83 pub fn new() -> Self {
84 Self {
85 table: [None, None, None, None, None, None, None, None],
86 }
87 }
88 pub fn get(&self, orientation: Orientation) -> Option<&T> {
89 self.table[orientation as usize].as_ref()
90 }
91 pub fn get_mut(&mut self, orientation: Orientation) -> Option<&mut T> {
92 self.table[orientation as usize].as_mut()
93 }
94 pub fn insert(&mut self, orientation: Orientation, value: T) {
95 self.table[orientation as usize] = Some(value);
96 }
97 pub fn iter(&self) -> impl Iterator<Item = &T> {
98 self.table.iter().filter_map(|t| t.as_ref())
99 }
100}
101
102#[cfg(test)]
103mod test {
104 use super::*;
105
106 #[test]
107 fn checks() {
108 let size = Size::new(3, 3);
109 assert_eq!(
110 Orientation::Clockwise90.transform_coord(size, Coord::new(1, 2)),
111 Coord::new(2, 1)
112 );
113 assert_eq!(
114 Orientation::Clockwise90.transform_coord(size, Coord::new(0, 0)),
115 Coord::new(0, 2)
116 );
117 }
118}