ncollide3d/bounding_volume/
aabb.rs
1use crate::bounding_volume::{BoundingSphere, BoundingVolume, HasBoundingVolume};
4use crate::math::{Isometry, Point, Vector, DIM};
5use crate::utils::IsometryOps;
6use na::{self, RealField};
7
8#[inline]
13pub fn aabb<N, G: ?Sized>(g: &G, m: &Isometry<N>) -> AABB<N>
14where
15 N: RealField + Copy,
16 G: HasBoundingVolume<N, AABB<N>>,
17{
18 g.bounding_volume(m)
19}
20
21#[inline]
26pub fn local_aabb<N, G: ?Sized>(g: &G) -> AABB<N>
27where
28 N: RealField + Copy,
29 G: HasBoundingVolume<N, AABB<N>>,
30{
31 g.local_bounding_volume()
32}
33
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36#[derive(Debug, PartialEq, Copy, Clone)]
37pub struct AABB<N: RealField + Copy> {
38 pub mins: Point<N>,
39 pub maxs: Point<N>,
40}
41
42impl<N: RealField + Copy> AABB<N> {
43 #[inline]
50 pub fn new(mins: Point<N>, maxs: Point<N>) -> AABB<N> {
51 AABB { mins, maxs }
52 }
53
54 #[inline]
58 pub fn new_invalid() -> Self {
59 Self::new(
60 Vector::repeat(N::max_value().unwrap()).into(),
61 Vector::repeat(-N::max_value().unwrap()).into(),
62 )
63 }
64
65 #[inline]
67 pub fn from_half_extents(center: Point<N>, half_extents: Vector<N>) -> Self {
68 Self::new(center - half_extents, center + half_extents)
69 }
70
71 pub fn from_points<'a, I>(pts: I) -> Self
73 where
74 I: IntoIterator<Item = &'a Point<N>>,
75 {
76 super::aabb_utils::local_point_cloud_aabb(pts)
77 }
78
79 #[inline]
81 #[deprecated(note = "use the `.mins` public field instead.")]
82 pub fn mins(&self) -> &Point<N> {
83 &self.mins
84 }
85
86 #[inline]
88 #[deprecated(note = "use the `.maxs` public field instead.")]
89 pub fn maxs(&self) -> &Point<N> {
90 &self.maxs
91 }
92
93 #[inline]
95 pub fn center(&self) -> Point<N> {
96 na::center(&self.mins, &self.maxs)
97 }
98
99 #[inline]
101 pub fn half_extents(&self) -> Vector<N> {
102 let half: N = na::convert(0.5);
103 (self.maxs - self.mins) * half
104 }
105
106 #[inline]
108 pub fn extents(&self) -> Vector<N> {
109 self.maxs - self.mins
110 }
111
112 pub fn take_point(&mut self, pt: Point<N>) {
114 self.mins = self.mins.coords.inf(&pt.coords).into();
115 self.maxs = self.maxs.coords.sup(&pt.coords).into();
116 }
117
118 #[inline]
120 pub fn transform_by(&self, m: &Isometry<N>) -> Self {
121 let ls_center = self.center();
122 let center = m * ls_center;
123 let ws_half_extents = m.absolute_transform_vector(&self.half_extents());
124
125 AABB::new(center + (-ws_half_extents), center + ws_half_extents)
126 }
127
128 #[inline]
130 pub fn bounding_sphere(&self) -> BoundingSphere<N> {
131 let center = self.center();
132 let rad = na::distance(&self.mins, &self.maxs);
133
134 BoundingSphere::new(center, rad)
135 }
136
137 #[inline]
138 pub fn contains_local_point(&self, point: &Point<N>) -> bool {
139 for i in 0..DIM {
140 if point[i] < self.mins[i] || point[i] > self.maxs[i] {
141 return false;
142 }
143 }
144
145 true
146 }
147}
148
149impl<N: RealField + Copy> BoundingVolume<N> for AABB<N> {
150 #[inline]
151 fn center(&self) -> Point<N> {
152 self.center()
153 }
154
155 #[inline]
156 fn intersects(&self, other: &AABB<N>) -> bool {
157 na::partial_le(&self.mins, &other.maxs) && na::partial_ge(&self.maxs, &other.mins)
158 }
159
160 #[inline]
161 fn contains(&self, other: &AABB<N>) -> bool {
162 na::partial_le(&self.mins, &other.mins) && na::partial_ge(&self.maxs, &other.maxs)
163 }
164
165 #[inline]
166 fn merge(&mut self, other: &AABB<N>) {
167 self.mins = self.mins.inf(&other.mins);
168 self.maxs = self.maxs.sup(&other.maxs);
169 }
170
171 #[inline]
172 fn merged(&self, other: &AABB<N>) -> AABB<N> {
173 AABB {
174 mins: self.mins.inf(&other.mins),
175 maxs: self.maxs.sup(&other.maxs),
176 }
177 }
178
179 #[inline]
180 fn loosen(&mut self, amount: N) {
181 assert!(
182 amount >= na::zero(),
183 "The loosening margin must be positive."
184 );
185 self.mins = self.mins + Vector::repeat(-amount);
186 self.maxs = self.maxs + Vector::repeat(amount);
187 }
188
189 #[inline]
190 fn loosened(&self, amount: N) -> AABB<N> {
191 assert!(
192 amount >= na::zero(),
193 "The loosening margin must be positive."
194 );
195 AABB {
196 mins: self.mins + Vector::repeat(-amount),
197 maxs: self.maxs + Vector::repeat(amount),
198 }
199 }
200
201 #[inline]
202 fn tighten(&mut self, amount: N) {
203 assert!(
204 amount >= na::zero(),
205 "The tightening margin must be positive."
206 );
207 self.mins = self.mins + Vector::repeat(amount);
208 self.maxs = self.maxs + Vector::repeat(-amount);
209 assert!(
210 na::partial_le(&self.mins, &self.maxs),
211 "The tightening margin is to large."
212 );
213 }
214
215 #[inline]
216 fn tightened(&self, amount: N) -> AABB<N> {
217 assert!(
218 amount >= na::zero(),
219 "The tightening margin must be positive."
220 );
221
222 AABB::new(
223 self.mins + Vector::repeat(amount),
224 self.maxs + Vector::repeat(-amount),
225 )
226 }
227}