1use core::ops::Mul;
2
3#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6pub struct BoundingBox<T> {
7 pub x_min: T,
9 pub y_min: T,
12 pub x_max: T,
14 pub y_max: T,
18}
19
20impl<T> BoundingBox<T>
21where
22 T: Mul<Output = T> + Copy,
23{
24 pub fn scale(&self, factor: T) -> Self {
30 Self {
31 x_min: self.x_min * factor,
32 y_min: self.y_min * factor,
33 x_max: self.x_max * factor,
34 y_max: self.y_max * factor,
35 }
36 }
37}
38
39impl<T> BoundingBox<T>
40where
41 T: PartialOrd + Copy,
42{
43 pub fn is_normalized(&self) -> bool {
46 self.x_min <= self.x_max && self.y_min <= self.y_max
47 }
48
49 pub fn normalize(&self) -> Self {
52 let (x_min, x_max) = if self.x_min <= self.x_max {
53 (self.x_min, self.x_max)
54 } else {
55 (self.x_max, self.x_min)
56 };
57 let (y_min, y_max) = if self.y_min <= self.y_max {
58 (self.y_min, self.y_max)
59 } else {
60 (self.y_max, self.y_min)
61 };
62 Self {
63 x_min,
64 y_min,
65 x_max,
66 y_max,
67 }
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn normalize() {
77 let bbox = BoundingBox {
78 x_min: 10,
79 y_min: 20,
80 x_max: 5,
81 y_max: 15,
82 };
83 assert!(!bbox.is_normalized());
84 let normalized = bbox.normalize();
85 assert!(normalized.is_normalized());
86 assert_eq!(normalized.x_min, 5);
87 assert_eq!(normalized.y_min, 15);
88 assert_eq!(normalized.x_max, 10);
89 assert_eq!(normalized.y_max, 20);
90 }
91
92 #[test]
93 fn normalize_negative_scaled() {
94 let bbox = BoundingBox {
95 x_min: 5,
96 y_min: 5,
97 x_max: 10,
98 y_max: 10,
99 };
100 assert_eq!(bbox.normalize(), bbox);
101 let scaled = bbox.scale(-2);
102 assert!(!scaled.is_normalized());
103 let normalized = scaled.normalize();
104 assert_eq!(normalized.x_min, -20);
105 assert_eq!(normalized.y_min, -20);
106 assert_eq!(normalized.x_max, -10);
107 assert_eq!(normalized.y_max, -10);
108 }
109}