1use std::cmp::Ordering;
2
3use num_traits::{Bounded, Num, NumCast};
4
5pub trait IndexableNum: Copy + Num + PartialOrd + Default + Bounded + NumCast {
8 #[inline]
10 fn min(self, other: Self) -> Self {
11 if self < other {
12 return self;
13 }
14
15 other
16 }
17
18 #[inline]
20 fn max(self, other: Self) -> Self {
21 if self > other {
22 return self;
23 }
24
25 other
26 }
27
28 fn total_cmp(&self, other: &Self) -> Ordering;
32}
33
34macro_rules! impl_indexable_num_for_ord_type {
35 ($t:ty) => {
36 impl IndexableNum for $t {
37 #[inline]
38 fn min(self, other: Self) -> Self {
39 std::cmp::min(self, other)
40 }
41 #[inline]
42 fn max(self, other: Self) -> Self {
43 std::cmp::max(self, other)
44 }
45 #[inline]
46 fn total_cmp(&self, other: &Self) -> Ordering {
47 self.cmp(other)
48 }
49 }
50 };
51}
52
53impl_indexable_num_for_ord_type!(i8);
55impl_indexable_num_for_ord_type!(u8);
56impl_indexable_num_for_ord_type!(i16);
57impl_indexable_num_for_ord_type!(u16);
58impl_indexable_num_for_ord_type!(i32);
59impl_indexable_num_for_ord_type!(u32);
60impl_indexable_num_for_ord_type!(i64);
61impl_indexable_num_for_ord_type!(u64);
62impl_indexable_num_for_ord_type!(i128);
63impl_indexable_num_for_ord_type!(u128);
64impl IndexableNum for f32 {
65 #[inline]
66 fn min(self, other: Self) -> Self {
67 self.min(other)
68 }
69 #[inline]
70 fn max(self, other: Self) -> Self {
71 self.max(other)
72 }
73 #[inline]
74 fn total_cmp(&self, other: &Self) -> Ordering {
75 self.total_cmp(other)
76 }
77}
78impl IndexableNum for f64 {
79 #[inline]
80 fn min(self, other: Self) -> Self {
81 self.min(other)
82 }
83 #[inline]
84 fn max(self, other: Self) -> Self {
85 self.max(other)
86 }
87 #[inline]
88 fn total_cmp(&self, other: &Self) -> Ordering {
89 self.total_cmp(other)
90 }
91}
92
93#[allow(clippy::upper_case_acronyms)]
95#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
96pub struct AABB<T = f64> {
97 pub min_x: T,
99 pub min_y: T,
101 pub max_x: T,
103 pub max_y: T,
105}
106
107impl<T> Default for AABB<T>
108where
109 T: IndexableNum,
110{
111 #[inline]
112 fn default() -> Self {
113 AABB {
114 min_x: T::zero(),
115 min_y: T::zero(),
116 max_x: T::zero(),
117 max_y: T::zero(),
118 }
119 }
120}
121
122impl<T> AABB<T>
123where
124 T: IndexableNum,
125{
126 #[inline]
127 pub fn new(min_x: T, min_y: T, max_x: T, max_y: T) -> AABB<T> {
128 AABB {
129 min_x,
130 min_y,
131 max_x,
132 max_y,
133 }
134 }
135
136 #[inline]
152 pub fn overlaps_aabb(&self, other: &AABB<T>) -> bool {
153 self.overlaps(other.min_x, other.min_y, other.max_x, other.max_y)
154 }
155
156 #[inline]
159 pub fn overlaps(&self, min_x: T, min_y: T, max_x: T, max_y: T) -> bool {
160 if self.max_x < min_x || self.max_y < min_y || self.min_x > max_x || self.min_y > max_y {
161 return false;
162 }
163
164 true
165 }
166
167 #[inline]
178 pub fn contains_aabb(&self, other: &AABB<T>) -> bool {
179 self.contains(other.min_x, other.min_y, other.max_x, other.max_y)
180 }
181
182 #[inline]
185 pub fn contains(&self, min_x: T, min_y: T, max_x: T, max_y: T) -> bool {
186 self.min_x <= min_x && self.min_y <= min_y && self.max_x >= max_x && self.max_y >= max_y
187 }
188}
189
190#[derive(Debug, Default)]
192pub enum Control<B> {
193 #[default]
195 Continue,
196 Break(B),
198}
199
200pub trait ControlFlow {
202 fn continuing() -> Self;
204 fn should_break(&self) -> bool;
206}
207
208impl<B> ControlFlow for Control<B> {
209 #[inline]
210 fn continuing() -> Self {
211 Control::Continue
212 }
213
214 #[inline]
215 fn should_break(&self) -> bool {
216 matches!(*self, Control::Break(_))
217 }
218}
219
220impl ControlFlow for () {
221 #[inline]
222 fn continuing() -> Self {}
223
224 #[inline]
225 fn should_break(&self) -> bool {
226 false
227 }
228}
229
230impl<C, E> ControlFlow for Result<C, E>
231where
232 C: ControlFlow,
233{
234 fn continuing() -> Self {
235 Ok(C::continuing())
236 }
237
238 fn should_break(&self) -> bool {
239 self.is_err()
240 }
241}
242
243pub trait QueryVisitor<T, C>
247where
248 T: IndexableNum,
249 C: ControlFlow,
250{
251 fn visit(&mut self, index_pos: usize) -> C;
253}
254
255impl<T, C, F> QueryVisitor<T, C> for F
256where
257 T: IndexableNum,
258 C: ControlFlow,
259 F: FnMut(usize) -> C,
260{
261 #[inline]
262 fn visit(&mut self, index_pos: usize) -> C {
263 self(index_pos)
264 }
265}
266
267pub trait NeighborVisitor<T, C>
269where
270 T: IndexableNum,
271 C: ControlFlow,
272{
273 fn visit(&mut self, index_pos: usize, dist_squared: T) -> C;
276}
277
278impl<T, C, F> NeighborVisitor<T, C> for F
279where
280 T: IndexableNum,
281 C: ControlFlow,
282 F: FnMut(usize, T) -> C,
283{
284 #[inline]
285 fn visit(&mut self, index_pos: usize, dist_squared: T) -> C {
286 self(index_pos, dist_squared)
287 }
288}
289
290#[macro_export]
291macro_rules! try_control {
292 ($e:expr) => {
293 match $e {
294 x => {
295 if x.should_break() {
296 return x;
297 }
298 }
299 }
300 };
301}