grid_search_cardinal_common/
coord.rs1use 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}