1use serde::{Deserialize, Serialize};
7
8use crate::{
10 geom::{Point, Shape},
11 Int, Rect,
12};
13
14#[derive(Debug, Default, Copy, Clone, Deserialize, Serialize, PartialEq, Eq)]
21pub struct BoundBox {
22 pub p0: Point,
23 pub p1: Point,
24}
25impl BoundBox {
26 fn new(p0: Point, p1: Point) -> Self {
29 Self { p0, p1 }
30 }
31 pub fn from_point(pt: &Point) -> Self {
34 Self {
35 p0: pt.clone(),
36 p1: pt.clone(),
37 }
38 }
39 pub fn from_points(p0: &Point, p1: &Point) -> Self {
41 Self {
42 p0: Point::new(p0.x.min(p1.x), p0.y.min(p1.y)),
43 p1: Point::new(p0.x.max(p1.x), p0.y.max(p1.y)),
44 }
45 }
46 pub fn empty() -> Self {
48 Self {
49 p0: Point::new(Int::MAX, Int::MAX),
50 p1: Point::new(Int::MIN, Int::MIN),
51 }
52 }
53 pub fn is_empty(&self) -> bool {
55 self.p0.x > self.p1.x || self.p0.y > self.p1.y
56 }
57 pub fn contains(&self, pt: &Point) -> bool {
59 self.p0.x <= pt.x && self.p1.x >= pt.x && self.p0.y <= pt.y && self.p1.y >= pt.y
60 }
61 pub fn expand(&mut self, delta: Int) {
63 self.p0.x -= delta;
64 self.p0.y -= delta;
65 self.p1.x += delta;
66 self.p1.y += delta;
67 }
68 pub fn size(&self) -> (Int, Int) {
70 (self.p1.x - self.p0.x, self.p1.y - self.p0.y)
71 }
72 pub fn center(&self) -> Point {
74 Point::new((self.p0.x + self.p1.x) / 2, (self.p0.y + self.p1.y) / 2)
75 }
76}
77
78pub trait BoundBoxTrait {
86 fn bbox(&self) -> BoundBox;
88 fn intersection(&self, bbox: &BoundBox) -> BoundBox {
92 self.bbox().intersection(&bbox)
93 }
94 fn union(&self, bbox: &BoundBox) -> BoundBox {
98 self.bbox().union(&bbox)
99 }
100}
101impl BoundBoxTrait for BoundBox {
102 fn bbox(&self) -> BoundBox {
103 self.clone()
106 }
107 fn intersection(&self, bbox: &BoundBox) -> BoundBox {
108 let pmin = Point::new(self.p0.x.max(bbox.p0.x), self.p0.y.max(bbox.p0.y));
109 let pmax = Point::new(self.p1.x.min(bbox.p1.x), self.p1.y.min(bbox.p1.y));
110 if pmin.x > pmax.x || pmin.y > pmax.y {
112 return BoundBox::empty();
113 }
114 BoundBox::new(pmin, pmax)
116 }
117 fn union(&self, bbox: &BoundBox) -> BoundBox {
118 BoundBox::new(
120 Point::new(self.p0.x.min(bbox.p0.x), self.p0.y.min(bbox.p0.y)),
121 Point::new(self.p1.x.max(bbox.p1.x), self.p1.y.max(bbox.p1.y)),
122 )
123 }
124}
125impl BoundBoxTrait for Point {
126 fn bbox(&self) -> BoundBox {
127 BoundBox::from_point(self)
128 }
129 fn intersection(&self, bbox: &BoundBox) -> BoundBox {
130 if !bbox.contains(self) {
131 return BoundBox::empty();
132 }
133 bbox.intersection(&BoundBox::from_point(self))
134 }
135 fn union(&self, bbox: &BoundBox) -> BoundBox {
136 BoundBox::new(
137 Point::new(self.x.min(bbox.p0.x), self.y.min(bbox.p0.y)),
138 Point::new(self.x.max(bbox.p1.x), self.y.max(bbox.p1.y)),
139 )
140 }
141}
142impl BoundBoxTrait for Shape {
143 fn bbox(&self) -> BoundBox {
144 match self {
146 Shape::Rect(ref r) => BoundBox::from_points(&r.p0, &r.p1),
147 Shape::Polygon(ref p) => (&p.points).bbox(),
148 Shape::Path(ref p) => (&p.points).bbox(),
149 }
150 }
151}
152
153impl BoundBoxTrait for Rect {
154 fn bbox(&self) -> BoundBox {
155 BoundBox::from_points(&self.p0, &self.p1)
156 }
157}
158
159impl BoundBoxTrait for Vec<Point> {
160 fn bbox(&self) -> BoundBox {
161 let mut bbox = BoundBox::empty();
163 for pt in self {
164 bbox = bbox.union(&pt.bbox());
165 }
166 bbox
167 }
168}