1use std::fmt::Display;
2
3#[derive(Debug, Clone, Copy)]
5pub struct Rect {
6 pub x: f32,
8 pub y: f32,
10 pub width: f32,
12 pub height: f32,
14}
15
16pub struct RectPosition {
18 pub x: f32,
19 pub y: f32,
20}
21
22impl RectPosition {
23 pub fn with_size(&self, width: f32, height: f32) -> Rect {
25 Rect {
26 x: self.x,
27 y: self.y,
28 width,
29 height,
30 }
31 }
32
33 pub fn ending_at(&self, x: f32, y: f32) -> Rect {
35 Rect {
36 x: self.x,
37 y: self.y,
38 width: x - self.x,
39 height: y - self.y,
40 }
41 }
42}
43
44impl Rect {
45 pub fn at(x: f32, y: f32) -> RectPosition {
47 RectPosition { x, y }
48 }
49
50 pub fn right(&self) -> f32 {
52 self.x + self.width
53 }
54
55 pub fn bottom(&self) -> f32 {
57 self.y + self.height
58 }
59
60 pub fn union(&self, other: &Rect) -> Rect {
70 let left = self.x.min(other.x);
71 let right = self.right().max(other.right());
72 let top = self.y.min(other.y);
73 let bottom = self.bottom().max(other.bottom());
74
75 Rect {
76 x: left,
77 y: top,
78 width: right - left,
79 height: bottom - top,
80 }
81 }
82
83 pub fn intersection(&self, other: &Rect) -> Rect {
93 let left = self.x.max(other.x);
94 let right = self.right().min(other.right());
95 let top = self.y.max(other.y);
96 let bottom = self.bottom().min(other.bottom());
97
98 Rect {
99 x: left,
100 y: top,
101 width: right - left,
102 height: bottom - top,
103 }
104 }
105
106 pub fn clamp(&self, width: f32, height: f32) -> Rect {
114 let left = self.x.max(0.0);
115 let right = self.right().min(width);
116 let top = self.y.max(0.0);
117 let bottom = self.bottom().min(height);
118
119 Rect {
120 x: left,
121 y: top,
122 width: right - left,
123 height: bottom - top,
124 }
125 }
126
127 pub fn iou(&self, other: &Rect) -> f32 {
137 let left = self.x.max(other.x);
138 let right = (self.right()).min(other.right());
139 let top = self.y.max(other.y);
140 let bottom = (self.bottom()).min(other.bottom());
141
142 let intersection = (right - left).max(0.0) * (bottom - top).max(0.0);
143 let area_self = self.width * self.height;
144 let area_other = other.width * other.height;
145
146 intersection / (area_self + area_other - intersection)
147 }
148
149 pub fn iou_min(&self, other: &Rect) -> f32 {
159 let left = self.x.max(other.x);
160 let right = (self.right()).min(other.right());
161 let top = self.y.max(other.y);
162 let bottom = (self.bottom()).min(other.bottom());
163
164 let intersection = (right - left).max(0.0) * (bottom - top).max(0.0);
165 let area_self = self.width * self.height;
166 let area_other = other.width * other.height;
167
168 intersection / area_self.min(area_other)
169 }
170
171 pub fn scale(&self, x_scale: f32, y_scale: f32) -> Rect {
173 Rect {
174 x: self.x * x_scale,
175 y: self.y * y_scale,
176 width: self.width * x_scale,
177 height: self.height * y_scale,
178 }
179 }
180
181 pub fn to_xywh(&self) -> (f32, f32, f32, f32) {
183 (self.x, self.y, self.width, self.height)
184 }
185}
186
187impl Display for Rect {
188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189 write!(
190 f,
191 "{{x: {}, y: {}, width: {}, height: {}}}",
192 self.x, self.y, self.width, self.height
193 )
194 }
195}