1use crate::*;
26
27use std::marker::PhantomData;
28
29#[derive(Clone)]
32pub enum AABBTree3D<HB>
34where
35 HB: HasBoundingBox3D + Clone,
36{
37 Empty,
38 Leaf(AABBTree3DLeaf<HB>),
39 Branch(AABBTree3DBranch<HB>),
40}
41
42impl<HB> AABBTree3D<HB>
46where
47 HB: HasBoundingBox3D + Clone,
48{
49 pub fn new(data: Vec<HB>, maxdepth: usize, allowed_bucket_size: usize) -> Self {
50 Self::new_rec(data, maxdepth, allowed_bucket_size, 0)
51 }
52
53 pub fn any<'a>(&'a self, f: &dyn Fn(&HB) -> bool) -> bool {
54 match self {
55 Self::Empty => false,
56 Self::Leaf(leaf) => leaf.any(f),
57 Self::Branch(branch) => branch.any(f),
58 }
59 }
60
61 pub fn for_each_intersection_candidate<'a>(&'a self, line: &Line3D, f: &mut dyn FnMut(&HB)) {
62 match self {
63 Self::Empty => (),
64 Self::Leaf(leaf) => leaf.for_each_intersection_candidate(line, f),
65 Self::Branch(branch) => branch.for_each_intersection_candidate(line, f),
66 }
67 }
68
69 pub fn for_each_collision_candidate<'a>(&'a self, bb: &BoundingBox3D, f: &mut dyn FnMut(&HB)) {
70 match self {
71 Self::Empty => (),
72 Self::Leaf(leaf) => leaf.for_each_collision_candidate(bb, f),
73 Self::Branch(branch) => branch.for_each_collision_candidate(bb, f),
74 }
75 }
76
77 pub fn bb_colliding<'a>(&'a self, bb: &BoundingBox3D, result: &mut Vec<&'a HB>) {
78 match self {
79 Self::Empty => (),
80 Self::Leaf(leaf) => leaf.bb_colliding(bb, result),
81 Self::Branch(branch) => branch.bb_colliding(bb, result),
82 }
83 }
84
85 pub fn bb_crossing_x_value<'a>(&'a self, x: f64, result: &mut Vec<&'a HB>) {
86 match self {
87 Self::Empty => (),
88 Self::Leaf(leaf) => leaf.bb_crossing_x_value(x, result),
89 Self::Branch(branch) => branch.bb_crossing_x_value(x, result),
90 }
91 }
92
93 pub fn bb_crossing_y_value<'a>(&'a self, y: f64, result: &mut Vec<&'a HB>) {
94 match self {
95 Self::Empty => (),
96 Self::Leaf(leaf) => leaf.bb_crossing_y_value(y, result),
97 Self::Branch(branch) => branch.bb_crossing_y_value(y, result),
98 }
99 }
100
101 pub fn bb_crossing_z_value<'a>(&'a self, z: f64, result: &mut Vec<&'a HB>) {
102 match self {
103 Self::Empty => (),
104 Self::Leaf(leaf) => leaf.bb_crossing_z_value(z, result),
105 Self::Branch(branch) => branch.bb_crossing_z_value(z, result),
106 }
107 }
108
109 fn new_rec(data: Vec<HB>, maxdepth: usize, allowed_bucket_size: usize, depth: usize) -> Self {
110 match data.len() {
111 0 => AABBTree3D::Empty,
112 1 => {
113 let bb = Self::bb_of(&data).unwrap(); AABBTree3D::Leaf(AABBTree3DLeaf::new(data, bb))
115 }
116 _ => {
117 if depth >= maxdepth || data.len() <= allowed_bucket_size {
118 let bb = Self::bb_of(&data).unwrap(); AABBTree3D::Leaf(AABBTree3DLeaf::new(data, bb))
120 } else {
121 let comp = match depth % 3 {
122 0 => Compare::X,
123 1 => Compare::Y,
124 _ => Compare::Z,
125 };
126 let bb = Self::bb_of(&data).unwrap(); let center = bb.center_bb();
128
129 let dleft = data
130 .iter()
131 .cloned()
132 .filter(|x| Self::is_left_of(&comp, &x.bounding_box(), ¢er))
133 .collect::<Vec<_>>();
134 let dright = data
135 .iter()
136 .cloned()
137 .filter(|x| Self::is_right_of(&comp, &x.bounding_box(), ¢er))
138 .collect::<Vec<_>>();
139
140 if (dleft.len() == dright.len()) && dleft.len() == data.len() {
141 AABBTree3D::Leaf(AABBTree3DLeaf::new(data, bb))
142 } else {
143 let left = Box::new(Self::new_rec(
144 dleft,
145 maxdepth,
146 allowed_bucket_size,
147 depth + 1,
148 ));
149 let right = Box::new(Self::new_rec(
150 dright,
151 maxdepth,
152 allowed_bucket_size,
153 depth + 1,
154 ));
155
156 AABBTree3D::Branch(AABBTree3DBranch::new(left, right, bb))
157 }
158 }
159 }
160 }
161 }
162
163 fn is_left_of(comp: &Compare, bb: &BoundingBox3D, center: &Point3D) -> bool {
164 match comp {
165 Compare::X => bb.min_p().x() < center.x(),
166 Compare::Y => bb.min_p().y() < center.y(),
167 Compare::Z => bb.min_p().z() < center.z(),
168 }
169 }
170
171 fn is_right_of(comp: &Compare, bb: &BoundingBox3D, center: &Point3D) -> bool {
172 match comp {
173 Compare::X => bb.max_p().x() >= center.x(),
174 Compare::Y => bb.max_p().y() >= center.y(),
175 Compare::Z => bb.max_p().z() >= center.z(),
176 }
177 }
178
179 fn bb_of(data: &Vec<HB>) -> Result<BoundingBox3D> {
180 if data.len() == 0 {
181 return Err(ErrorKind::TooFewPoints);
182 }
183 let mut result = data[0].bounding_box();
184 for x in data.iter() {
185 result.consume(x.bounding_box());
186 }
187
188 Ok(result)
189 }
190}
191
192enum Compare {
195 X,
196 Y,
197 Z,
198}
199
200#[derive(Clone)]
201pub struct AABBTree3DLeaf<HB>
203where
204 HB: HasBoundingBox3D,
205{
206 data: Vec<HB>,
207 bb: BoundingBox3D,
208 _marker: PhantomData<HB>,
209}
210
211impl<HB> AABBTree3DLeaf<HB>
212where
213 HB: HasBoundingBox3D + Clone,
214{
215 pub fn new(data: Vec<HB>, bb: BoundingBox3D) -> Self {
216 AABBTree3DLeaf {
217 data,
218 bb,
219 _marker: PhantomData,
220 }
221 }
222
223 pub fn any<'a>(&'a self, f: &dyn Fn(&HB) -> bool) -> bool {
224 for x in self.data.iter() {
225 if f(x) {
226 return true;
228 }
229 }
230 false
231 }
232
233 pub fn for_each_intersection_candidate<'a>(&'a self, line: &Line3D, f: &mut dyn FnMut(&HB)) {
234 if intersection(line, &self.bb).is_none() {
235 return;
236 }
237 for x in self.data.iter() {
238 if intersection(line, &x.bounding_box()).is_some() {
239 f(x)
240 }
241 }
242 }
243
244 pub fn for_each_collision_candidate<'a>(&'a self, bb: &BoundingBox3D, f: &mut dyn FnMut(&HB)) {
245 if !self.bb.collides_with(bb) {
246 return;
247 }
248 for x in self.data.iter() {
249 if x.bounding_box().collides_with(bb) {
250 f(x)
251 }
252 }
253 }
254
255 pub fn bb_colliding<'a>(&'a self, bb: &BoundingBox3D, result: &mut Vec<&'a HB>) {
256 if self.bb.collides_with(bb) {
257 for x in self.data.iter() {
258 if x.bounding_box().collides_with(bb) {
259 result.push(x)
260 }
261 }
262 }
263 }
264
265 pub fn bb_crossing_x_value<'a>(&'a self, x: f64, result: &mut Vec<&'a HB>) {
266 if self.bb.crossing_x_value(x) {
267 for d in self.data.iter() {
268 if d.bounding_box().crossing_x_value(x) {
269 result.push(d)
270 }
271 }
272 }
273 }
274
275 pub fn bb_crossing_y_value<'a>(&'a self, y: f64, result: &mut Vec<&'a HB>) {
276 if self.bb.crossing_y_value(y) {
277 for d in self.data.iter() {
278 if d.bounding_box().crossing_y_value(y) {
279 result.push(d)
280 }
281 }
282 }
283 }
284
285 pub fn bb_crossing_z_value<'a>(&'a self, z: f64, result: &mut Vec<&'a HB>) {
286 if self.bb.crossing_z_value(z) {
287 for d in self.data.iter() {
288 if d.bounding_box().crossing_z_value(z) {
289 result.push(d)
290 }
291 }
292 }
293 }
294}
295
296#[derive(Clone)]
299pub struct AABBTree3DBranch<HB>
301where
302 HB: HasBoundingBox3D + Clone,
303{
304 left: Box<AABBTree3D<HB>>,
305 right: Box<AABBTree3D<HB>>,
306 bb: BoundingBox3D,
307 _marker: PhantomData<HB>,
308}
309
310impl<HB> AABBTree3DBranch<HB>
311where
312 HB: HasBoundingBox3D + Clone,
313{
314 pub fn new(left: Box<AABBTree3D<HB>>, right: Box<AABBTree3D<HB>>, bb: BoundingBox3D) -> Self {
315 AABBTree3DBranch {
316 left,
317 right,
318 bb,
319 _marker: PhantomData,
320 }
321 }
322
323 pub fn any<'a>(&'a self, f: &dyn Fn(&HB) -> bool) -> bool {
324 self.left.any(f) || self.right.any(f)
325 }
326
327 pub fn for_each_intersection_candidate<'a>(&'a self, line: &Line3D, f: &mut dyn FnMut(&HB)) {
328 if intersection(line, &self.bb).is_none() {
329 return;
330 }
331
332 self.left.for_each_intersection_candidate(line, f);
333 self.right.for_each_intersection_candidate(line, f);
334 }
335
336 pub fn for_each_collision_candidate<'a>(&'a self, bb: &BoundingBox3D, f: &mut dyn FnMut(&HB)) {
337 if !self.bb.collides_with(bb) {
338 return;
339 }
340
341 self.left.for_each_collision_candidate(bb, f);
342 self.right.for_each_collision_candidate(bb, f);
343 }
344
345 pub fn bb_colliding<'a>(&'a self, bb: &BoundingBox3D, result: &mut Vec<&'a HB>) {
346 if self.bb.collides_with(bb) {
347 self.left.bb_colliding(bb, result);
348 self.right.bb_colliding(bb, result);
349 }
350 }
351
352 pub fn bb_crossing_x_value<'a>(&'a self, x: f64, result: &mut Vec<&'a HB>) {
353 if self.bb.crossing_x_value(x) {
354 self.left.bb_crossing_x_value(x, result);
355 self.right.bb_crossing_x_value(x, result);
356 }
357 }
358
359 pub fn bb_crossing_y_value<'a>(&'a self, y: f64, result: &mut Vec<&'a HB>) {
360 if self.bb.crossing_y_value(y) {
361 self.left.bb_crossing_y_value(y, result);
362 self.right.bb_crossing_y_value(y, result);
363 }
364 }
365
366 pub fn bb_crossing_z_value<'a>(&'a self, z: f64, result: &mut Vec<&'a HB>) {
367 if self.bb.crossing_z_value(z) {
368 self.left.bb_crossing_z_value(z, result);
369 self.right.bb_crossing_z_value(z, result);
370 }
371 }
372}
373
374impl<HB> IsColliderContainer3D for AABBTree3D<HB>
377where
378 HB: Clone + HasColliders3D + Sized,
379{
380 fn any_element_collides_with_collider(&self, other: &dyn HasColliders3D) -> bool {
381 let mut any_collides = false;
382 self.for_each_collision_candidate(&other.bounding_box(), &mut |candidate| {
383 if !any_collides {
384 any_collides = candidate.collides_with(other);
385 }
386 });
387
388 any_collides
389 }
390
391 fn any_element_collides_with_bounding(&self, other: &dyn HasBoundingBox3D) -> bool {
392 let mut any_collides = false;
393 self.for_each_collision_candidate(&other.bounding_box(), &mut |_candidate| {
394 any_collides = true;
395 });
396
397 any_collides
398 }
399}