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}