1use crate::Point;
2
3#[derive(Debug, Clone)]
4pub struct Rectangle {
5 pub x: i32,
6 pub y: i32,
7 pub width: i32,
8 pub height: i32,
9}
10
11impl Rectangle {
12 pub fn new(x: i32, y: i32, width: i32, height: i32) -> Self {
14 Self {
15 x,
16 y,
17 width,
18 height,
19 }
20 }
21
22 pub fn overlaps_rectangle(&self, other: &Self) -> bool {
24 self.x < (other.x + other.width) &&
25 (self.x + self.width) > other.x &&
26
27 self.y < (other.y + other.height) &&
28 (self.y + self.height) > other.y
29 }
30
31 pub fn contains_rectangle(&self, other: &Self) -> bool {
33 other.x >= self.x &&
34 other.x + other.width <= self.x + self.width &&
35 other.y >= self.y &&
36 other.y + other.height <= self.y + self.height
37 }
38
39 pub fn contains_point(&self, point: Point) -> bool {
41 point.x >= self.x && point.x <= (self.x + self.width) &&
42 point.y >= self.y && point.y <= (self.y + self.height)
43 }
44
45 pub fn inflate(&self, horizontal: i32, vertical: i32) -> Self {
47 Self::new(
48 self.x - horizontal,
49 self.y - vertical,
50 self.width + horizontal,
51 self.height + vertical,
52 )
53 }
54
55 pub fn translate(&self, x: i32, y: i32) -> Self {
57 Self::new(
58 self.x + x,
59 self.y + y,
60 self.width,
61 self.height,
62 )
63 }
64
65 pub fn union(&self, other: Self) -> Self {
67 let x = self.x.min(other.x);
68 let y = self.y.min(other.y);
69 let width = (self.x + self.width).max(other.x + other.width) - x;
70 let height = (self.y + self.height).max(other.y + other.height) - y;
71 Self::new(
72 x,
73 y,
74 width,
75 height,
76 )
77 }
78
79 pub(crate) fn to_rendering_position(&self, bounds: &Self) -> (f32, f32, f32, f32) {
80 let left = self.x as f32 / bounds.width as f32;
83 let right = (self.x + self.width) as f32 / bounds.width as f32;
84
85
86 let top = self.y as f32 / bounds.height as f32;
87 let bottom = (self.y + self.height) as f32 / bounds.height as f32;
88
89 (left, right, top, bottom)
90 }
91}
92
93impl Into<(i32, i32, i32, i32)> for Rectangle {
94 fn into(self) -> (i32, i32, i32, i32) {
95 (self.x, self.y, self.width, self.height)
96 }
97}
98
99impl From<(i32, i32, i32, i32)> for Rectangle {
100 fn from(values: (i32, i32, i32, i32)) -> Self {
101 Self::new(values.0, values.1, values.2, values.3)
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn it_works() {
111 let a = Rectangle::new(0, 0, 3, 3);
112 let b = Rectangle::new(1, 1, 1, 1);
113
114 assert!(a.overlaps_rectangle(&b));
115 assert!(b.overlaps_rectangle(&a));
116
117 assert!(a.contains_rectangle(&b));
118 assert!(!b.contains_rectangle(&a));
119 }
120}