wfc/
orientation.rs

1use coord_2d::{Coord, Size};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
4#[repr(u8)]
5pub enum Orientation {
6    /// ##.
7    /// ...
8    /// ...
9    Original,
10    /// ..#
11    /// ..#
12    /// ...
13    Clockwise90,
14    /// ...
15    /// ...
16    /// .##
17    Clockwise180,
18    /// ...
19    /// #..
20    /// #..
21    Clockwise270,
22    /// #..
23    /// #..
24    /// ...
25    DiagonallyFlipped,
26    /// .##
27    /// ...
28    /// ...
29    DiagonallyFlippedClockwise90,
30    /// ...
31    /// ..#
32    /// ..#
33    DiagonallyFlippedClockwise180,
34    /// ...
35    /// ...
36    /// ##.
37    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}