grid_search_cardinal_common/
coord.rs

1use direction::CardinalDirection;
2use grid_2d::Coord;
3#[cfg(feature = "serialize")]
4use serde::{Deserialize, Serialize};
5use std::cmp::Ordering;
6
7#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
8#[derive(Clone, Copy, Debug)]
9pub struct CardinalCoord(Coord);
10
11#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
12#[derive(Clone, Copy, Debug)]
13pub struct UnitCoord(CardinalCoord);
14
15pub const UNIT_COORDS: [UnitCoord; 4] = [
16    UnitCoord(CardinalCoord(Coord::new(1, 0))),
17    UnitCoord(CardinalCoord(Coord::new(0, -1))),
18    UnitCoord(CardinalCoord(Coord::new(-1, 0))),
19    UnitCoord(CardinalCoord(Coord::new(0, 1))),
20];
21
22fn is_cardinal(coord: Coord) -> bool {
23    (coord.x == 0 && coord.y != 0) || (coord.y == 0 && coord.x != 0)
24}
25
26impl CardinalCoord {
27    pub const fn to_coord(self) -> Coord {
28        self.0
29    }
30    pub fn from_coord(coord: Coord) -> Option<Self> {
31        if is_cardinal(coord) {
32            Some(Self(coord))
33        } else {
34            None
35        }
36    }
37    pub const fn left90(self) -> Self {
38        Self(self.0.left90())
39    }
40    pub const fn right90(self) -> Self {
41        Self(self.0.right90())
42    }
43    pub const fn left135(self) -> Coord {
44        self.0.cardinal_left135()
45    }
46    pub const fn right135(self) -> Coord {
47        self.0.cardinal_right135()
48    }
49    pub fn to_cardinal_direction(self) -> CardinalDirection {
50        match self.0.x.cmp(&0) {
51            Ordering::Equal => match self.0.y.cmp(&0) {
52                Ordering::Equal => unreachable!(),
53                Ordering::Less => CardinalDirection::North,
54                Ordering::Greater => CardinalDirection::South,
55            },
56            Ordering::Less => CardinalDirection::West,
57            Ordering::Greater => CardinalDirection::East,
58        }
59    }
60    pub const fn magnitude(self) -> u32 {
61        (self.0.x + self.0.y).abs() as u32
62    }
63    pub fn to_unit_coord(self) -> UnitCoord {
64        match self.0.x.cmp(&0) {
65            Ordering::Equal => match self.0.y.cmp(&0) {
66                Ordering::Equal => unreachable!(),
67                Ordering::Less => UnitCoord(Self(Coord::new(0, -1))),
68                Ordering::Greater => UnitCoord(Self(Coord::new(0, 1))),
69            },
70            Ordering::Less => UnitCoord(Self(Coord::new(-1, 0))),
71            Ordering::Greater => UnitCoord(Self(Coord::new(1, 0))),
72        }
73    }
74}
75
76impl UnitCoord {
77    pub const fn left90(self) -> Self {
78        Self(self.0.left90())
79    }
80    pub const fn right90(self) -> Self {
81        Self(self.0.right90())
82    }
83    pub const fn left135(self) -> Coord {
84        self.0.left135()
85    }
86    pub const fn right135(self) -> Coord {
87        self.0.right135()
88    }
89    pub const fn to_coord(self) -> Coord {
90        self.0.to_coord()
91    }
92    pub const fn to_cardinal_coord(self) -> CardinalCoord {
93        self.0
94    }
95    pub fn to_cardinal_direction(self) -> CardinalDirection {
96        self.0.to_cardinal_direction()
97    }
98    pub fn from_cardinal_direction(cardinal_direction: CardinalDirection) -> Self {
99        Self(CardinalCoord(cardinal_direction.coord()))
100    }
101    pub fn scale(self, by: u32) -> CardinalCoord {
102        assert_ne!(by, 0);
103        CardinalCoord(self.to_coord() * by as i32)
104    }
105}