AABB.hpp
Go to the documentation of this file.
1 /*
2  * Original work Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
3  * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 
22 #ifndef PLAYRHO_COLLISION_AABB_HPP
23 #define PLAYRHO_COLLISION_AABB_HPP
24 
27 
31 #include <array>
32 #include <algorithm>
33 #include <functional>
34 
35 namespace playrho {
36 
37 namespace detail {
38 
39 template <std::size_t N> struct RayCastInput;
40 
56 template <std::size_t N>
57 struct AABB
58 {
61 
65  PLAYRHO_CONSTEXPR inline AABB() = default;
66 
74  template<typename... Tail>
75  PLAYRHO_CONSTEXPR inline AABB(std::enable_if_t<sizeof...(Tail)+1 == N, LengthInterval> head,
76  Tail... tail) noexcept:
77  ranges{head, LengthInterval(tail)...}
78  {
79  // Intentionally empty.
80  }
81 
88  PLAYRHO_CONSTEXPR inline explicit AABB(const Location p) noexcept
89  {
90  for (auto i = decltype(N){0}; i < N; ++i)
91  {
92  ranges[i] = LengthInterval{p[i]};
93  }
94  }
95 
99  PLAYRHO_CONSTEXPR inline AABB(const Location a, const Location b) noexcept
100  {
101  for (auto i = decltype(N){0}; i < N; ++i)
102  {
103  ranges[i] = LengthInterval{a[i], b[i]};
104  }
105  }
106 
108  LengthInterval ranges[N];
109 };
110 
114 template <std::size_t N>
115 PLAYRHO_CONSTEXPR inline bool operator== (const AABB<N>& lhs, const AABB<N>& rhs) noexcept
116 {
117  for (auto i = decltype(N){0}; i < N; ++i)
118  {
119  if (lhs.ranges[i] != rhs.ranges[i])
120  {
121  return false;
122  }
123  }
124  return true;
125 }
126 
130 template <std::size_t N>
131 PLAYRHO_CONSTEXPR inline bool operator!= (const AABB<N>& lhs, const AABB<N>& rhs) noexcept
132 {
133  return !(lhs == rhs);
134 }
135 
138 template <std::size_t N>
139 inline bool operator< (const AABB<N>& lhs, const AABB<N>& rhs) noexcept
140 {
141  return std::lexicographical_compare(cbegin(lhs.ranges), cend(lhs.ranges),
142  cbegin(rhs.ranges), cend(rhs.ranges),
143  std::less<LengthInterval>{});
144 }
145 
148 template <std::size_t N>
149 inline bool operator<= (const AABB<N>& lhs, const AABB<N>& rhs) noexcept
150 {
151  const auto lhsEnd = cend(lhs.ranges);
152  const auto rhsEnd = cend(rhs.ranges);
153  const auto diff = std::mismatch(cbegin(lhs.ranges), lhsEnd,
154  cbegin(rhs.ranges), rhsEnd);
155  return (std::get<0>(diff) == lhsEnd) || (*std::get<0>(diff) < *std::get<1>(diff));
156 }
157 
160 template <std::size_t N>
161 inline bool operator> (const AABB<N>& lhs, const AABB<N>& rhs) noexcept
162 {
163  return std::lexicographical_compare(cbegin(lhs.ranges), cend(lhs.ranges),
164  cbegin(rhs.ranges), cend(rhs.ranges),
165  std::greater<LengthInterval>{});
166 }
167 
170 template <std::size_t N>
171 inline bool operator>= (const AABB<N>& lhs, const AABB<N>& rhs) noexcept
172 {
173  const auto lhsEnd = cend(lhs.ranges);
174  const auto rhsEnd = cend(rhs.ranges);
175  const auto diff = std::mismatch(cbegin(lhs.ranges), lhsEnd,
176  cbegin(rhs.ranges), rhsEnd);
177  return (std::get<0>(diff) == lhsEnd) || (*std::get<0>(diff) > *std::get<1>(diff));
178 }
179 
183 template <std::size_t N>
184 PLAYRHO_CONSTEXPR inline bool TestOverlap(const AABB<N>& a, const AABB<N>& b) noexcept
185 {
186  for (auto i = decltype(N){0}; i < N; ++i)
187  {
188  if (!IsIntersecting(a.ranges[i], b.ranges[i]))
189  {
190  return false;
191  }
192  }
193  return true;
194 }
195 
197 template <std::size_t N>
198 PLAYRHO_CONSTEXPR inline AABB<N> GetIntersectingAABB(const AABB<N>& a, const AABB<N>& b) noexcept
199 {
200  auto result = AABB<N>{};
201  for (auto i = decltype(N){0}; i < N; ++i)
202  {
203  result.ranges[i] = GetIntersection(a.ranges[i], b.ranges[i]);
204  }
205  return result;
206 }
207 
210 template <std::size_t N>
212 {
213  auto result = Vector<Length, N>{};
214  for (auto i = decltype(N){0}; i < N; ++i)
215  {
216  result[i] = GetCenter(aabb.ranges[i]);
217  }
218  return result;
219 }
220 
223 template <std::size_t N>
225 {
226  auto result = Vector<Length, N>{};
227  for (auto i = decltype(N){0}; i < N; ++i)
228  {
229  result[i] = GetSize(aabb.ranges[i]);
230  }
231  return result;
232 }
233 
236 template <std::size_t N>
238 {
239  PLAYRHO_CONSTEXPR const auto RealInverseOfTwo = Real{1} / Real{2};
240  return GetDimensions(aabb) * RealInverseOfTwo;
241 }
242 
251 template <std::size_t N>
252 PLAYRHO_CONSTEXPR inline bool Contains(const AABB<N>& a, const AABB<N>& b) noexcept
253 {
254  for (auto i = decltype(N){0}; i < N; ++i)
255  {
256  if (!IsEntirelyEnclosing(a.ranges[i], b.ranges[i]))
257  {
258  return false;
259  }
260  }
261  return true;
262 }
263 
266 template <std::size_t N>
267 PLAYRHO_CONSTEXPR inline AABB<N>& Include(AABB<N>& var, const Vector<Length, N>& value) noexcept
268 {
269  for (auto i = decltype(N){0}; i < N; ++i)
270  {
271  var.ranges[i].Include(value[i]);
272  }
273  return var;
274 }
275 
281 template <std::size_t N>
282 PLAYRHO_CONSTEXPR inline AABB<N>& Include(AABB<N>& var, const AABB<N>& val) noexcept
283 {
284  for (auto i = decltype(N){0}; i < N; ++i)
285  {
286  var.ranges[i].Include(val.ranges[i]);
287  }
288  return var;
289 }
290 
292 template <std::size_t N>
293 PLAYRHO_CONSTEXPR inline AABB<N>& Move(AABB<N>& var, const Vector<Length, N> value) noexcept
294 {
295  for (auto i = decltype(N){0}; i < N; ++i)
296  {
297  var.ranges[i].Move(value[i]);
298  }
299  return var;
300 }
301 
304 template <std::size_t N>
305 PLAYRHO_CONSTEXPR inline AABB<N>& Fatten(AABB<N>& var, const NonNegative<Length> amount) noexcept
306 {
307  for (auto i = decltype(N){0}; i < N; ++i)
308  {
309  var.ranges[i].ExpandEqually(amount);
310  }
311  return var;
312 }
313 
317 template <std::size_t N>
319 {
320  for (auto i = decltype(N){0}; i < N; ++i)
321  {
322  aabb.ranges[i].Expand(displacement[i]);
323  }
324  return aabb;
325 }
326 
329 template <std::size_t N>
331 {
332  return Fatten(aabb, amount);
333 }
334 
337 template <std::size_t N>
339 {
340  return Move(aabb, value);
341 }
342 
345 template <std::size_t N>
347 {
348  return Include(a, b);
349 }
350 
353 template <std::size_t N>
355 {
356  auto result = Vector<Length, N>{};
357  for (auto i = decltype(N){0}; i < N; ++i)
358  {
359  result[i] = aabb.ranges[i].GetMin();
360  }
361  return result;
362 }
363 
366 template <std::size_t N>
368 {
369  auto result = Vector<Length, N>{};
370  for (auto i = decltype(N){0}; i < N; ++i)
371  {
372  result[i] = aabb.ranges[i].GetMax();
373  }
374  return result;
375 }
376 
378 template <std::size_t N>
379 inline ::std::ostream& operator<< (::std::ostream& os, const AABB<N>& value)
380 {
381  os << "{";
382  auto multiple = false;
383  for (const auto& range: value.ranges)
384  {
385  if (multiple)
386  {
387  os << ',';
388  }
389  else
390  {
391  multiple = true;
392  }
393  os << range;
394  }
395  os << "}";
396  return os;
397 }
398 
399 } // namespace detail
400 
401 namespace d2 {
402 
403 class Shape;
404 class Fixture;
405 class Body;
406 class Contact;
407 class DistanceProxy;
408 struct Transformation;
409 
410 using detail::TestOverlap;
411 using detail::Contains;
412 
416 
422 PLAYRHO_CONSTEXPR inline Length GetPerimeter(const AABB& aabb) noexcept
423 {
424  return (GetSize(aabb.ranges[0]) + GetSize(aabb.ranges[1])) * 2;
425 }
426 
435 AABB ComputeAABB(const DistanceProxy& proxy, const Transformation& xf) noexcept;
436 
446 AABB ComputeAABB(const DistanceProxy& proxy,
447  const Transformation& xfm0, const Transformation& xfm1) noexcept;
448 
451 AABB ComputeAABB(const Shape& shape, const Transformation& xf) noexcept;
452 
457 AABB ComputeAABB(const Fixture& fixture) noexcept;
458 
461 AABB ComputeAABB(const Body& body);
462 
467 AABB ComputeIntersectingAABB(const Fixture& fA, ChildCounter iA,
468  const Fixture& fB, ChildCounter iB) noexcept;
469 
472 AABB ComputeIntersectingAABB(const Contact& contact);
473 
476 AABB GetAABB(const playrho::detail::RayCastInput<2>& input) noexcept;
477 
478 } // namespace d2
479 
482 template <>
484 {
485  return d2::AABB{LengthInterval{GetInvalid<Length>()}, LengthInterval{GetInvalid<Length>()}};
486 }
487 
488 } // namespace playrho
489 
490 #endif // PLAYRHO_COLLISION_AABB_HPP