bk2d/point.rs
1use std::ops::{Add, AddAssign, Sub, SubAssign};
2
3/// A point
4///
5/// # Example
6///
7/// ```
8/// let point = bk2d::point::Point::new(1, 2);
9///
10/// assert_eq!(point.x, 1);
11/// assert_eq!(point.y, 2);
12/// ```
13#[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
14pub struct Point {
15 pub x: i32,
16 pub y: i32,
17}
18
19impl Point {
20 pub fn new(x: i32, y: i32) -> Point {
21 Point { x, y }
22 }
23
24 /// Distance to origin
25 ///
26 /// # Example
27 ///
28 /// ```
29 /// assert_eq!(bk2d::point::Point::new(1, 2).length(), 3);
30 /// assert_eq!(bk2d::point::Point::new(5, -3).length(), 8);
31 /// ```
32 pub fn length(self) -> u32 {
33 (self.x.abs() + self.y.abs()) as u32
34 }
35
36 /// Point inside board
37 ///
38 /// # Example
39 ///
40 /// ```
41 /// let board = bk2d::point::Board::new(5, 5);
42 ///
43 /// assert!(bk2d::point::Point::new(0, 4).inside(board));
44 /// assert!(bk2d::point::Point::new(3, 0).inside(board));
45 /// assert!(bk2d::point::Point::new(3, 4).inside(board));
46 /// ```
47 pub fn inside(self, board: Board) -> bool {
48 !self.outside(board)
49 }
50
51 /// Point outside board
52 ///
53 /// # Example
54 ///
55 /// ```
56 /// let board = bk2d::point::Board::new(5, 5);
57 ///
58 /// assert!(bk2d::point::Point::new(5, 4).outside(board));
59 /// assert!(bk2d::point::Point::new(0, 5).outside(board));
60 /// assert!(bk2d::point::Point::new(7, -1).outside(board));
61 /// ```
62 pub fn outside(self, board: Board) -> bool {
63 self.x < 0 || self.x >= board.w as i32 || self.y < 0 || self.y >= board.h as i32
64 }
65}
66
67impl Add<Path> for Point {
68 type Output = Point;
69
70 /// Point moves on the path
71 ///
72 /// # Example
73 ///
74 /// ```
75 /// let a = bk2d::point::Point::new(3, 1);
76 /// let b = bk2d::point::Path::new(-2, 1);
77 /// assert_eq!(a + b, bk2d::point::Point::new(1, 2));
78 /// ```
79 fn add(self, other: Path) -> Point {
80 Point {
81 x: self.x + other.dx,
82 y: self.y + other.dy,
83 }
84 }
85}
86
87impl AddAssign<Path> for Point {
88 /// Point moves on the path
89 ///
90 /// # Example
91 ///
92 /// ```
93 /// let mut a = bk2d::point::Point::new(3, 1);
94 /// a += bk2d::point::Path::new(-2, 1);
95 /// assert_eq!(a, bk2d::point::Point::new(1, 2));
96 /// ```
97 fn add_assign(&mut self, other: Path) {
98 *self = *self + other
99 }
100}
101
102impl Sub<Path> for Point {
103 type Output = Point;
104
105 /// Point moves backward on the path
106 ///
107 /// # Example
108 ///
109 /// ```
110 /// let a = bk2d::point::Point::new(1, 2);
111 /// let b = bk2d::point::Path::new(-2, 1);
112 /// assert_eq!(a - b, bk2d::point::Point::new(3, 1));
113 /// ```
114 fn sub(self, other: Path) -> Point {
115 Point {
116 x: self.x - other.dx,
117 y: self.y - other.dy,
118 }
119 }
120}
121
122impl SubAssign<Path> for Point {
123 /// Point moves backward on the path
124 ///
125 /// # Example
126 ///
127 /// ```
128 /// let mut a = bk2d::point::Point::new(1, 2);
129 /// a -= bk2d::point::Path::new(-2, 1);
130 /// assert_eq!(a, bk2d::point::Point::new(3, 1));
131 /// ```
132 fn sub_assign(&mut self, other: Path) {
133 *self = *self - other
134 }
135}
136
137impl Sub<Point> for Point {
138 type Output = Path;
139
140 /// Vector between two points
141 ///
142 /// # Example
143 ///
144 /// ```
145 /// let a = bk2d::point::Point::new(1, 2);
146 /// let b = bk2d::point::Point::new(3, 1);
147 /// let sub = a - b;
148 /// assert_eq!(sub, bk2d::point::Path::new(-2, 1));
149 /// assert_eq!(sub.length(), 3);
150 /// ```
151 fn sub(self, other: Point) -> Path {
152 Path {
153 dx: self.x - other.x,
154 dy: self.y - other.y,
155 }
156 }
157}
158
159/// A path, or a vector
160///
161/// # Example
162///
163/// ```
164/// let path = bk2d::point::Path::new(2, 1);
165///
166/// assert_eq!(path.dx, 2);
167/// assert_eq!(path.dy, 1);
168///
169/// assert_eq!(path.length(), 3); // 2 + 1
170/// ```
171///
172/// # Merge multiple path
173///
174/// ```
175/// let a = bk2d::point::Path::new(2, 1);
176/// let b = bk2d::point::Path::new(-3, 2);
177/// let c = bk2d::point::Path::new(1, 0);
178/// assert_eq!(bk2d::point::Path::merge(&[a, b, c]), bk2d::point::Path::new(0, 3));
179/// assert_eq!(a + b + c, bk2d::point::Path::new(0, 3));
180/// ```
181///
182/// # Common direction
183///
184/// ```
185/// assert_eq!(bk2d::point::Path::up(), bk2d::point::Path::new(0, -1));
186/// assert_eq!(bk2d::point::Path::down(), bk2d::point::Path::new(0, 1));
187/// assert_eq!(bk2d::point::Path::left(), bk2d::point::Path::new(-1, 0));
188/// assert_eq!(bk2d::point::Path::right(), bk2d::point::Path::new(1, 0));
189/// ```
190#[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
191pub struct Path {
192 pub dx: i32,
193 pub dy: i32,
194}
195
196impl Path {
197 pub fn new(dx: i32, dy: i32) -> Path {
198 Path { dx, dy }
199 }
200
201 pub fn up() -> Path {
202 Path::new(0, -1)
203 }
204
205 pub fn down() -> Path {
206 Path::new(0, 1)
207 }
208
209 pub fn left() -> Path {
210 Path::new(-1, 0)
211 }
212
213 pub fn right() -> Path {
214 Path::new(1, 0)
215 }
216
217 /// Merge multiple path
218 ///
219 /// # Example
220 ///
221 /// ```
222 /// let a = bk2d::point::Path::new(2, 1);
223 /// let b = bk2d::point::Path::new(-3, 2);
224 /// let c = bk2d::point::Path::new(1, 0);
225 /// assert_eq!(bk2d::point::Path::merge(&[a, b]), bk2d::point::Path::new(-1, 3));
226 /// assert_eq!(bk2d::point::Path::merge(&[a, c]), bk2d::point::Path::new(3, 1));
227 /// assert_eq!(bk2d::point::Path::merge(&[b, c]), bk2d::point::Path::new(-2, 2));
228 /// assert_eq!(bk2d::point::Path::merge(&[a, b, c]), bk2d::point::Path::new(0, 3));
229 /// ```
230 pub fn merge(paths: &[Path]) -> Path {
231 let mut dx = 0;
232 let mut dy = 0;
233 for a in paths {
234 dx += a.dx;
235 dy += a.dy;
236 }
237 Path { dx, dy }
238 }
239
240 /// Distance of path
241 ///
242 /// # Example
243 ///
244 /// ```
245 /// assert_eq!(bk2d::point::Path::new(1, 2).length(), 3);
246 /// assert_eq!(bk2d::point::Path::new(5, -3).length(), 8);
247 /// ```
248 pub fn length(self) -> u32 {
249 (self.dx.abs() + self.dy.abs()) as u32
250 }
251}
252
253impl Add for Path {
254 type Output = Path;
255
256 /// Vector Addition
257 ///
258 /// # Example
259 ///
260 /// ```
261 /// let a = bk2d::point::Path::new(2, 1);
262 /// let b = bk2d::point::Path::new(-3, 2);
263 /// let c = bk2d::point::Path::new(1, 0);
264 /// assert_eq!(a + b, bk2d::point::Path::new(-1, 3));
265 /// assert_eq!(a + c, bk2d::point::Path::new(3, 1));
266 /// assert_eq!(b + c, bk2d::point::Path::new(-2, 2));
267 /// assert_eq!(a + b + c, bk2d::point::Path::new(0, 3));
268 /// ```
269 fn add(self, other: Path) -> Path {
270 Path {
271 dx: self.dx + other.dx,
272 dy: self.dy + other.dy,
273 }
274 }
275}
276
277/// A board with width [0, w), height [0, h)
278///
279/// # Example
280///
281/// ```
282/// let board = bk2d::point::Board::new(5, 6);
283///
284/// assert_eq!(board.w, 5);
285/// assert_eq!(board.h, 6);
286///
287/// let i = bk2d::point::Point::new(0, 4);
288/// assert!(board.inside(i));
289///
290/// let out = bk2d::point::Point::new(5, 3);
291/// assert!(board.outside(out));
292/// ```
293#[derive(Debug, PartialEq, Eq, Copy, Clone)]
294pub struct Board {
295 pub w: u32,
296 pub h: u32,
297}
298
299impl Board {
300 pub fn new(w: u32, h: u32) -> Board {
301 Board { w, h }
302 }
303
304 /// Point inside board
305 ///
306 /// # Example
307 ///
308 /// ```
309 /// let board = bk2d::point::Board::new(5, 6);
310 ///
311 /// assert!(board.inside(bk2d::point::Point::new(0, 4)));
312 /// assert!(board.inside(bk2d::point::Point::new(3, 0)));
313 /// assert!(board.inside(bk2d::point::Point::new(3, 5)));
314 /// ```
315 pub fn inside(self, p: Point) -> bool {
316 p.inside(self)
317 }
318
319 /// Point outside board
320 ///
321 /// # Example
322 ///
323 /// ```
324 /// let board = bk2d::point::Board::new(5, 6);
325 ///
326 /// assert!(board.outside(bk2d::point::Point::new(-1, 4)));
327 /// assert!(board.outside(bk2d::point::Point::new(3, 6)));
328 /// assert!(board.outside(bk2d::point::Point::new(10, -2)));
329 /// ```
330 pub fn outside(self, p: Point) -> bool {
331 p.outside(self)
332 }
333}
334
335impl Default for Board {
336 /// Get standard board
337 fn default() -> Board {
338 Board { w: 5, h: 5 }
339 }
340}