1use impl_trait_for_tuples::impl_for_tuples;
4
5use crate::{polygon::Polygon, rect::Rect, union::BoundingUnion};
6
7pub trait Bbox {
19 fn bbox(&self) -> Option<Rect>;
26
27 fn bbox_rect(&self) -> Rect {
30 self.bbox().unwrap()
31 }
32}
33
34impl<T> Bbox for &T
35where
36 T: Bbox,
37{
38 fn bbox(&self) -> Option<Rect> {
39 T::bbox(*self)
40 }
41}
42
43#[impl_for_tuples(64)]
44impl Bbox for TupleIdentifier {
45 #[allow(clippy::let_and_return)]
46 fn bbox(&self) -> Option<Rect> {
47 let mut bbox = None;
48 for_tuples!( #( bbox = bbox.bounding_union(&TupleIdentifier.bbox()); )* );
49 bbox
50 }
51}
52
53impl<T: Bbox> Bbox for Vec<T> {
54 fn bbox(&self) -> Option<Rect> {
55 let mut bbox = None;
56 for item in self {
57 bbox = bbox.bounding_union(&item.bbox());
58 }
59 bbox
60 }
61}
62
63impl Bbox for Option<Rect> {
64 fn bbox(&self) -> Option<Rect> {
65 *self
66 }
67}
68
69impl Bbox for Option<Polygon> {
70 fn bbox(&self) -> Option<Rect> {
71 match self {
72 Some(polygon) => Rect::from_sides_option(
73 polygon.left(),
74 polygon.bot(),
75 polygon.right(),
76 polygon.top(),
77 ),
78 None => None,
79 }
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use crate::{bbox::Bbox, point::Point, polygon::Polygon, rect::Rect};
86
87 #[test]
88 fn bbox_works_for_tuples() {
89 let tuple = (
90 Rect::from_sides(0, 0, 100, 200),
91 Rect::from_sides(-50, 20, 90, 250),
92 );
93 assert_eq!(tuple.bbox(), Some(Rect::from_sides(-50, 0, 100, 250)));
94 }
95
96 #[test]
97 fn bbox_works_for_vecs() {
98 let v = vec![
99 Rect::from_sides(0, 0, 100, 200),
100 Rect::from_sides(-50, 20, 90, 250),
101 ];
102 assert_eq!(v.bbox(), Some(Rect::from_sides(-50, 0, 100, 250)));
103 }
104
105 #[test]
106 fn bbox_works_for_polygon() {
107 let points = vec![
108 Point { x: -10, y: 25 },
109 Point { x: 0, y: 16 },
110 Point { x: 40, y: -20 },
111 ];
112 let polygon = Polygon::from_verts(points);
113 assert_eq!(polygon.bbox(), Some(Rect::from_sides(-10, -20, 40, 25)));
114 }
115
116 #[test]
117 fn bbox_works_for_diff_types() {
118 let points = vec![
119 Point { x: -10, y: 25 },
120 Point { x: 0, y: 16 },
121 Point { x: 40, y: -20 },
122 ];
123 let tuple: (Rect, Polygon) = (
124 Rect::from_sides(0, 0, 100, 200),
125 Polygon::from_verts(points),
126 );
127 assert_eq!(tuple.bbox(), Some(Rect::from_sides(-10, -20, 100, 200)));
128 }
129}