cogs_gamedev/grids/
rectangles.rs1use super::ICoord;
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9pub struct IRect {
10 pub left: isize,
11 pub top: isize,
12 pub width: usize,
13 pub height: usize,
14}
15
16impl IRect {
17 pub fn new(left: isize, top: isize, width: usize, height: usize) -> Self {
18 Self {
19 left,
20 top,
21 width,
22 height,
23 }
24 }
25
26 pub fn centered(center: ICoord, width: usize, height: usize) -> Self {
28 let top = center.y - height as isize / 2;
29 let left = center.x - width as isize / 2;
30 Self::new(left, top, width, height)
31 }
32
33 pub fn contains(&self, pos: ICoord) -> bool {
37 self.top <= pos.y && self.bottom() >= pos.y && self.left <= pos.x && self.right() >= pos.x
38 }
39
40 pub fn area(&self) -> usize {
41 self.width * self.height
42 }
43
44 pub fn contained_coords(&self) -> RectIter {
49 RectIter::new(*self)
50 }
51
52 pub fn right(&self) -> isize {
53 self.left + self.width as isize - 1
54 }
55
56 pub fn bottom(&self) -> isize {
57 self.top + self.height as isize - 1
58 }
59
60 pub fn shifted(self, by: ICoord) -> IRect {
61 IRect {
62 top: self.top + by.y,
63 left: self.left + by.x,
64 ..self
65 }
66 }
67}
68
69impl std::ops::Add<ICoord> for IRect {
70 type Output = IRect;
71 fn add(self, rhs: ICoord) -> Self::Output {
72 self.shifted(rhs)
73 }
74}
75
76pub struct RectIter {
77 rect: IRect,
78 cursor: ICoord,
79 exhausted: bool,
80}
81
82impl RectIter {
83 pub fn new(rect: IRect) -> Self {
84 Self {
85 rect,
86 cursor: ICoord::new(rect.left, rect.top),
87 exhausted: rect.width == 0 || rect.height == 0,
89 }
90 }
91}
92
93impl Iterator for RectIter {
94 type Item = ICoord;
95 fn next(&mut self) -> Option<Self::Item> {
96 if !self.exhausted {
97 let out = self.cursor;
98
99 self.cursor.x += 1;
100 if !self.rect.contains(self.cursor) {
101 self.cursor.x = self.rect.left;
102 self.cursor.y += 1;
103 if !self.rect.contains(self.cursor) {
104 self.exhausted = true;
105 }
108 }
109
110 Some(out)
111 } else {
112 None
113 }
114 }
115}