1use parry2d_f64::bounding_volume::BoundingVolume as _;
2use parry3d_f64::bounding_volume::BoundingVolume as _;
3
4use super::{Point, Vector};
5
6#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
8#[repr(C)]
9pub struct Aabb<const D: usize> {
10 pub min: Point<D>,
12
13 pub max: Point<D>,
15}
16
17impl<const D: usize> Aabb<D> {
18 pub fn contains(&self, point: impl Into<Point<D>>) -> bool {
20 let point = point.into();
21
22 let min = self
23 .min
24 .coords
25 .components
26 .into_iter()
27 .zip(point.coords.components);
28 for (min, p) in min {
29 if min > p {
30 return false;
31 }
32 }
33
34 let max = self
35 .max
36 .coords
37 .components
38 .into_iter()
39 .zip(point.coords.components);
40 for (max, p) in max {
41 if max < p {
42 return false;
43 }
44 }
45
46 true
47 }
48}
49
50impl Aabb<2> {
51 pub fn from_points(
55 points: impl IntoIterator<Item = impl Into<Point<2>>>,
56 ) -> Self {
57 let points: Vec<_> = points
58 .into_iter()
59 .map(|point| point.into().to_na())
60 .collect();
61 parry2d_f64::bounding_volume::Aabb::from_points(&points).into()
62 }
63
64 pub fn from_parry(aabb: parry2d_f64::bounding_volume::Aabb) -> Self {
66 Self {
67 min: aabb.mins.into(),
68 max: aabb.maxs.into(),
69 }
70 }
71
72 pub fn to_parry(self) -> parry2d_f64::bounding_volume::Aabb {
74 parry2d_f64::bounding_volume::Aabb {
75 mins: self.min.to_na(),
76 maxs: self.max.to_na(),
77 }
78 }
79
80 pub fn merged(&self, other: &Self) -> Self {
82 self.to_parry().merged(&other.to_parry()).into()
83 }
84}
85
86impl Aabb<3> {
87 pub fn from_points(
91 points: impl IntoIterator<Item = impl Into<Point<3>>>,
92 ) -> Self {
93 let points: Vec<_> = points
94 .into_iter()
95 .map(|point| point.into().to_na())
96 .collect();
97 parry3d_f64::bounding_volume::Aabb::from_points(&points).into()
98 }
99
100 pub fn from_parry(aabb: parry3d_f64::bounding_volume::Aabb) -> Self {
102 Self {
103 min: aabb.mins.into(),
104 max: aabb.maxs.into(),
105 }
106 }
107
108 pub fn to_parry(self) -> parry3d_f64::bounding_volume::Aabb {
110 parry3d_f64::bounding_volume::Aabb {
111 mins: self.min.to_na(),
112 maxs: self.max.to_na(),
113 }
114 }
115
116 pub fn vertices(&self) -> [Point<3>; 8] {
118 self.to_parry().vertices().map(Into::into)
119 }
120
121 pub fn center(&self) -> Point<3> {
123 self.to_parry().center().into()
124 }
125
126 pub fn size(&self) -> Vector<3> {
128 self.to_parry().extents().into()
129 }
130
131 pub fn include_point(self, point: &Point<3>) -> Self {
133 let mut aabb = self.to_parry();
134 aabb.take_point(point.to_na());
135
136 Self::from_parry(aabb)
137 }
138
139 pub fn merged(&self, other: &Self) -> Self {
141 self.to_parry().merged(&other.to_parry()).into()
142 }
143}
144
145impl From<parry2d_f64::bounding_volume::Aabb> for Aabb<2> {
146 fn from(aabb: parry2d_f64::bounding_volume::Aabb) -> Self {
147 Self::from_parry(aabb)
148 }
149}
150
151impl From<parry3d_f64::bounding_volume::Aabb> for Aabb<3> {
152 fn from(aabb: parry3d_f64::bounding_volume::Aabb) -> Self {
153 Self::from_parry(aabb)
154 }
155}
156
157#[cfg(test)]
158mod tests {
159 use super::Aabb;
160
161 #[test]
162 fn contains() {
163 let aabb = Aabb::<2>::from_points([[1., 1.], [3., 3.]]);
164
165 assert!(aabb.contains([2., 2.]));
166
167 assert!(!aabb.contains([0., 0.]));
168 assert!(!aabb.contains([4., 0.]));
169 assert!(!aabb.contains([4., 4.]));
170 assert!(!aabb.contains([0., 4.]));
171
172 assert!(!aabb.contains([2., 0.]));
173 assert!(!aabb.contains([2., 4.]));
174 assert!(!aabb.contains([0., 2.]));
175 assert!(!aabb.contains([4., 2.]));
176 }
177}