1use crate::{Scalar, VecN};
2
3pub trait Aabb: Sized {
5 type Vector: VecN;
7 const ORIGIN_ZERO_SIZE: Self;
9 fn origin_dim(&self, dim: usize) -> <Self::Vector as VecN>::Scalar;
11 fn origin_dim_mut(&mut self, dim: usize) -> &mut <Self::Vector as VecN>::Scalar;
13 fn size_dim(&self, dim: usize) -> <Self::Vector as VecN>::Scalar;
15 fn size_dim_mut(&mut self, dim: usize) -> &mut <Self::Vector as VecN>::Scalar;
17 fn set_origin_dim(&mut self, dim: usize, val: <Self::Vector as VecN>::Scalar) {
19 *self.origin_dim_mut(dim) = val;
20 }
21 fn set_size_dim(&mut self, dim: usize, val: <Self::Vector as VecN>::Scalar) {
23 *self.size_dim_mut(dim) = val;
24 }
25 fn end_dim(&self, dim: usize) -> <Self::Vector as VecN>::Scalar {
27 self.origin_dim(dim) + self.size_dim(dim)
28 }
29 fn center_dim(&self, dim: usize) -> <Self::Vector as VecN>::Scalar {
31 self.origin_dim(dim) + self.size_dim(dim) / <Self::Vector as VecN>::Scalar::TWO
32 }
33 fn center(&self) -> Self::Vector {
35 let mut v = Self::Vector::ZERO;
36 for i in 0..Self::Vector::N {
37 v.set_dim(i, self.center_dim(i));
38 }
39 v
40 }
41 fn contains(&self, v: Self::Vector) -> bool {
43 for i in 0..Self::Vector::N {
44 let d = v.dim(i);
45 let origin = self.origin_dim(i);
46 if d < origin || d > origin + self.size_dim(i) {
47 return false;
48 }
49 }
50 true
51 }
52 fn bounding<I>(iter: I) -> Option<Self>
54 where
55 I: IntoIterator<Item = Self::Vector>,
56 Self::Vector: Clone,
57 {
58 let mut iter = iter.into_iter();
59 let mut min = iter.next()?;
60 let mut max = min.clone();
61 for v in iter {
62 for i in 0..Self::Vector::N {
63 let d = v.dim(i);
64 if d < min.dim(i) {
65 min.set_dim(i, d);
66 } else if d > max.dim(i) {
67 max.set_dim(i, d);
68 }
69 }
70 }
71 let mut res = Self::ORIGIN_ZERO_SIZE;
72 for i in 0..Self::Vector::N {
73 let min = min.dim(i);
74 res.set_origin_dim(i, min);
75 res.set_size_dim(i, max.dim(i) - min);
76 }
77 Some(res)
78 }
79}
80
81impl<T, const N: usize> Aabb for [[T; N]; 2]
82where
83 T: Scalar,
84{
85 type Vector = [T; N];
86 const ORIGIN_ZERO_SIZE: Self = [[<Self::Vector as VecN>::Scalar::ZERO; N]; 2];
87 fn origin_dim(&self, dim: usize) -> <Self::Vector as VecN>::Scalar {
88 self[0][dim]
89 }
90 fn origin_dim_mut(&mut self, dim: usize) -> &mut <Self::Vector as VecN>::Scalar {
91 &mut self[0][dim]
92 }
93 fn size_dim(&self, dim: usize) -> <Self::Vector as VecN>::Scalar {
94 self[1][dim]
95 }
96 fn size_dim_mut(&mut self, dim: usize) -> &mut <Self::Vector as VecN>::Scalar {
97 &mut self[1][dim]
98 }
99}
100
101macro_rules! aabb_impl {
102 ($($size:literal),* $(,)?) => {
103 $(
104 impl<T> Aabb for [T; $size * 2]
105 where
106 T: Scalar,
107 {
108 type Vector = [T; $size];
109 const ORIGIN_ZERO_SIZE: Self = [<Self::Vector as VecN>::Scalar::ZERO; $size * 2];
110 fn origin_dim(&self, dim: usize) -> <Self::Vector as VecN>::Scalar {
111 self[dim]
112 }
113 fn origin_dim_mut(&mut self, dim: usize) -> &mut <Self::Vector as VecN>::Scalar {
114 &mut self[dim]
115 }
116 fn size_dim(&self, dim: usize) -> <Self::Vector as VecN>::Scalar {
117 self[Self::Vector::N + dim]
118 }
119 fn size_dim_mut(&mut self, dim: usize) -> &mut <Self::Vector as VecN>::Scalar {
120 &mut self[Self::Vector::N + dim]
121 }
122 }
123 )*
124 };
125}
126
127aabb_impl!(1, 2, 3, 4, 5, 6, 7, 8);
128
129macro_rules! dim_trait {
130 (
131 $doc:literal,
132 $trait:ident,
133 $get_origin:ident,
134 $get_origin_mut:ident,
135 $set_origin:ident,
136 $get_size:ident,
137 $get_size_mut:ident,
138 $set_size:ident,
139 $get_end:ident,
140 $index:literal
141 ) => {
142 #[doc = $doc]
143 pub trait $trait: Aabb {
144 fn $get_origin(&self) -> <Self::Vector as VecN>::Scalar;
146 fn $get_origin_mut(&mut self) -> &mut <Self::Vector as VecN>::Scalar;
148 fn $get_size(&self) -> <Self::Vector as VecN>::Scalar;
150 fn $get_size_mut(&mut self) -> &mut <Self::Vector as VecN>::Scalar;
152 fn $set_origin(&mut self, x: <Self::Vector as VecN>::Scalar) {
154 *self.$get_origin_mut() = x;
155 }
156 fn $set_size(&mut self, x: <Self::Vector as VecN>::Scalar) {
158 *self.$get_size_mut() = x;
159 }
160 fn $get_end(&self) -> <Self::Vector as VecN>::Scalar {
162 self.end_dim($index)
163 }
164 }
165
166 impl<A> $trait for A
167 where
168 A: Aabb,
169 {
170 fn $get_origin(&self) -> <Self::Vector as VecN>::Scalar {
171 self.origin_dim($index)
172 }
173 fn $get_origin_mut(&mut self) -> &mut <Self::Vector as VecN>::Scalar {
174 self.origin_dim_mut($index)
175 }
176 fn $get_size(&self) -> <Self::Vector as VecN>::Scalar {
177 self.size_dim($index)
178 }
179 fn $get_size_mut(&mut self) -> &mut <Self::Vector as VecN>::Scalar {
180 self.size_dim_mut($index)
181 }
182 }
183 };
184}
185
186dim_trait!(
187 "Trait for axis-aligned bounding boxes with a width",
188 XAabb,
189 left,
190 left_mut,
191 set_left,
192 width,
193 width_mut,
194 set_width,
195 right,
196 0
197);
198dim_trait!(
199 "Trait for axis-aligned bounding boxes with a height",
200 YAabb,
201 top,
202 top_mut,
203 set_top,
204 height,
205 height_mut,
206 set_height,
207 bottom,
208 1
209);
210dim_trait!(
211 "Trait for axis-aligned bounding boxes with a depth",
212 ZAabb,
213 back,
214 back_mut,
215 set_back,
216 depth,
217 depth_mut,
218 set_depth,
219 front,
220 2
221);