olp-cpp-sdk  1.22.0
AlignedBox.h
1 /*
2  * Copyright (C) 2019-2021 HERE Europe B.V.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  * License-Filename: LICENSE
18  */
19 
20 #pragma once
21 
22 #include <array>
23 #include <limits>
24 
25 #include <olp/core/math/Vector.h>
26 
27 namespace olp {
28 namespace math {
41 template <typename T,
42  int IntegerBits = std::is_integral<T>::value ? sizeof(T) * 8 : 0,
43  bool IsSigned = std::numeric_limits<T>::is_signed>
44 struct OverflowTrait {
46  using Type = T;
47 };
48 
50 template <typename T>
53  using Type = int16_t;
54 };
55 
57 template <typename T>
60  using Type = uint16_t;
61 };
62 
64 template <typename T>
67  using Type = int32_t;
68 };
69 
71 template <typename T>
74  using Type = uint32_t;
75 };
76 
78 template <typename T>
81  using Type = int64_t;
82 };
83 
85 template <typename T>
88  using Type = uint64_t;
89 };
90 
97 template <typename T, unsigned int N>
98 class AlignedBox {
99  public:
101  static const unsigned int numCorners = 1 << N;
103  static const unsigned int dimensions = N;
104 
106  using ValueType = T;
110  using VectorType = Vector<ValueType, N>;
112  using OverflowVectorType = Vector<OverflowType, N>;
113 
116  typename std::array<VectorType,
117  numCorners>;
118 
124  AlignedBox();
125 
135  AlignedBox(const VectorType& min, const VectorType& max);
136 
143  template <typename OtherT>
144  AlignedBox(const AlignedBox<OtherT, N>& other);
145 
149  void Reset();
150 
160  void Reset(const VectorType& min, const VectorType& max);
161 
167  bool Empty() const;
168 
176  VectorType Center() const;
177 
188  VectorType Size() const;
189 
197  const VectorType& Minimum() const;
198 
206  const VectorType& Maximum() const;
207 
226  bool Contains(const VectorType& point, T epsilon = T()) const;
227 
235  bool Contains(const AlignedBox& box) const;
236 
247  bool Intersects(const AlignedBox& box) const;
248 
258  VectorType NearestPoint(const VectorType& point) const;
259 
271  ValueType Distance(const VectorType& point) const;
272 
284  ValueType Distance2(const VectorType& point) const;
285 
291  bool operator==(const AlignedBox& box) const;
292 
298  bool operator!=(const AlignedBox& box) const;
299 
300  private:
301  template <typename U, unsigned int X>
302  friend class AlignedBox;
303 
305  VectorType minimum_;
307  VectorType maximum_;
308 };
309 
310 #ifndef NDEBUG
311 template <typename T>
312 bool CheckAddOperationOverflow(T a, T b) {
313  return ((a > 0) && (b > 0) && (a > (std::numeric_limits<T>::max() - b))) ||
314  ((a < 0) && (b < 0) && (a < (std::numeric_limits<T>::min() - b)));
315 }
316 #endif
317 
319 using AlignedBox3d =
320  AlignedBox<double, 3>;
321 
322 template <typename T, unsigned int N>
324  : minimum_(std::numeric_limits<T>::max()),
325  maximum_(std::numeric_limits<T>::lowest()) {}
326 
327 template <typename T, unsigned int N>
328 template <typename OtherT>
330  : minimum_(other.min()), maximum_(other.max()) {}
331 
332 template <typename T, unsigned int N>
334  : minimum_(min), maximum_(max) {}
335 
336 template <typename T, unsigned int N>
338  minimum_ = VectorType(std::numeric_limits<T>::max());
339  maximum_ = VectorType(std::numeric_limits<T>::lowest());
340 }
341 
342 template <typename T, unsigned int N>
343 void AlignedBox<T, N>::Reset(const VectorType& min, const VectorType& max) {
344  minimum_ = min;
345  maximum_ = max;
346 }
347 
348 template <typename T, unsigned int N>
350 #ifndef NDEBUG
351  // Checks for possible 64-bit integer overflows or underflows.
352  if (std::numeric_limits<OverflowType>::is_integer &&
353  sizeof(OverflowType) * 8 == 64) {
354  for (unsigned dim = 0; dim < dimensions; ++dim) {
355  if (CheckAddOperationOverflow<OverflowType>(maximum_[dim],
356  minimum_[dim])) {
357  // DEBUG_ASSERT( false );
358  return VectorType(0);
359  }
360  }
361  }
362 #endif
363 
364  return VectorType(
365  (OverflowVectorType(maximum_) + OverflowVectorType(minimum_)) /
366  OverflowVectorType(2));
367 }
368 
369 template <typename T, unsigned int N>
371  Vector3<bool> result = maximum_.LessThan(minimum_);
372  return result.x || result.y || result.z;
373 }
374 
375 template <typename T, unsigned int N>
377  return Empty() ? VectorType(0) : maximum_ - minimum_;
378 }
379 
380 template <typename T, unsigned int N>
382  return minimum_;
383 }
384 
385 template <typename T, unsigned int N>
387  return maximum_;
388 }
389 
390 template <typename T, unsigned int N>
391 bool AlignedBox<T, N>::Contains(const VectorType& point, T epsilon) const {
392  if (Empty()) {
393  return false;
394  }
395 
396  for (unsigned dim = 0; dim < dimensions; dim++) {
397  if (minimum_[dim] - epsilon > point[dim] ||
398  maximum_[dim] + epsilon < point[dim])
399  return false;
400  }
401 
402  return true;
403 }
404 
405 template <typename T, unsigned int N>
406 bool AlignedBox<T, N>::Contains(const AlignedBox& box) const {
407  if (Empty()) {
408  return false;
409  }
410 
411  for (unsigned dim = 0; dim < dimensions; ++dim) {
412  if (box.minimum_[dim] < minimum_[dim] ||
413  box.maximum_[dim] > maximum_[dim]) {
414  return false;
415  }
416  }
417 
418  return true;
419 }
420 
421 template <typename T, unsigned int N>
422 bool AlignedBox<T, N>::Intersects(const AlignedBox& box) const {
423  if (Empty()) {
424  return false;
425  }
426 
427  const VectorType& otherMin = box.Minimum();
428  const VectorType& otherMax = box.Maximum();
429  for (unsigned dim = 0; dim < dimensions; dim++) {
430  if ((maximum_[dim] < otherMin[dim]) || (minimum_[dim] > otherMax[dim]))
431  return false;
432  }
433 
434  return true;
435 }
436 
437 template <typename T, unsigned int N>
438 auto AlignedBox<T, N>::Distance(const VectorType& point) const -> ValueType {
439  return static_cast<ValueType>(sqrt(distance2(point)));
440 }
441 
442 template <typename T, unsigned int N>
443 auto AlignedBox<T, N>::Distance2(const VectorType& point) const -> ValueType {
444  T distance2 = 0;
445  for (unsigned dim = 0; dim < dimensions; dim++) {
446  if (point[dim] < minimum_[dim]) {
447  T dimDistance = minimum_[dim] - point[dim];
448  distance2 += dimDistance * dimDistance;
449  } else if (point[dim] > maximum_[dim]) {
450  T dimDistance = point[dim] - maximum_[dim];
451  distance2 += dimDistance * dimDistance;
452  }
453  }
454 
455  return distance2;
456 }
457 
458 template <typename T, unsigned int N>
459 bool AlignedBox<T, N>::operator==(const AlignedBox& box) const {
460  //
461  // If either box is empty, checks which ones are
462  // empty.
463  //
464  bool thisEmpty = Empty();
465  bool otherEmpty = box.Empty();
466  if (thisEmpty || otherEmpty) {
467  return thisEmpty == otherEmpty;
468  }
469 
470  return minimum_ == box.Minimum() && maximum_ == box.Maximum();
471 }
472 
473 template <typename T, unsigned int N>
474 bool AlignedBox<T, N>::operator!=(const AlignedBox& box) const {
475  return !(*this == box);
476 }
477 
478 } // namespace math
479 } // namespace olp
The aligned bounding-box implementation.
Definition: AlignedBox.h:98
ValueType Distance(const VectorType &point) const
Computes the distance from a point to the box.
Definition: AlignedBox.h:438
bool Intersects(const AlignedBox &box) const
Tests whether the box intersects another box.
Definition: AlignedBox.h:422
bool operator==(const AlignedBox &box) const
Checks whether two boxes are equal.
Definition: AlignedBox.h:459
ValueType Distance2(const VectorType &point) const
Computes the squared distance from a point to the box.
Definition: AlignedBox.h:443
VectorType Center() const
Gets the center point of the box.
Definition: AlignedBox.h:349
typename OverflowTrait< T >::Type OverflowType
An alias for the overflow trait.
Definition: AlignedBox.h:108
Vector< OverflowType, N > OverflowVectorType
An alias for the overflow vector type.
Definition: AlignedBox.h:112
bool Empty() const
Tests whether the box is empty.
Definition: AlignedBox.h:370
const VectorType & Minimum() const
Gets the box minimum corner point.
Definition: AlignedBox.h:381
void Reset()
Resets the box to empty.
Definition: AlignedBox.h:337
bool operator!=(const AlignedBox &box) const
Checks whether two boxes are not equal.
Definition: AlignedBox.h:474
typename std::array< VectorType, numCorners > CornerArrayType
An alias for the corner points array type.
Definition: AlignedBox.h:117
VectorType Size() const
Gets the size of the box.
Definition: AlignedBox.h:376
T ValueType
An alias for the box value type.
Definition: AlignedBox.h:106
Vector< ValueType, N > VectorType
An alias for the vector type of the box.
Definition: AlignedBox.h:110
bool Contains(const VectorType &point, T epsilon=T()) const
Tests whether the box contains a point.
Definition: AlignedBox.h:391
CornerArrayType Corners() const
Gets the corner points of the box.
const VectorType & Maximum() const
Gets the box maximum corner point.
Definition: AlignedBox.h:386
VectorType NearestPoint(const VectorType &point) const
Computes the nearest point on the box to a point.
Rules all the other namespaces.
Definition: AppleSignInProperties.h:24
A specialization for 16-bit unsigned integers.
Definition: AlignedBox.h:72
uint32_t Type
An alias for uint32_t integer type.
Definition: AlignedBox.h:74
A specialization for 16-bit signed integers.
Definition: AlignedBox.h:65
int32_t Type
An alias for the int32_t integer type.
Definition: AlignedBox.h:67
A specialization for 32-bit unsigned integers.
Definition: AlignedBox.h:86
uint64_t Type
An alias for the uint64_t integer type.
Definition: AlignedBox.h:88
A specialization for 32-bit signed integers.
Definition: AlignedBox.h:79
int64_t Type
An alias for the int64_t integer type.
Definition: AlignedBox.h:81
A specialization for 8-bit unsigned integers.
Definition: AlignedBox.h:58
uint16_t Type
An alias for the uint16_t integer type.
Definition: AlignedBox.h:60
A specialization for 8-bit signed integers.
Definition: AlignedBox.h:51
int16_t Type
An alias for the int16_t integer type.
Definition: AlignedBox.h:53
Maps an integer type to the one that can handle arithmetic overflows.
Definition: AlignedBox.h:44
T Type
An alias for the integer type.
Definition: AlignedBox.h:46
Represents 3D vectors and points.
Definition: Vector.h:86
Vector3< bool > LessThan(Vector3< T > const &v) const
Checks whether the parameters of one vector are less than the parameters of the other vector.
Definition: Vector.h:142
T z
The Z component of the vector.
Definition: Vector.h:151
T y
The Y component of the vector.
Definition: Vector.h:149
T x
The X component of the vector.
Definition: Vector.h:147