AABBtree  0.0.0
A C++ non-recursive ND AABB tree
Loading...
Searching...
No Matches
Box.hxx
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
2 * Copyright (c) 2025, 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 * e-mail: davide.stocco@unitn.it e-mail: 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
27 template <typename Real, Integer N> class Ray;
28
48 template <typename Real, Integer N>
49 class Box {
50 static_assert(std::is_floating_point<Real>::value, "Box Real type must be a floating-point type.");
51 static_assert(N > 0, "Box dimension must be positive.");
52
53 // Constants for numerical computations
54 constexpr static Real EPS{std::numeric_limits<Real>::epsilon()};
55 constexpr static Real INF{std::numeric_limits<Real>::infinity()};
56 constexpr static Real DUMMY_TOL{EPS*static_cast<Real>(100.0)};
57
62
65
66 public:
70 ~Box() = default;
71
76 Box() {this->set_empty();}
77
82 Box(Box const & b) : m_min(b.m_min), m_max(b.m_max) {}
83
91 Box(Point const & t_min, Point const & t_max) : m_min(t_min), m_max(t_max) {}
92
97 Box(Point const & p) : m_min(p), m_max(p) {}
98
106 template <typename = std::enable_if<N == 1>>
107 Box(Real const x_min, Real const x_max) : m_min(x_min), m_max(x_max) {}
108
118 template <typename = std::enable_if<N == 2>>
119 Box(Real const x_min, Real const y_min, Real const x_max, Real const y_max)
120 : m_min(x_min, y_min), m_max(x_max, y_max) {}
121
133 template <typename = std::enable_if<N == 3>>
135 Real const x_min, Real const y_min, Real const z_min,
136 Real const x_max, Real const y_max, Real const z_max
137 ) : m_min(x_min, y_min, z_min), m_max(x_max, y_max, z_max) {}
138
144 template<typename OtherReal>
145 explicit Box(Box<OtherReal, N> const & b)
146 : m_min(b.m_min.template cast<Real>()), m_max(b.m_max.template cast<Real>()) {}
147
153 Box & operator=(Box const & b) = default;
154
161 template<typename NewReal>
163 {
164 if constexpr (std::is_same<Real, NewReal>::value) {return *this;}
165 return Box<NewReal,N>(m_min.template cast<NewReal>(), m_max.template cast<NewReal>());
166 }
167
172 Point const & min() const {return m_min;}
173
178 Point & min() {return m_min;}
179
184 Point const & max() const {return m_max;}
185
190 Point & max() {return m_max;}
191
196 void reorder() {
197 for (Integer i{0}; i < N; ++i) {
198 if (m_min[i] > m_max[i]) {std::swap(m_min[i], m_max[i]);}
199 }
200 }
201
207 bool is_empty() const {return (m_max.array() < m_min.array()).any();}
208
215 bool is_approx(Box const & b, Real const tol /*= DUMMY_TOL*/) const
216 {return m_min.isApprox(b.m_min, tol) && m_max.isApprox(b.m_max, tol);}
217
223 bool is_degenerate(Real const tol /*= DUMMY_TOL*/) const
224 {return m_min.isApprox(m_max, tol);}
225
231 {
232 Vector sizes{ m_max - m_min };
233 return std::distance(sizes.data(), std::max_element(sizes.data(), sizes.data() + N));
234 }
235
242 Integer longest_axis(Real & max_length, Real & mid_point) const
243 {
244 Integer axis{-1};
245 max_length = -1;
246 for (Integer i{0}; i < N; ++i) {
247 if (Real const tmp_length{m_max(i) - m_min(i)}; max_length < tmp_length)
248 {max_length = tmp_length; mid_point = 0.5*(m_max(i) + m_min(i)); axis = i;}
249 }
250 return axis;
251 }
252
258 void sort_axes_length(Vector & sizes, Eigen::Vector<Integer, N> & ipos) const
259 {
260 sizes = m_max - m_min;
261 ipos = Eigen::Vector<Integer, N>::LinSpaced(N, 0, N - 1);
262 std::sort(ipos.data(), ipos.data() + N, [&sizes](Integer i, Integer j) {return sizes[i] > sizes[j];});
263 }
264
269 Point baricenter() const {return 0.5*(m_min + m_max);}
270
276 Real baricenter(Integer i) const {return 0.5*(m_min(i) + m_max(i));}
277
282 Real volume() const {return (m_max-m_min).prod();}
283
288 Real surface() const {
289 Vector sizes { m_max - m_min };
290 Real area{0};
291 for (Integer i{0}; i < N; ++i) {
292 Real prod{1.0};
293 for (Integer j{0}; j < N; ++j)
294 if (j != i)
295 prod *= sizes[j];
296 area += 2.0*prod;
297 }
298 return area;
299 }
300
306 Vector diagonal() const {return m_max-m_min;}
307
312 void set_degenerate(Point const & p) {
313 m_min = p;
314 m_max = p;
315 }
316
320 void set_empty() {
321 m_min.setConstant(+INF);
322 m_max.setConstant(-INF);
323 }
324
330 bool intersects(Box const & b) const {
331 return (m_min.array() <= b.m_max.array()).all() && (b.m_min.array() <= m_max.array()).all();
332 }
333
340 bool intersect(Box const & b_in, Box & b_out) const {
341 b_out.m_min = m_min.cwiseMax(b_in.m_min);
342 b_out.m_max = m_max.cwiseMin(b_in.m_max);
343 return (b_out.m_min.array() <= b_out.m_max.array()).all();
344 }
345
351 Box merged(Box const & b) const
352 {return Box(m_min.cwiseMin(b.m_min), m_max.cwiseMax(b.m_max));}
353
359 Box & translate(Vector const & t) {m_min += t; m_max += t; return *this;}
360
366 Box translated(Vector const & t) const {return Box(m_min + t, m_max + t);}
367
375 template <typename Transform>
376 Box transformed(Transform const & t) const
377 {
378 Box result(m_min.transform(t), m_max.transform(t));
379 result.reorder();
380 return result;
381 }
382
390 template <typename Transform>
391 Box & transform(Transform const & t) {
392 m_min.transform(t);
393 m_max.transform(t);
394 this->reorder();
395 return *this;
396 }
397
401 enum class Side : Integer {LEFT = -1, INSIDE = 0, RIGHT = +1};
402
410 Side which_side(Real const x, Real const tol, Integer const dim) const {
411 Real const mi { m_min(dim) };
412 Real const ma { m_max(dim) };
413 bool const on_left { ma < x + tol };
414 bool const on_right { x - tol < mi };
415 if (on_left && on_right) {
416 return (mi+ma)/2 < x ? Side::LEFT : Side::RIGHT;
417 }
418 if (on_left) return Side::LEFT;
419 if (on_right) return Side::RIGHT;
420 return Side::INSIDE;
421 }
422
428 bool contains(Point const & p) const {
429 return (m_min.array() <= p.array()).all() &&
430 (p.array() <= m_max.array()).all();
431 }
432
439 bool intersects(Point const & p) const {
440 return (m_min.array() <= p.array()).all() && (p.array() <= m_max.array()).all();
441 }
442
448 bool contains(Box const & b) const {
449 return (m_min.array() <= b.m_min.array()).all() &&
450 (b.m_max.array() <= m_max.array()).all();
451 }
452
458 template<typename Derived>
459 Box & extend(Point const & p) {
460 m_min = m_min.cwiseMin(p);
461 m_max = m_max.cwiseMax(p);
462 return *this;
463 }
464
471 Box & extend(Box const & b) {
472 m_min = m_min.cwiseMin(b.m_min);
473 m_max = m_max.cwiseMax(b.m_max);
474 return *this;
475 }
476
484 Real squared_interior_distance(Point const & p) const
485 {
486 Real dist2{0.0};
487 for (Integer i{0}; i < N; ++i) {
488 if (m_min[i] > p[i]) {Real aux{m_min[i] - p[i]}; dist2 += aux*aux;}
489 else if (p[i] > m_max[i]) {Real aux{p[i] - m_max[i]}; dist2 += aux*aux;}
490 }
491 return dist2;
492 }
493
503 Real squared_interior_distance(Point const & p, Point & c) const {
504 if (this->contains(p)) return 0;
505 c = p.cwiseMax(m_min).cwiseMin(m_max);
506 return (p - c).squaredNorm();
507 }
508
515 Real interior_distance(Point const & p) const
516 {return std::sqrt(this->squared_interior_distance(p));}
517
526 Real interior_distance(Point const & p, Point & c) const
527 {return std::sqrt(this->squared_interior_distance(p, c));}
528
535 Real squared_exterior_distance(Point const & p) const {
536 Real dist2{0.0};
537 for (Integer i{0}; i < N; ++i) {
538 Real const aux1{ std::abs(m_min[i] - p[i])};
539 Real const aux2{ std::abs(m_max[i] - p[i])};
540 Real const aux3{ std::max(aux1,aux2)};
541 dist2 += aux3*aux3;
542 }
543 return dist2;
544 }
545
554 Real squared_exterior_distance(Point const & p, Point & f) const {
555 for (Integer i{0}; i < N; ++i) {
556 Real const aux1{ std::abs(m_min[i] - p[i])};
557 Real const aux2{ std::abs(m_max[i] - p[i])};
558 f[i] = aux1 > aux2 ? m_min[i] : m_max[i];
559 }
560 return (f - p).squaredNorm();
561 }
562
569 Real exterior_distance(Point const & p) const
570 {return std::sqrt(this->squared_exterior_distance(p));}
571
580 Real exterior_distance(Point const & p, Point & f) const
581 {return std::sqrt(this->squared_exterior_distance(p, f));}
582
589 Real squared_interior_distance(Box const & b) const {
590 if (this->intersects(b)) return 0;
591 Real dist2{0.0};
592 for (Integer i{0}; i < N; ++i) {
593 Real aux{ m_min[i] - b.m_max[i]};
594 if (aux < 0.0) {
595 aux = b.m_min[i] - m_max[i];
596 if (aux < 0.0) {continue;}
597 }
598 dist2 += aux*aux;
599 }
600 return dist2;
601 }
602
612 Real squared_interior_distance(Box const & b, Point & p1, Point & p2) const {
613 if (this->intersects(b)) {return 0.0;}
614 for (Integer i{0}; i < N; ++ i) {
615 if (m_min[i] > b.m_max[i]) {p1[i] = b.m_max[i]; p2[i] = m_min[i];}
616 else if (b.m_min[i] > m_max[i]) {p1[i] = m_max[i]; p2[i] = b.m_min[i];}
617 else {
618 p1[i] = p2[i] = 0.5*(std::min(m_max[i], b.m_max[i]) + std::max(m_min[i], b.m_min[i]));
619 }
620 }
621 return (p2 - p1).squaredNorm();
622 }
623
630 Real interior_distance(Box const & b) const {return std::sqrt(this->squared_interior_distance(b));}
631
641 Real interior_distance(Box const & b, Point & p1, Point & p2) const
642 {return std::sqrt(this->squared_interior_distance(b, p1, p2));}
643
650 Real squared_exterior_distance(Box const & b) const {
651 Real dist2{ Real(0)};
652 for (Integer i{0}; i < N; ++i) {
653 Real const aux{ std::max(m_max[i], b.m_max[i]) - std::min(m_min[i], b.m_min[i])};
654 dist2 += aux*aux;
655 }
656 return dist2;
657 }
658
667 Real squared_exterior_distance(Box const & b, Point & p1, Point & p2) const {
668 p1 = b.m_min.cwiseMin(m_min);
669 p2 = b.m_max.cwiseMax(m_max);
670 return (p2 - p1).squaredNorm();
671 }
672
679 Real exterior_distance(Box const & b) const
680 {return std::sqrt(this->squared_exterior_distance(b));}
681
691 Real exterior_distance(Box const & b, Point & p1, Point & p2) const
692 {return std::sqrt(this->squared_exterior_distance(b, p1, p2));}
693
700 bool intersects(Ray<Real, N> const & r, Real tol = DUMMY_TOL) const
701 {return r.intersects(*this, tol);}
702
711 bool intersect(Ray<Real, N> const & r, Point & c, Point & f, Real tol = DUMMY_TOL) const
712 {return r.intersect(*this, c, f, tol);}
713
721 Real squared_interior_distance(Ray<Real, N> const & r, Real tol = DUMMY_TOL) const
722 {return r.squared_interior_distance(*this, tol);}
723
734 Real squared_interior_distance(Ray<Real, N> const & r, Point & p1, Point & p2, Real tol = DUMMY_TOL) const
735 {return r.squared_interior_distance(*this, p2, p1, tol);}
736
744 Real interior_distance(Ray<Real, N> const & r, Real tol = DUMMY_TOL) const
745 {return r.interior_distance(*this, tol);}
746
757 Real interior_distance(Ray<Real, N> const & r, Point & p1, Point & p2, Real tol = DUMMY_TOL) const
758 {return r.interior_distance(*this, p2, p1, tol);}
759
767 Real squared_exterior_distance(Ray<Real, N> const & r, Real tol = DUMMY_TOL) const
768 {return r.squared_exterior_distance(*this, tol);}
769
779 Real squared_exterior_distance(Ray<Real, N> const & r, Point & p1, Point & p2, Real tol = DUMMY_TOL) const
780 {return r.squared_exterior_distance(*this, p2, p1, tol);}
781
789 Real exterior_distance(Ray<Real, N> const & r, Real tol = DUMMY_TOL) const
790 {return r.exterior_distance(*this, tol);}
791
802 Real exterior_distance(Ray<Real, N> const & r, Point & p1, Point & p2, Real tol = DUMMY_TOL) const
803 {return r.exterior_distance(*this, p2, p1, tol);}
804
809 void print(std::ostream & os) const {
810 os <<
811 "────────────────────────────────────────────────────────────────────────────────\n" <<
812 "BOX INFO\n" <<
813 "\tmin = " << m_min.transpose() << '\n' <<
814 "\tmax = " << m_max.transpose() << '\n' <<
815 "────────────────────────────────────────────────────────────────────────────────\n";
816 }
817
818 }; // class Box
819
827 template <typename Real, Integer N>
828 std::ostream & operator<<(std::ostream & os, Box<Real, N> const & b) {b.print(os); return os;}
829
830} // namespace AABBtree
831
832#endif // AABBTREE_BOX_HXX
A class representing an axis-aligned bounding box (AABB) in N-dimensional space.
Definition Box.hxx:49
Box & extend(Point const &p)
Definition Box.hxx:459
Box()
Definition Box.hxx:76
Real squared_interior_distance(Box const &b) const
Definition Box.hxx:589
Box & extend(Box const &b)
Definition Box.hxx:471
Point m_max
Definition Box.hxx:64
static constexpr Real INF
Definition Box.hxx:55
Box transformed(Transform const &t) const
Definition Box.hxx:376
Real squared_exterior_distance(Point const &p) const
Definition Box.hxx:535
void set_degenerate(Point const &p)
Definition Box.hxx:312
bool is_empty() const
Definition Box.hxx:207
Real squared_exterior_distance(Ray< Real, N > const &r, Point &p1, Point &p2, Real tol=DUMMY_TOL) const
Definition Box.hxx:779
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:134
static constexpr Real EPS
Definition Box.hxx:54
Real squared_exterior_distance(Box const &b, Point &p1, Point &p2) const
Definition Box.hxx:667
bool intersect(Ray< Real, N > const &r, Point &c, Point &f, Real tol=DUMMY_TOL) const
Definition Box.hxx:711
Real baricenter(Integer i) const
Definition Box.hxx:276
void reorder()
Definition Box.hxx:196
void set_empty()
Definition Box.hxx:320
Real squared_exterior_distance(Ray< Real, N > const &r, Real tol=DUMMY_TOL) const
Definition Box.hxx:767
bool contains(Box const &b) const
Definition Box.hxx:448
Box(Real const x_min, Real const y_min, Real const x_max, Real const y_max)
Definition Box.hxx:119
Real exterior_distance(Box const &b) const
Definition Box.hxx:679
Real surface() const
Definition Box.hxx:288
static constexpr Real DUMMY_TOL
Definition Box.hxx:56
Box & translate(Vector const &t)
Definition Box.hxx:359
Real exterior_distance(Ray< Real, N > const &r, Point &p1, Point &p2, Real tol=DUMMY_TOL) const
Definition Box.hxx:802
Side which_side(Real const x, Real const tol, Integer const dim) const
Definition Box.hxx:410
Real squared_exterior_distance(Point const &p, Point &f) const
Definition Box.hxx:554
Box(Real const x_min, Real const x_max)
Definition Box.hxx:107
Box< NewReal, N > cast() const
Definition Box.hxx:162
Real squared_interior_distance(Point const &p) const
Definition Box.hxx:484
Real squared_interior_distance(Box const &b, Point &p1, Point &p2) const
Definition Box.hxx:612
Real interior_distance(Point const &p) const
Definition Box.hxx:515
Real exterior_distance(Point const &p) const
Definition Box.hxx:569
void sort_axes_length(Vector &sizes, Eigen::Vector< Integer, N > &ipos) const
Definition Box.hxx:258
Box & operator=(Box const &b)=default
bool contains(Point const &p) const
Definition Box.hxx:428
bool intersects(Ray< Real, N > const &r, Real tol=DUMMY_TOL) const
Definition Box.hxx:700
Real interior_distance(Point const &p, Point &c) const
Definition Box.hxx:526
Point const & min() const
Definition Box.hxx:172
Box & transform(Transform const &t)
Definition Box.hxx:391
AABBtree::BoxUniquePtrList< Real, N > BoxUniquePtrList
Definition Box.hxx:61
bool is_degenerate(Real const tol) const
Definition Box.hxx:223
Box(Box const &b)
Definition Box.hxx:82
~Box()=default
AABBtree::Vector< Real, N > Vector
Definition Box.hxx:59
Real squared_interior_distance(Point const &p, Point &c) const
Definition Box.hxx:503
Real interior_distance(Ray< Real, N > const &r, Point &p1, Point &p2, Real tol=DUMMY_TOL) const
Definition Box.hxx:757
Box(Point const &p)
Definition Box.hxx:97
Point baricenter() const
Definition Box.hxx:269
bool intersect(Box const &b_in, Box &b_out) const
Definition Box.hxx:340
AABBtree::BoxUniquePtr< Real, N > BoxUniquePtr
Definition Box.hxx:60
Real exterior_distance(Ray< Real, N > const &r, Real tol=DUMMY_TOL) const
Definition Box.hxx:789
Integer longest_axis() const
Definition Box.hxx:230
Real squared_interior_distance(Ray< Real, N > const &r, Point &p1, Point &p2, Real tol=DUMMY_TOL) const
Definition Box.hxx:734
AABBtree::Point< Real, N > Point
Definition Box.hxx:58
Side
Definition Box.hxx:401
@ RIGHT
Definition Box.hxx:401
@ INSIDE
Definition Box.hxx:401
@ LEFT
Definition Box.hxx:401
Real squared_exterior_distance(Box const &b) const
Definition Box.hxx:650
Box(Point const &t_min, Point const &t_max)
Definition Box.hxx:91
bool is_approx(Box const &b, Real const tol) const
Definition Box.hxx:215
Point m_min
Definition Box.hxx:63
Real squared_interior_distance(Ray< Real, N > const &r, Real tol=DUMMY_TOL) const
Definition Box.hxx:721
Integer longest_axis(Real &max_length, Real &mid_point) const
Definition Box.hxx:242
Point & min()
Definition Box.hxx:178
Point & max()
Definition Box.hxx:190
Vector diagonal() const
Definition Box.hxx:306
Real interior_distance(Box const &b) const
Definition Box.hxx:630
void print(std::ostream &os) const
Definition Box.hxx:809
bool intersects(Box const &b) const
Definition Box.hxx:330
bool intersects(Point const &p) const
Definition Box.hxx:439
Real interior_distance(Ray< Real, N > const &r, Real tol=DUMMY_TOL) const
Definition Box.hxx:744
Real exterior_distance(Box const &b, Point &p1, Point &p2) const
Definition Box.hxx:691
Real exterior_distance(Point const &p, Point &f) const
Definition Box.hxx:580
Point const & max() const
Definition Box.hxx:184
Real interior_distance(Box const &b, Point &p1, Point &p2) const
Definition Box.hxx:641
Real volume() const
Definition Box.hxx:282
Box(Box< OtherReal, N > const &b)
Definition Box.hxx:145
Box translated(Vector const &t) const
Definition Box.hxx:366
Box merged(Box const &b) const
Definition Box.hxx:351
A mathematical ray in N-dimensional space.
Definition Ray.hxx:39
bool intersects(Box< Real, N > const &b, Real tol=DUMMY_TOL) const
Definition Ray.hxx:239
Real squared_interior_distance(Box< Real, N > const &b, Real tol=DUMMY_TOL) const
Definition Ray.hxx:340
Real interior_distance(Box< Real, N > const &b, Real tol=DUMMY_TOL) const
Definition Ray.hxx:406
bool intersect(Box< Real, N > const &b, Point &c, Point &f, Real tol=DUMMY_TOL) const
Definition Ray.hxx:266
Real exterior_distance(Box< Real, N > const &b, Real tol=DUMMY_TOL) const
Definition Ray.hxx:495
Real squared_exterior_distance(Box< Real, N > const &b, Real tol=DUMMY_TOL) const
Definition Ray.hxx:429
Namespace for the AABBtree library.
Definition AABBtree.hh:70
Eigen::Vector< Real, N > Point
Definition AABBtree.hh:91
std::ostream & operator<<(std::ostream &os, Box< Real, N > const &b)
Definition Box.hxx:828
std::unique_ptr< Box< Real, N > > BoxUniquePtr
Definition AABBtree.hh:88
std::vector< BoxUniquePtr< Real, N > > BoxUniquePtrList
Definition AABBtree.hh:89
Eigen::Vector< Real, N > Vector
Definition AABBtree.hh:90
AABBTREE_DEFAULT_INTEGER_TYPE Integer
The Integer type used in the AABBtree class.
Definition AABBtree.hh:78