1use std::fmt::Debug;
6
7use crate::prelude::Xy;
8
9
10
11pub struct Rect<T> {
16 pub min: Xy<T>,
17 pub max: Xy<T>,
18}
19
20impl <T> Rect<T> {
21 pub fn new(min_x: T, min_y: T, max_x: T, max_y: T) -> Self {
22 Self {
23 min: Xy::new(min_x, min_y),
24 max: Xy::new(max_x, max_y),
25 }
26 }
27}
28
29impl<T: PartialOrd> Rect<T> {
30 pub fn intersects(&self, other: &Self) -> bool {
31 self.min.x < other.max.x
32 && self.max.x > other.min.x
33 && self.min.y < other.max.y
34 && self.max.y > other.min.y
35 }
36
37 pub fn contains(self, xy: Xy<T>) -> bool {
38 xy.x >= self.min.x
39 && xy.x < self.max.x
40 && xy.y >= self.min.y
41 && xy.y < self.max.y
42 }
43}
44
45impl<T: Copy> Rect<T> {
46 pub fn left(&self) -> T {
47 self.min.x
48 }
49
50 pub fn right(&self) -> T {
51 self.max.x
52 }
53
54 pub fn top(&self) -> T {
55 self.min.y
56 }
57
58 pub fn bottom(&self) -> T {
59 self.max.y
60 }
61}
62
63
64
65impl<T: Clone> Clone for Rect<T> {
70 fn clone(&self) -> Self {
71 Self {
72 min: self.min.clone(),
73 max: self.max.clone(),
74 }
75 }
76}
77
78impl<T: Copy> Copy for Rect<T> {}
79
80impl<T: Debug> Debug for Rect<T> {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 f.debug_struct("Rect")
83 .field("min", &self.min)
84 .field("max", &self.max)
85 .finish()
86 }
87}
88
89impl<T: Default> Default for Rect<T> {
90 fn default() -> Self {
91 Self {
92 min: Xy::default(),
93 max: Xy::default(),
94 }
95 }
96}
97
98impl<T: Eq> Eq for Rect<T> {}
99
100impl<T: PartialEq> PartialEq for Rect<T> {
101 fn eq(&self, other: &Self) -> bool {
102 self.min == other.min && self.max == other.max
103 }
104}
105
106
107
108#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
118 fn assert_implementations() {
119 let u32rect_a: Rect<u32> = Rect::new(1, 3, 2, 4);
120 let u32rect_b: Rect<u32> = Rect::new(3, 1, 4, 2);
121
122 assert_eq!(u32rect_a, u32rect_a.clone());
123 assert_ne!(u32rect_a, u32rect_b);
124 }
125}