1use std::fmt;
2use std::ops::{BitOr, BitOrAssign, Div, Mul};
3
4use crate::{Pos2, Rangef, Vec2, midpoint, pos2};
5
6#[derive(Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
15pub struct Rect {
16 pub min: Pos2,
18
19 pub max: Pos2,
21}
22
23impl Rect {
24 pub const EVERYTHING: Self = Self {
26 min: pos2(-f32::INFINITY, -f32::INFINITY),
27 max: pos2(f32::INFINITY, f32::INFINITY),
28 };
29
30 pub const NOTHING: Self = Self {
33 min: pos2(f32::INFINITY, f32::INFINITY),
34 max: pos2(-f32::INFINITY, -f32::INFINITY),
35 };
36
37 pub const ZERO: Self = Self {
38 min: Pos2::ZERO,
39 max: Pos2::ZERO,
40 };
41
42 #[inline]
43 pub const fn from_min_max(min: Pos2, max: Pos2) -> Self {
44 Self { min, max }
45 }
46
47 #[inline]
49 pub fn from_min_size(min: Pos2, size: Vec2) -> Self {
50 Self {
51 min,
52 max: min + size,
53 }
54 }
55
56 #[inline]
57 pub fn from_center_size(center: Pos2, size: Vec2) -> Self {
58 Self {
59 min: center - size * 0.5,
60 max: center + size * 0.5,
61 }
62 }
63
64 #[inline]
66 pub fn from_two_pos(a: Pos2, b: Pos2) -> Self {
67 Self {
68 min: pos2(a.x.min(b.x), a.y.min(b.y)),
69 max: pos2(a.x.max(b.x), a.y.max(b.y)),
70 }
71 }
72
73 #[inline]
75 pub const fn from_pos(point: Pos2) -> Self {
76 Self {
77 min: point,
78 max: point,
79 }
80 }
81
82 pub fn from_points(points: &[Pos2]) -> Self {
84 let mut rect = Self::NOTHING;
85 for &p in points {
86 rect.extend_with(p);
87 }
88 rect
89 }
90
91 #[inline]
92 pub fn from_x_y_ranges(x_range: Rangef, y_range: Rangef) -> Self {
93 Self {
94 min: pos2(x_range.min, y_range.min),
95 max: pos2(x_range.max, y_range.max),
96 }
97 }
98
99 #[must_use]
101 pub fn expand(self, amnt: f32) -> Self {
102 self.expand2(Vec2::splat(amnt))
103 }
104
105 #[must_use]
107 pub fn expand2(self, amnt: Vec2) -> Self {
108 Self::from_min_max(self.min - amnt, self.max + amnt)
109 }
110
111 #[must_use]
113 pub fn shrink(self, amnt: f32) -> Self {
114 self.shrink2(Vec2::splat(amnt))
115 }
116
117 #[must_use]
119 pub fn shrink2(self, amnt: Vec2) -> Self {
120 Self::from_min_max(self.min + amnt, self.max - amnt)
121 }
122
123 #[must_use]
124 #[inline]
125 pub fn translate(self, amnt: Vec2) -> Self {
126 Self::from_min_size(self.min + amnt, self.size())
127 }
128
129 #[must_use]
130 #[inline]
131 pub fn intersects(self, other: Self) -> bool {
132 self.min.x <= other.max.x
133 && other.min.x <= self.max.x
134 && self.min.y <= other.max.y
135 && other.min.y <= self.max.y
136 }
137
138 pub fn set_width(&mut self, w: f32) {
140 self.max.x = self.min.x + w;
141 }
142
143 pub fn set_height(&mut self, h: f32) {
145 self.max.y = self.min.y + h;
146 }
147
148 pub fn set_center(&mut self, center: Pos2) {
150 *self = self.translate(center - self.center());
151 }
152
153 #[must_use]
154 #[inline]
155 pub fn contains(&self, p: Pos2) -> bool {
156 self.min.x <= p.x && p.x <= self.max.x && self.min.y <= p.y && p.y <= self.max.y
157 }
158
159 #[must_use]
160 pub fn contains_rect(&self, other: Self) -> bool {
161 self.contains(other.min) && self.contains(other.max)
162 }
163
164 #[must_use]
166 pub fn clamp(&self, p: Pos2) -> Pos2 {
167 p.clamp(self.min, self.max)
168 }
169
170 #[inline]
171 pub fn extend_with(&mut self, p: Pos2) {
172 self.min = self.min.min(p);
173 self.max = self.max.max(p);
174 }
175
176 #[inline]
178 #[must_use]
179 pub fn union(self, other: Self) -> Self {
180 Self {
181 min: self.min.min(other.min),
182 max: self.max.max(other.max),
183 }
184 }
185
186 #[inline]
188 #[must_use]
189 pub fn intersect(self, other: Self) -> Self {
190 Self {
191 min: self.min.max(other.min),
192 max: self.max.min(other.max),
193 }
194 }
195
196 #[inline]
197 pub fn center(&self) -> Pos2 {
198 Pos2 {
199 x: midpoint(self.min.x, self.max.x),
200 y: midpoint(self.min.y, self.max.y),
201 }
202 }
203
204 #[inline]
205 pub fn size(&self) -> Vec2 {
206 self.max - self.min
207 }
208
209 #[inline]
211 pub fn width(&self) -> f32 {
212 self.max.x - self.min.x
213 }
214
215 #[inline]
217 pub fn height(&self) -> f32 {
218 self.max.y - self.min.y
219 }
220
221 pub fn aspect_ratio(&self) -> f32 {
223 self.width() / self.height()
224 }
225
226 #[inline]
228 pub fn area(&self) -> f32 {
229 self.width().max(0.0) * self.height().max(0.0)
230 }
231
232 #[inline]
234 pub fn is_negative(&self) -> bool {
235 self.max.x < self.min.x || self.max.y < self.min.y
236 }
237
238 #[inline]
240 pub fn is_positive(&self) -> bool {
241 self.min.x < self.max.x && self.min.y < self.max.y
242 }
243
244 #[inline]
245 pub fn is_finite(&self) -> bool {
246 self.min.is_finite() && self.max.is_finite()
247 }
248
249 #[inline]
250 pub fn x_range(&self) -> Rangef {
251 Rangef::new(self.min.x, self.max.x)
252 }
253
254 #[inline]
255 pub fn y_range(&self) -> Rangef {
256 Rangef::new(self.min.y, self.max.y)
257 }
258}
259
260impl Rect {
262 #[inline]
263 pub fn left(&self) -> f32 {
264 self.min.x
265 }
266
267 #[inline]
268 pub fn right(&self) -> f32 {
269 self.max.x
270 }
271
272 #[inline]
273 pub fn top(&self) -> f32 {
274 self.min.y
275 }
276
277 #[inline]
278 pub fn bottom(&self) -> f32 {
279 self.max.y
280 }
281
282 #[inline]
283 pub fn left_top(&self) -> Pos2 {
284 pos2(self.left(), self.top())
285 }
286
287 #[inline]
288 pub fn center_top(&self) -> Pos2 {
289 pos2(self.center().x, self.top())
290 }
291
292 #[inline]
293 pub fn right_top(&self) -> Pos2 {
294 pos2(self.right(), self.top())
295 }
296
297 #[inline]
298 pub fn left_center(&self) -> Pos2 {
299 pos2(self.left(), self.center().y)
300 }
301
302 #[inline]
303 pub fn right_center(&self) -> Pos2 {
304 pos2(self.right(), self.center().y)
305 }
306
307 #[inline]
308 pub fn left_bottom(&self) -> Pos2 {
309 pos2(self.left(), self.bottom())
310 }
311
312 #[inline]
313 pub fn center_bottom(&self) -> Pos2 {
314 pos2(self.center().x, self.bottom())
315 }
316
317 #[inline]
318 pub fn right_bottom(&self) -> Pos2 {
319 pos2(self.right(), self.bottom())
320 }
321}
322
323impl From<[Pos2; 2]> for Rect {
324 #[inline]
325 fn from([min, max]: [Pos2; 2]) -> Self {
326 Self { min, max }
327 }
328}
329
330impl Mul<f32> for Rect {
331 type Output = Self;
332
333 #[inline]
334 fn mul(self, factor: f32) -> Self {
335 Self {
336 min: self.min * factor,
337 max: self.max * factor,
338 }
339 }
340}
341
342impl Mul<Rect> for f32 {
343 type Output = Rect;
344
345 #[inline]
346 fn mul(self, r: Rect) -> Rect {
347 Rect {
348 min: self * r.min,
349 max: self * r.max,
350 }
351 }
352}
353
354impl Div<f32> for Rect {
355 type Output = Self;
356
357 #[inline]
358 fn div(self, factor: f32) -> Self {
359 Self {
360 min: self.min / factor,
361 max: self.max / factor,
362 }
363 }
364}
365
366impl BitOr for Rect {
367 type Output = Self;
368
369 #[inline]
370 fn bitor(self, other: Self) -> Self {
371 self.union(other)
372 }
373}
374
375impl BitOrAssign for Rect {
376 #[inline]
377 fn bitor_assign(&mut self, other: Self) {
378 *self = self.union(other);
379 }
380}
381
382impl fmt::Debug for Rect {
383 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
384 if let Some(precision) = f.precision() {
385 write!(f, "[{1:.0$?} - {2:.0$?}]", precision, self.min, self.max)
386 } else {
387 write!(f, "[{:?} - {:?}]", self.min, self.max)
388 }
389 }
390}
391
392impl fmt::Display for Rect {
393 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
394 write!(f, "[{} - {}]", self.min, self.max)
395 }
396}