1use std::hash::{Hash, Hasher};
28use std::ops::{Add, AddAssign, Mul, Sub, SubAssign};
29
30pub const ORIGIN: Point = Point::new(0, 0);
31pub const UP: Point = Point::new(0, -1);
32pub const DOWN: Point = Point::new(0, 1);
33pub const LEFT: Point = Point::new(-1, 0);
34pub const RIGHT: Point = Point::new(1, 0);
35pub const ORTHOGONAL: [Point; 4] = [UP, DOWN, LEFT, RIGHT];
36pub const DIAGONAL: [Point; 8] = [
38 Point::new(-1, -1),
39 UP,
40 Point::new(1, -1),
41 LEFT,
42 RIGHT,
43 Point::new(-1, 1),
44 DOWN,
45 Point::new(1, 1),
46];
47
48#[derive(Copy, Clone, Debug, Eq, PartialEq)]
49pub struct Point {
50 pub x: i32,
51 pub y: i32,
52}
53
54impl Point {
55 #[inline]
56 #[must_use]
57 pub const fn new(x: i32, y: i32) -> Self {
58 Point { x, y }
59 }
60
61 #[inline]
62 #[must_use]
63 pub fn clockwise(self) -> Self {
64 Point::new(-self.y, self.x)
65 }
66
67 #[inline]
68 #[must_use]
69 pub fn counter_clockwise(self) -> Self {
70 Point::new(self.y, -self.x)
71 }
72
73 #[inline]
74 #[must_use]
75 pub fn manhattan(self, other: Self) -> i32 {
76 (self.x - other.x).abs() + (self.y - other.y).abs()
77 }
78
79 #[inline]
80 #[must_use]
81 pub fn signum(self, other: Self) -> Self {
82 Point::new((self.x - other.x).signum(), (self.y - other.y).signum())
83 }
84}
85
86impl From<u8> for Point {
87 #[inline]
88 fn from(value: u8) -> Self {
89 match value {
90 b'^' | b'U' => UP,
91 b'v' | b'D' => DOWN,
92 b'<' | b'L' => LEFT,
93 b'>' | b'R' => RIGHT,
94 _ => unreachable!(),
95 }
96 }
97}
98
99impl Hash for Point {
100 #[inline]
101 fn hash<H: Hasher>(&self, state: &mut H) {
102 state.write_u32(self.x as u32);
103 state.write_u32(self.y as u32);
104 }
105}
106
107impl Add for Point {
108 type Output = Self;
109
110 #[inline]
111 fn add(self, rhs: Self) -> Self {
112 Point::new(self.x + rhs.x, self.y + rhs.y)
113 }
114}
115
116impl AddAssign for Point {
117 #[inline]
118 fn add_assign(&mut self, rhs: Self) {
119 self.x += rhs.x;
120 self.y += rhs.y;
121 }
122}
123
124impl Mul<i32> for Point {
125 type Output = Self;
126
127 #[inline]
128 fn mul(self, rhs: i32) -> Self {
129 Point::new(self.x * rhs, self.y * rhs)
130 }
131}
132
133impl Sub for Point {
134 type Output = Self;
135
136 #[inline]
137 fn sub(self, rhs: Self) -> Self {
138 Point::new(self.x - rhs.x, self.y - rhs.y)
139 }
140}
141
142impl SubAssign for Point {
143 #[inline]
144 fn sub_assign(&mut self, rhs: Self) {
145 self.x -= rhs.x;
146 self.y -= rhs.y;
147 }
148}