AABBtree  0.0.1
A C++ non-recursive ND AABB tree
Loading...
Searching...
No Matches
Box.hxx
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
2 * Copyright (c) 2026, Davide Stocco and Enrico Bertolazzi. *
3 * *
4 * The AABBtree project is distributed under the BSD 2-Clause License. *
5 * *
6 * Davide Stocco Enrico Bertolazzi *
7 * University of Trento University of Trento *
8 * davide.stocco@unitn.it enrico.bertolazzi@unitn.it *
9\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10
11// DISCLAIMER: The code in this file is a modified version of the Eigen library.
12
13#pragma once
14
15#ifndef AABBTREE_BOX_HXX
16#define AABBTREE_BOX_HXX
17
18#include "AABBtree/Ray.hxx"
19
20namespace AABBtree {
21
27template <typename Real, Integer N> class Ray;
28
50template <typename Real, Integer N> class Box {
51 static_assert(std::is_floating_point<Real>::value,
52 "Box Real type must be a floating-point type.");
53 static_assert(N > 0, "Box dimension must be positive.");
54
59
60 Point
62 Point
64
65public:
69 ~Box() = default;
70
76 Box() { this->set_empty(); }
77
82 Box(Box const &b) : m_min(b.m_min), m_max(b.m_max) {}
83
93 Box(Point const &t_min, Point const &t_max) : m_min(t_min), m_max(t_max) {}
94
99 Box(Point const &p) : m_min(p), m_max(p) {}
100
108 template <typename = std::enable_if<N == 1>>
109 Box(Real const x_min, Real const x_max) : m_min(x_min), m_max(x_max) {}
110
120 template <typename = std::enable_if<N == 2>>
121 Box(Real const x_min, Real const y_min, Real const x_max, Real const y_max)
122 : m_min(x_min, y_min), m_max(x_max, y_max) {}
123
135 template <typename = std::enable_if<N == 3>>
136 Box(Real const x_min, Real const y_min, Real const z_min, Real const x_max,
137 Real const y_max, Real const z_max)
138 : m_min(x_min, y_min, z_min), m_max(x_max, y_max, z_max) {}
139
146 template <typename OtherReal>
147 explicit Box(Box<OtherReal, N> const &b)
148 : m_min(b.m_min.template cast<Real>()),
149 m_max(b.m_max.template cast<Real>()) {}
150
156 Box &operator=(Box const &b) = default;
157
164 template <typename NewReal> Box<NewReal, N> cast() const {
165 if constexpr (std::is_same<Real, NewReal>::value) {
166 return *this;
167 }
168 return Box<NewReal, N>(m_min.template cast<NewReal>(),
169 m_max.template cast<NewReal>());
170 }
171
176 Point const &min() const { return m_min; }
177
182 Point &min() { return m_min; }
183
188 Point const &max() const { return m_max; }
189
194 Point &max() { return m_max; }
195
200 void reorder() {
201 for (Integer i{0}; i < N; ++i) {
202 if (m_min[i] > m_max[i]) {
203 std::swap(m_min[i], m_max[i]);
204 }
205 }
206 }
207
213 bool is_empty() const { return (m_max.array() < m_min.array()).any(); }
214
221 bool
222 is_approx(Box const &b,
223 Real const tol = Eigen::NumTraits<Real>::dummy_precision()) const {
224 return m_min.isApprox(b.m_min, tol) && m_max.isApprox(b.m_max, tol);
225 }
226
233 Real const tol = Eigen::NumTraits<Real>::dummy_precision()) const {
234 return m_min.isApprox(m_max, tol);
235 }
236
242 Vector sizes{m_max - m_min};
243 return std::distance(sizes.data(),
244 std::max_element(sizes.data(), sizes.data() + N));
245 }
246
253 Integer longest_axis(Real &max_length, Real &mid_point) const {
254 Integer axis{-1};
255 max_length = -1;
256 for (Integer i{0}; i < N; ++i) {
257 if (Real const tmp_length{m_max(i) - m_min(i)}; max_length < tmp_length) {
258 max_length = tmp_length;
259 mid_point = 0.5 * (m_max(i) + m_min(i));
260 axis = i;
261 }
262 }
263 return axis;
264 }
265
271 void sort_axes_length(Vector &sizes, Eigen::Vector<Integer, N> &ipos) const {
272 sizes = m_max - m_min;
273 ipos = Eigen::Vector<Integer, N>::LinSpaced(N, 0, N - 1);
274 std::sort(ipos.data(), ipos.data() + N,
275 [&sizes](Integer i, Integer j) { return sizes[i] > sizes[j]; });
276 }
277
282 Point baricenter() const { return 0.5 * (m_min + m_max); }
283
289 Real baricenter(Integer i) const { return 0.5 * (m_min(i) + m_max(i)); }
290
295 Real volume() const { return (m_max - m_min).prod(); }
296
301 Real surface() const {
302 Vector sizes{m_max - m_min};
303 Real area{0};
304 for (Integer i{0}; i < N; ++i) {
305 Real prod{1.0};
306 for (Integer j{0}; j < N; ++j)
307 if (j != i)
308 prod *= sizes[j];
309 area += 2.0 * prod;
310 }
311 return area;
312 }
313
319 Vector diagonal() const { return m_max - m_min; }
320
325 void set_degenerate(Point const &p) {
326 m_min = p;
327 m_max = p;
328 }
329
333 void set_empty() {
334 m_min.setConstant(+std::numeric_limits<Real>::infinity());
335 m_max.setConstant(-std::numeric_limits<Real>::infinity());
336 }
337
343 bool intersects(Box const &b) const {
344 // return (m_min.array() <= b.m_max.array()).all() && (b.m_min.array() <=
345 // m_max.array()).all();
346 for (int d = 0; d < m_min.size(); ++d)
347 if (m_min[d] > b.m_max[d] || b.m_min[d] > m_max[d])
348 return false;
349 return true;
350 }
351
357 template <Integer d = 2> bool quasi_intersects(Box const &b) const {
358 return (m_min.template head<d>().array() <=
359 b.m_max.template head<d>().array())
360 .all() &&
361 (b.m_min.template head<d>().array() <=
362 m_max.template head<d>().array())
363 .all();
364 }
365
372 bool intersect(Box const &b_in, Box &b_out) const {
373 b_out.m_min = m_min.cwiseMax(b_in.m_min);
374 b_out.m_max = m_max.cwiseMin(b_in.m_max);
375 return (b_out.m_min.array() <= b_out.m_max.array()).all();
376 }
377
383 Box merged(Box const &b) const {
384 return Box(m_min.cwiseMin(b.m_min), m_max.cwiseMax(b.m_max));
385 }
386
392 Box &translate(Vector const &t) {
393 m_min += t;
394 m_max += t;
395 return *this;
396 }
397
403 Box translated(Vector const &t) const { return Box(m_min + t, m_max + t); }
404
413 template <typename Transform> Box transformed(Transform const &t) const {
414 Box result(m_min.transform(t), m_max.transform(t));
415 result.reorder();
416 return result;
417 }
418
427 template <typename Transform> Box &transform(Transform const &t) {
428 m_min.transform(t);
429 m_max.transform(t);
430 this->reorder();
431 return *this;
432 }
433
437 enum class Side : Integer { LEFT = -1, INSIDE = 0, RIGHT = +1 };
438
447 Side which_side(Real const x, Real const tol, Integer const dim) const {
448 Real const x_min{m_min(dim)};
449 Real const x_max{m_max(dim)};
450 bool const on_left{x_max < x + tol};
451 bool const on_right{x - tol < x_min};
452 if (on_left && on_right) {
453 return 0.5 * (x_min + x_max) < x ? Side::LEFT : Side::RIGHT;
454 } else if (on_left) {
455 return Side::LEFT;
456 } else if (on_right) {
457 return Side::RIGHT;
458 } else {
459 return Side::INSIDE;
460 }
461 }
462
468 bool contains(Point const &p) const {
469 return (m_min.array() <= p.array()).all() &&
470 (p.array() <= m_max.array()).all();
471 }
472
479 bool intersects(Point const &p) const {
480 return (m_min.array() <= p.array()).all() &&
481 (p.array() <= m_max.array()).all();
482 }
483
491 template <Integer d = 2> bool quasi_intersects(Point const &p) const {
492 return (m_min.template head<d>().array() <= p.template head<d>().array()) &&
493 (p.template head<d>().array() <= m_max.template head<d>().array());
494 }
495
501 bool contains(Box const &b) const {
502 return (m_min.array() <= b.m_min.array()).all() &&
503 (b.m_max.array() <= m_max.array()).all();
504 }
505
511 template <typename Derived> Box &extend(Point const &p) {
512 m_min = m_min.cwiseMin(p);
513 m_max = m_max.cwiseMax(p);
514 return *this;
515 }
516
523 Box &extend(Box const &b) {
524 m_min = m_min.cwiseMin(b.m_min);
525 m_max = m_max.cwiseMax(b.m_max);
526 return *this;
527 }
528
537 Real squared_interior_distance(Point const &p) const {
538 Real dist2{0.0};
539 for (Integer i{0}; i < N; ++i) {
540 if (m_min[i] > p[i]) {
541 Real aux{m_min[i] - p[i]};
542 dist2 += aux * aux;
543 } else if (p[i] > m_max[i]) {
544 Real aux{p[i] - m_max[i]};
545 dist2 += aux * aux;
546 }
547 }
548 return dist2;
549 }
550
561 Real squared_interior_distance(Point const &p, Point &c) const {
562 if (this->contains(p))
563 return 0;
564 c = p.cwiseMax(m_min).cwiseMin(m_max);
565 return (p - c).squaredNorm();
566 }
567
576 Real interior_distance(Point const &p) const {
577 return std::sqrt(this->squared_interior_distance(p));
578 }
579
589 Real interior_distance(Point const &p, Point &c) const {
590 return std::sqrt(this->squared_interior_distance(p, c));
591 }
592
601 Real squared_exterior_distance(Point const &p) const {
602 Real dist2{0.0};
603 for (Integer i{0}; i < N; ++i) {
604 Real const aux1{std::abs(m_min[i] - p[i])};
605 Real const aux2{std::abs(m_max[i] - p[i])};
606 Real const aux3{std::max(aux1, aux2)};
607 dist2 += aux3 * aux3;
608 }
609 return dist2;
610 }
611
621 Real squared_exterior_distance(Point const &p, Point &f) const {
622 for (Integer i{0}; i < N; ++i) {
623 Real const aux1{std::abs(m_min[i] - p[i])};
624 Real const aux2{std::abs(m_max[i] - p[i])};
625 f[i] = aux1 > aux2 ? m_min[i] : m_max[i];
626 }
627 return (f - p).squaredNorm();
628 }
629
638 Real exterior_distance(Point const &p) const {
639 return std::sqrt(this->squared_exterior_distance(p));
640 }
641
651 Real exterior_distance(Point const &p, Point &f) const {
652 return std::sqrt(this->squared_exterior_distance(p, f));
653 }
654
663 Real squared_interior_distance(Box const &b) const {
664 if (this->intersects(b))
665 return 0;
666 Real dist2{0.0};
667 for (Integer i{0}; i < N; ++i) {
668 Real aux{m_min[i] - b.m_max[i]};
669 if (aux < 0.0) {
670 aux = b.m_min[i] - m_max[i];
671 if (aux < 0.0) {
672 continue;
673 }
674 }
675 dist2 += aux * aux;
676 }
677 return dist2;
678 }
679
690 Real squared_interior_distance(Box const &b, Point &p1, Point &p2) const {
691 if (this->intersects(b)) {
692 return 0.0;
693 }
694 for (Integer i{0}; i < N; ++i) {
695 if (m_min[i] > b.m_max[i]) {
696 p1[i] = b.m_max[i];
697 p2[i] = m_min[i];
698 } else if (b.m_min[i] > m_max[i]) {
699 p1[i] = m_max[i];
700 p2[i] = b.m_min[i];
701 } else {
702 p1[i] = p2[i] = 0.5 * (std::min(m_max[i], b.m_max[i]) +
703 std::max(m_min[i], b.m_min[i]));
704 }
705 }
706 return (p2 - p1).squaredNorm();
707 }
708
717 Real interior_distance(Box const &b) const {
718 return std::sqrt(this->squared_interior_distance(b));
719 }
720
731 Real interior_distance(Box const &b, Point &p1, Point &p2) const {
732 return std::sqrt(this->squared_interior_distance(b, p1, p2));
733 }
734
743 Real squared_exterior_distance(Box const &b) const {
744 Real dist2{Real(0)};
745 for (Integer i{0}; i < N; ++i) {
746 Real const aux{std::max(m_max[i], b.m_max[i]) -
747 std::min(m_min[i], b.m_min[i])};
748 dist2 += aux * aux;
749 }
750 return dist2;
751 }
752
761 Real squared_exterior_distance(Box const &b, Point &p1, Point &p2) const {
762 p1 = b.m_min.cwiseMin(m_min);
763 p2 = b.m_max.cwiseMax(m_max);
764 return (p2 - p1).squaredNorm();
765 }
766
775 Real exterior_distance(Box const &b) const {
776 return std::sqrt(this->squared_exterior_distance(b));
777 }
778
789 Real exterior_distance(Box const &b, Point &p1, Point &p2) const {
790 return std::sqrt(this->squared_exterior_distance(b, p1, p2));
791 }
792
800 Real tol = Eigen::NumTraits<Real>::dummy_precision()) const {
801 return r.intersects(*this, tol);
802 }
803
812 bool intersect(Ray<Real, N> const &r, Point &c, Point &f,
813 Real tol = Eigen::NumTraits<Real>::dummy_precision()) const {
814 return r.intersect(*this, c, f, tol);
815 }
816
827 Ray<Real, N> const &r,
828 Real tol = Eigen::NumTraits<Real>::dummy_precision()) const {
829 return r.squared_interior_distance(*this, tol);
830 }
831
844 Ray<Real, N> const &r, Point &p1, Point &p2,
845 Real tol = Eigen::NumTraits<Real>::dummy_precision()) const {
846 return r.squared_interior_distance(*this, p2, p1, tol);
847 }
848
859 Ray<Real, N> const &r,
860 Real tol = Eigen::NumTraits<Real>::dummy_precision()) const {
861 return r.interior_distance(*this, tol);
862 }
863
876 Ray<Real, N> const &r, Point &p1, Point &p2,
877 Real tol = Eigen::NumTraits<Real>::dummy_precision()) const {
878 return r.interior_distance(*this, p2, p1, tol);
879 }
880
891 Ray<Real, N> const &r,
892 Real tol = Eigen::NumTraits<Real>::dummy_precision()) const {
893 return r.squared_exterior_distance(*this, tol);
894 }
895
906 Ray<Real, N> const &r, Point &p1, Point &p2,
907 Real tol = Eigen::NumTraits<Real>::dummy_precision()) const {
908 return r.squared_exterior_distance(*this, p2, p1, tol);
909 }
910
921 Ray<Real, N> const &r,
922 Real tol = Eigen::NumTraits<Real>::dummy_precision()) const {
923 return r.exterior_distance(*this, tol);
924 }
925
938 Ray<Real, N> const &r, Point &p1, Point &p2,
939 Real tol = Eigen::NumTraits<Real>::dummy_precision()) const {
940 return r.exterior_distance(*this, p2, p1, tol);
941 }
942
947 void print(std::ostream &os) const {
948 os << "BOX INFO" << std::endl
949 << "\tmin = " << m_min.transpose() << std::endl
950 << "\tmax = " << m_max.transpose() << std::endl;
951 }
952
953}; // class Box
954
962template <typename Real, Integer N>
963std::ostream &operator<<(std::ostream &os, Box<Real, N> const &b) {
964 b.print(os);
965 return os;
966}
967
968} // namespace AABBtree
969
970#endif // AABBTREE_BOX_HXX
A class representing an axis-aligned bounding box (AABB) in N-dimensional space.
Definition Box.hxx:50
Box & extend(Point const &p)
Definition Box.hxx:511
Box()
Definition Box.hxx:76
Real squared_interior_distance(Box const &b) const
Definition Box.hxx:663
Box & extend(Box const &b)
Definition Box.hxx:523
Point m_max
Definition Box.hxx:63
Box transformed(Transform const &t) const
Definition Box.hxx:413
Real squared_exterior_distance(Point const &p) const
Definition Box.hxx:601
void set_degenerate(Point const &p)
Definition Box.hxx:325
bool is_empty() const
Definition Box.hxx:213
Real squared_exterior_distance(Ray< Real, N > const &r, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Box.hxx:890
bool quasi_intersects(Point const &p) const
Definition Box.hxx:491
bool is_approx(Box const &b, Real const tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Box.hxx:222
Real squared_interior_distance(Ray< Real, N > const &r, Point &p1, Point &p2, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Box.hxx:843
Box(Real const x_min, Real const y_min, Real const z_min, Real const x_max, Real const y_max, Real const z_max)
Definition Box.hxx:136
Real squared_exterior_distance(Ray< Real, N > const &r, Point &p1, Point &p2, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Box.hxx:905
Real exterior_distance(Ray< Real, N > const &r, Point &p1, Point &p2, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Box.hxx:937
Real squared_exterior_distance(Box const &b, Point &p1, Point &p2) const
Definition Box.hxx:761
Real interior_distance(Ray< Real, N > const &r, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Box.hxx:858
Real baricenter(Integer i) const
Definition Box.hxx:289
void reorder()
Definition Box.hxx:200
void set_empty()
Definition Box.hxx:333
bool is_degenerate(Real const tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Box.hxx:232
bool contains(Box const &b) const
Definition Box.hxx:501
Box(Real const x_min, Real const y_min, Real const x_max, Real const y_max)
Definition Box.hxx:121
Real exterior_distance(Box const &b) const
Definition Box.hxx:775
Real surface() const
Definition Box.hxx:301
Box & translate(Vector const &t)
Definition Box.hxx:392
Side which_side(Real const x, Real const tol, Integer const dim) const
Definition Box.hxx:447
Real squared_exterior_distance(Point const &p, Point &f) const
Definition Box.hxx:621
Box(Real const x_min, Real const x_max)
Definition Box.hxx:109
Box< NewReal, N > cast() const
Definition Box.hxx:164
Real squared_interior_distance(Point const &p) const
Definition Box.hxx:537
Real squared_interior_distance(Box const &b, Point &p1, Point &p2) const
Definition Box.hxx:690
Real interior_distance(Point const &p) const
Definition Box.hxx:576
bool intersects(Ray< Real, N > const &r, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Box.hxx:799
Real exterior_distance(Point const &p) const
Definition Box.hxx:638
void sort_axes_length(Vector &sizes, Eigen::Vector< Integer, N > &ipos) const
Definition Box.hxx:271
Box & operator=(Box const &b)=default
Real squared_interior_distance(Ray< Real, N > const &r, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Box.hxx:826
bool contains(Point const &p) const
Definition Box.hxx:468
Real interior_distance(Point const &p, Point &c) const
Definition Box.hxx:589
Point const & min() const
Definition Box.hxx:176
Box & transform(Transform const &t)
Definition Box.hxx:427
AABBtree::BoxUniquePtrList< Real, N > BoxUniquePtrList
Definition Box.hxx:58
Box(Box const &b)
Definition Box.hxx:82
~Box()=default
AABBtree::Vector< Real, N > Vector
Definition Box.hxx:56
Real squared_interior_distance(Point const &p, Point &c) const
Definition Box.hxx:561
Box(Point const &p)
Definition Box.hxx:99
bool quasi_intersects(Box const &b) const
Definition Box.hxx:357
Point baricenter() const
Definition Box.hxx:282
bool intersect(Box const &b_in, Box &b_out) const
Definition Box.hxx:372
AABBtree::BoxUniquePtr< Real, N > BoxUniquePtr
Definition Box.hxx:57
Real interior_distance(Ray< Real, N > const &r, Point &p1, Point &p2, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Box.hxx:875
Integer longest_axis() const
Definition Box.hxx:241
bool intersect(Ray< Real, N > const &r, Point &c, Point &f, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Box.hxx:812
AABBtree::Point< Real, N > Point
Definition Box.hxx:55
Side
Definition Box.hxx:437
@ RIGHT
Definition Box.hxx:437
@ INSIDE
Definition Box.hxx:437
@ LEFT
Definition Box.hxx:437
Real squared_exterior_distance(Box const &b) const
Definition Box.hxx:743
Box(Point const &t_min, Point const &t_max)
Definition Box.hxx:93
Point m_min
Definition Box.hxx:61
Integer longest_axis(Real &max_length, Real &mid_point) const
Definition Box.hxx:253
Point & min()
Definition Box.hxx:182
Point & max()
Definition Box.hxx:194
Real exterior_distance(Ray< Real, N > const &r, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Box.hxx:920
Vector diagonal() const
Definition Box.hxx:319
Real interior_distance(Box const &b) const
Definition Box.hxx:717
void print(std::ostream &os) const
Definition Box.hxx:947
bool intersects(Box const &b) const
Definition Box.hxx:343
bool intersects(Point const &p) const
Definition Box.hxx:479
Real exterior_distance(Box const &b, Point &p1, Point &p2) const
Definition Box.hxx:789
Real exterior_distance(Point const &p, Point &f) const
Definition Box.hxx:651
Point const & max() const
Definition Box.hxx:188
Real interior_distance(Box const &b, Point &p1, Point &p2) const
Definition Box.hxx:731
Real volume() const
Definition Box.hxx:295
Box(Box< OtherReal, N > const &b)
Definition Box.hxx:147
Box translated(Vector const &t) const
Definition Box.hxx:403
Box merged(Box const &b) const
Definition Box.hxx:383
A mathematical ray in N-dimensional space.
Definition Ray.hxx:38
Real interior_distance(Box< Real, N > const &b, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Ray.hxx:479
bool intersect(Box< Real, N > const &b, Point &c, Point &f, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Ray.hxx:286
Real squared_exterior_distance(Box< Real, N > const &b, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Ray.hxx:512
bool intersects(Box< Real, N > const &b, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Ray.hxx:252
Real squared_interior_distance(Box< Real, N > const &b, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Ray.hxx:381
Real exterior_distance(Box< Real, N > const &b, Real tol=Eigen::NumTraits< Real >::dummy_precision()) const
Definition Ray.hxx:608
Namespace for the AABBtree library.
Definition AABBtree.hh:81
Eigen::Vector< Real, N > Point
Definition AABBtree.hh:105
std::ostream & operator<<(std::ostream &os, Box< Real, N > const &b)
Definition Box.hxx:963
std::unique_ptr< Box< Real, N > > BoxUniquePtr
Definition AABBtree.hh:101
std::vector< BoxUniquePtr< Real, N > > BoxUniquePtrList
Definition AABBtree.hh:103
Eigen::Vector< Real, N > Vector
Definition AABBtree.hh:104
AABBTREE_DEFAULT_INTEGER_TYPE Integer
The Integer type used in the AABBtree class.
Definition AABBtree.hh:89