grid_search_cardinal_common/
coord.rs1use direction::CardinalDirection;
2use grid_2d::ICoord;
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(ICoord);
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(ICoord::new(1, 0))),
17 UnitCoord(CardinalCoord(ICoord::new(0, -1))),
18 UnitCoord(CardinalCoord(ICoord::new(-1, 0))),
19 UnitCoord(CardinalCoord(ICoord::new(0, 1))),
20];
21
22fn is_cardinal(coord: ICoord) -> 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) -> ICoord {
28 self.0
29 }
30 pub fn from_coord(coord: ICoord) -> Option<Self> {
31 if is_cardinal(coord) { Some(Self(coord)) } else { None }
32 }
33 pub const fn left90(self) -> Self {
34 Self(self.0.left90())
35 }
36 pub const fn right90(self) -> Self {
37 Self(self.0.right90())
38 }
39 pub const fn left135(self) -> ICoord {
40 self.0.cardinal_left135()
41 }
42 pub const fn right135(self) -> ICoord {
43 self.0.cardinal_right135()
44 }
45 pub fn to_cardinal_direction(self) -> CardinalDirection {
46 match self.0.x.cmp(&0) {
47 Ordering::Equal => match self.0.y.cmp(&0) {
48 Ordering::Equal => unreachable!(),
49 Ordering::Less => CardinalDirection::North,
50 Ordering::Greater => CardinalDirection::South,
51 },
52 Ordering::Less => CardinalDirection::West,
53 Ordering::Greater => CardinalDirection::East,
54 }
55 }
56 pub const fn magnitude(self) -> u32 {
57 (self.0.x + self.0.y).unsigned_abs()
58 }
59 pub fn to_unit_coord(self) -> UnitCoord {
60 match self.0.x.cmp(&0) {
61 Ordering::Equal => match self.0.y.cmp(&0) {
62 Ordering::Equal => unreachable!(),
63 Ordering::Less => UnitCoord(Self(ICoord::new(0, -1))),
64 Ordering::Greater => UnitCoord(Self(ICoord::new(0, 1))),
65 },
66 Ordering::Less => UnitCoord(Self(ICoord::new(-1, 0))),
67 Ordering::Greater => UnitCoord(Self(ICoord::new(1, 0))),
68 }
69 }
70}
71
72impl UnitCoord {
73 pub const fn left90(self) -> Self {
74 Self(self.0.left90())
75 }
76 pub const fn right90(self) -> Self {
77 Self(self.0.right90())
78 }
79 pub const fn left135(self) -> ICoord {
80 self.0.left135()
81 }
82 pub const fn right135(self) -> ICoord {
83 self.0.right135()
84 }
85 pub const fn to_coord(self) -> ICoord {
86 self.0.to_coord()
87 }
88 pub const fn to_cardinal_coord(self) -> CardinalCoord {
89 self.0
90 }
91 pub fn to_cardinal_direction(self) -> CardinalDirection {
92 self.0.to_cardinal_direction()
93 }
94 pub fn from_cardinal_direction(cardinal_direction: CardinalDirection) -> Self {
95 Self(CardinalCoord(cardinal_direction.coord()))
96 }
97 pub fn scale(self, by: u32) -> CardinalCoord {
98 assert_ne!(by, 0);
99 CardinalCoord(self.to_coord() * by as i32)
100 }
101}