1use crate::points::{Double2D, Vec2D};
6
7#[allow(unused_imports)]
8use irox_tools::f64::FloatExt;
9
10#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Eq, Ord)]
11pub struct Rect2D {
12 pub origin: Double2D,
13 pub far_point: Double2D,
14}
15impl Rect2D {
16 pub const fn empty() -> Rect2D {
17 Self {
18 origin: Double2D::new(f64::INFINITY, f64::INFINITY),
19 far_point: Double2D::new(f64::NEG_INFINITY, f64::NEG_INFINITY),
20 }
21 }
22 #[must_use]
23 pub fn new(origin: Double2D, size: Vec2D) -> Self {
24 Self {
25 origin,
26 far_point: origin.translate(&size),
27 }
28 }
29 #[must_use]
30 pub fn origin(&self) -> Double2D {
31 self.origin
32 }
33 #[must_use]
34 pub fn size(&self) -> Vec2D {
35 self.far_point - self.origin
36 }
37
38 #[must_use]
39 pub fn far_point(&self) -> Double2D {
40 self.far_point
41 }
42
43 #[must_use]
44 pub fn far_horiz(&self) -> Double2D {
45 Double2D {
46 x: self.far_point.x,
47 y: self.origin.y,
48 }
49 }
50 #[must_use]
51 pub fn far_vert(&self) -> Double2D {
52 Double2D {
53 x: self.origin.x,
54 y: self.far_point.y,
55 }
56 }
57
58 #[must_use]
59 pub fn corners(&self) -> [Double2D; 4] {
60 [
61 self.origin,
62 self.far_horiz(),
63 self.far_point(),
64 self.far_vert(),
65 ]
66 }
67
68 #[must_use]
69 pub fn contains(&self, point: Double2D) -> bool {
70 let Double2D { x, y } = point;
71 let Double2D { x: fx, y: fy } = self.far_point();
72 x >= self.origin.x && x <= fx && y >= self.origin.y && y <= fy
73 }
74 #[must_use]
75 pub fn intersects(&self, other: &Rect2D) -> bool {
76 for mypt in self.corners() {
77 if other.contains(mypt) {
78 return true;
79 }
80 }
81 for pt in other.corners() {
82 if self.contains(pt) {
83 return true;
84 }
85 }
86 false
87 }
88
89 pub fn add_point(&mut self, x: f64, y: f64) {
90 self.origin.x = self.origin.x.min(x);
91 self.origin.y = self.origin.y.min(y);
92 self.far_point.x = self.far_point.x.max(x);
93 self.far_point.y = self.far_point.y.max(y);
94 }
95
96 #[must_use]
97 pub fn height(&self) -> f64 {
98 (self.far_point.y - self.origin.y).abs()
99 }
100 #[must_use]
101 pub fn width(&self) -> f64 {
102 (self.far_point.x - self.origin.x).abs()
103 }
104 #[must_use]
105 pub fn center(&self) -> Double2D {
106 let y = self.height() / 2. + self.origin.y;
107 let x = self.width() / 2. + self.origin.x;
108 Double2D::new(x, y)
109 }
110 #[must_use]
111 pub fn lower_left_quadrant(&self) -> Rect2D {
112 Rect2D {
113 origin: self.origin,
114 far_point: self.center(),
115 }
116 }
117 #[must_use]
118 pub fn upper_left_quadrant(&self) -> Rect2D {
119 let ctr = self.center();
120 Rect2D {
121 origin: Double2D::new(self.origin.x, ctr.y),
122 far_point: Double2D::new(ctr.x, self.far_point.y),
123 }
124 }
125 #[must_use]
126 pub fn upper_right_quadrant(&self) -> Rect2D {
127 Rect2D {
128 origin: self.center(),
129 far_point: self.far_point,
130 }
131 }
132 #[must_use]
133 pub fn lower_right_quadrant(&self) -> Rect2D {
134 let ctr = self.center();
135 Rect2D {
136 origin: Double2D::new(ctr.x, self.origin.y),
137 far_point: Double2D::new(self.far_point.x, ctr.y),
138 }
139 }
140}
141
142#[cfg(feature = "emath")]
143impl From<emath::Rect> for Rect2D {
144 fn from(rect: emath::Rect) -> Self {
145 Self {
146 origin: rect.min.into(),
147 far_point: rect.max.into(),
148 }
149 }
150}
151#[cfg(feature = "emath")]
152impl From<Rect2D> for emath::Rect {
153 fn from(rect: Rect2D) -> Self {
154 Self {
155 min: rect.origin.into(),
156 max: rect.far_point.into(),
157 }
158 }
159}