conspire/geometry/bbox/base/
mod.rs1#[cfg(test)]
2mod test;
3
4use crate::{
5 geometry::{Coordinate, bbox::BoundingBox},
6 math::{Scalar, Tensor},
7};
8use std::array::from_fn;
9
10impl<const D: usize> BoundingBox<D> {
11 pub fn minimum(&self) -> &Coordinate<D> {
12 &self.minimum
13 }
14 pub fn maximum(&self) -> &Coordinate<D> {
15 &self.maximum
16 }
17 pub fn overlaps(&self, other: &Self) -> bool {
18 (0..D).all(|d| self.minimum[d] <= other.maximum[d] && other.minimum[d] <= self.maximum[d])
19 }
20 pub fn longest_axis(&self) -> usize {
21 self.maximum
22 .iter()
23 .zip(self.minimum.iter())
24 .enumerate()
25 .map(|(i, (&max, &min))| (i, max - min))
26 .max_by(|(_, length_a), (_, length_b)| length_a.partial_cmp(length_b).unwrap())
27 .unwrap()
28 .0
29 }
30 pub fn shortest_axis(&self) -> usize {
31 self.maximum
32 .iter()
33 .zip(self.minimum.iter())
34 .enumerate()
35 .map(|(i, (&max, &min))| (i, max - min))
36 .min_by(|(_, length_a), (_, length_b)| length_a.partial_cmp(length_b).unwrap())
37 .unwrap()
38 .0
39 }
40}
41
42impl BoundingBox<3> {
43 pub fn overlaps_triangle(
44 &self,
45 a: &Coordinate<3>,
46 b: &Coordinate<3>,
47 c: &Coordinate<3>,
48 ) -> bool {
49 let center: [Scalar; 3] = from_fn(|k| (self.minimum[k] + self.maximum[k]) * 0.5);
50 let half: [Scalar; 3] = from_fn(|k| (self.maximum[k] - self.minimum[k]) * 0.5);
51 let v: [[Scalar; 3]; 3] = [a, b, c].map(|p| from_fn(|k| p[k] - center[k]));
52 let edges: [[Scalar; 3]; 3] = [
53 from_fn(|k| v[1][k] - v[0][k]),
54 from_fn(|k| v[2][k] - v[1][k]),
55 from_fn(|k| v[0][k] - v[2][k]),
56 ];
57 for k in 0..3 {
58 for e in &edges {
59 let axis = match k {
60 0 => [0.0, -e[2], e[1]],
61 1 => [e[2], 0.0, -e[0]],
62 _ => [-e[1], e[0], 0.0],
63 };
64 let radius = (0..3).map(|i| half[i] * axis[i].abs()).sum();
65 let projection: [Scalar; 3] = from_fn(|i| (0..3).map(|j| axis[j] * v[i][j]).sum());
66 let low = projection[0].min(projection[1]).min(projection[2]);
67 let high = projection[0].max(projection[1]).max(projection[2]);
68 if low > radius || high < -radius {
69 return false;
70 }
71 }
72 }
73 for k in 0..3 {
74 let low = v[0][k].min(v[1][k]).min(v[2][k]);
75 let high = v[0][k].max(v[1][k]).max(v[2][k]);
76 if low > half[k] || high < -half[k] {
77 return false;
78 }
79 }
80 let normal: [Scalar; 3] = from_fn(|k| {
81 let (i, j) = ((k + 1) % 3, (k + 2) % 3);
82 edges[0][i] * edges[1][j] - edges[0][j] * edges[1][i]
83 });
84 let radius = (0..3).map(|i| half[i] * normal[i].abs()).sum();
85 let distance: Scalar = (0..3).map(|i| normal[i] * v[0][i]).sum();
86 distance.abs() <= radius
87 }
88}