AABBtree  0.0.0
A C++ non-recursive ND AABB tree
Loading...
Searching...
No Matches
Ray.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_RAY_HXX
16#define AABBTREE_RAY_HXX
17
18#include "AABBtree/Box.hxx"
19
20namespace AABBtree {
21
38 template <typename Real, Integer N>
39 class Ray {
40 static_assert(std::is_floating_point<Real>::value, "Ray Real type must be a floating-point type.");
41 static_assert(N > 0, "Ray dimension must be positive.");
42
43 // Constants for numerical computations
44 constexpr static Real EPS{std::numeric_limits<Real>::epsilon()};
45 constexpr static Real INF{std::numeric_limits<Real>::infinity()};
46 constexpr static Real DUMMY_TOL{EPS*static_cast<Real>(100.0)};
47
50
53
54 public:
60 ~Ray() = default;
61
67 Ray() = default;
68
74
80 Ray(Point const & o, Vector const & d) : m_origin(o), m_direction(d) {}
81
89 template <typename = std::enable_if<N == 1>>
90 Ray(Real const o, Real const d) : m_origin(o), m_direction(d) {}
91
101 template <typename = std::enable_if<N == 2>>
102 Ray(Real const o_x, Real const o_y, Real const d_x, Real const d_y)
103 : m_origin(o_x, o_y), m_direction(d_x, d_y) {}
104
116 template <typename = std::enable_if<N == 3>>
117 Ray(Real const o_x, Real const o_y, Real const o_z, Real const d_x, Real const d_y, Real const d_z)
118 : m_origin(o_x, o_y, o_z), m_direction(d_x, d_y, d_z) {}
119
125 template<typename OtherReal>
126 explicit Ray(Ray<OtherReal, N> const & r)
127 : m_origin(r.m_origin.template cast<Real>()), m_direction(r.m_direction.template cast<Real>()) {}
128
135 template<typename NewReal>
137 if constexpr (std::is_same<Real, NewReal>::value) {return *this;}
138 return Ray<NewReal, N>(m_origin.template cast<NewReal>(), m_direction.template cast<NewReal>());
139 }
140
145 Point & origin() {return m_origin;}
146
151 Point const & origin() const {return m_origin;}
152
158
163 Vector const & direction() const {return m_direction;}
164
169 Ray & normalize() {m_direction.normalize(); return *this;}
170
175 Ray normalized() const {return Ray(m_origin, m_direction.normalized());}
176
182 bool is_approx(Ray const & r, Real const tol = DUMMY_TOL) const
183 {return m_origin.isApprox(r.m_origin, tol) && m_direction.isApprox(r.m_direction, tol);}
184
190 Ray & translate(Vector const & t) {m_origin += t; return *this;}
191
197 Ray translated(Vector const & t) const {return Ray(m_origin + t, m_direction);}
198
205 template <typename Transform>
206 Ray transformed(Transform const & t) const
207 {return Ray(m_origin.transform(t), m_direction.rotate(t));}
208
215 template <typename Transform>
216 Ray & transform(Transform const & t) {
217 m_origin.transform(t);
218 m_direction.rotate(t);
219 return *this;
220 }
221
228 bool contains(Point const & p, Real tol = DUMMY_TOL) const {
229 Vector v((p - m_origin).normalized());
230 return std::abs(v.cross(m_direction).norm()) < tol && v.dot(m_direction) >= -tol;
231 }
232
239 bool intersects(Box<Real, N> const & b, Real tol = DUMMY_TOL) const {
240 if (b.contains(m_origin)) {return true;}
241 Point const & b_min{b.min()};
242 Point const & b_max{b.max()};
243 Vector t_min, t_max; t_min.setConstant(-INF), t_max.setConstant(INF);
244 for (Integer i{0}; i < N; ++i) {
245 if (std::abs(m_direction[i]) > tol) {
246 t_min[i] = (b_min[i] - m_origin[i])/m_direction[i];
247 t_max[i] = (b_max[i] - m_origin[i])/m_direction[i];
248 if (t_min[i] > t_max[i]) {std::swap(t_min[i], t_max[i]);}
249 } else if (m_origin[i] < b_min[i] || m_origin[i] > b_max[i]) {
250 return false;
251 }
252 }
253 Real t_entry{t_min.maxCoeff()};
254 Real t_exit{t_max.minCoeff()};
255 return t_entry <= t_exit && t_exit >= -tol;
256 }
257
266 bool intersect(Box<Real, N> const & b, Point & c, Point & f, Real tol = DUMMY_TOL) const {
267 if (b.contains(m_origin)) {return true;}
268 Point const & b_min{b.min()};
269 Point const & b_max{b.max()};
270 Vector t_min, t_max; t_min.setConstant(-INF), t_max.setConstant(INF);
271 for (Integer i{0}; i < N; ++i) {
272 if (std::abs(m_direction[i]) > tol) {
273 t_min[i] = (b_min[i] - m_origin[i])/m_direction[i];
274 t_max[i] = (b_max[i] - m_origin[i])/m_direction[i];
275 if (t_min[i] > t_max[i]) {std::swap(t_min[i], t_max[i]);}
276 } else if (m_origin[i] < b_min[i] || m_origin[i] > b_max[i]) {
277 return false;
278 }
279 }
280 Real t_entry{t_min.maxCoeff()};
281 Real t_exit{t_max.minCoeff()};
282 if (t_entry > t_exit && t_exit < -tol) {return false;}
283 c = m_origin + t_entry*m_direction;
284 f = m_origin + t_exit*m_direction;
285 return true;
286 }
287
294 Real squared_distance(Point const & p, Real tol = DUMMY_TOL) const {
295 Real t{(p - m_origin).dot(m_direction)/m_direction.squaredNorm()};
296 return (m_origin + std::max(static_cast<Real>(-tol), t) * m_direction - p).squaredNorm();
297 }
298
306 Real squared_distance(Point const & p, Point & c, Real tol = DUMMY_TOL) const
307 {
308 Real t{(p - m_origin).transpose().dot(m_direction)/m_direction.squaredNorm()};
309 c = m_origin + std::max(static_cast<Real>(-tol), t) * m_direction;
310 return (c - p).squaredNorm();
311 }
312
319 Real distance(Point const & p, Real tol = DUMMY_TOL) const
320 {return std::sqrt(this->squared_distance(p, tol));}
321
329 Real distance(Point const & p, Point & c, Real tol = DUMMY_TOL) const
330 {return std::sqrt(this->squared_distance(p, c, tol));}
331
332
340 Real squared_interior_distance(Box<Real, N> const & b, Real tol = DUMMY_TOL) const
341 { Point p1, p2; return this->squared_interior_distance(b, p1, p2, tol);}
342
353 Real squared_interior_distance(Box<Real, N> const & b, Point & p1, Point & p2, Real tol = DUMMY_TOL) const {
354 if (b.contains(m_origin)) {return 0.0;}
355 Point const & b_min{b.min()};
356 Point const & b_max{b.max()};
357
358 // Compute intersection parameters
359 Vector t_min, t_max; t_min.setConstant(-INF); t_max.setConstant(INF);
360 for (Integer i{0}; i < N; ++i) {
361 if (std::abs(m_direction[i]) > tol) {
362 t_min[i] = (b_min[i] - m_origin[i])/m_direction[i];
363 t_max[i] = (b_max[i] - m_origin[i])/m_direction[i];
364 if (t_min[i] > t_max[i]) {std::swap(t_min[i], t_max[i]);}
365 } else if (m_origin[i] < b_min[i] || m_origin[i] > b_max[i]) {
366 // Ray is parallel and outside the box and non-intersecting
368 Vector sides{b_max - b_min};
369 this->distance(p2, p1);
370 for (Integer j{0}; j < N; ++j){
371 if (j == i) {continue;}
372 if (m_direction[j] > 0.0) {p1[j] += 0.5*sides[j]; p2[j] += 0.5*sides[j];}
373 else {p1[j] -= 0.5*sides[j]; p2[j] -= 0.5*sides[j];}
374 }
375 return (p2 - m_origin).norm();
376 }
377 }
378
379 // Compute global intersection range
380 Real t_entry{t_min.maxCoeff()}, t_exit{t_max.minCoeff()};
381 if (t_entry <= t_exit && t_exit >= 0.0) {return 0.0;}
382
383 // Compute closest point if no intersection
384 for (Integer i{0}; i < N; ++i) {
385 if (m_origin[i] < b_min[i]) {p2[i] = b_min[i];}
386 else if (m_origin[i] > b_max[i]) {p2[i] = b_max[i];}
387 else {p2[i] = m_origin[i];}
388 }
389
390 // Project closest point onto the ray
391 Vector v(p2 - m_origin);
392 Real t_proj{ v.dot(m_direction)/m_direction.squaredNorm()};
393 if (t_proj < 0.0) {p1 = m_origin; return v.norm();}
394
395 p1 = m_origin + t_proj * m_direction;;
396 return (p2 - p1).squaredNorm();
397 }
398
406 Real interior_distance(Box<Real, N> const & b, Real tol = DUMMY_TOL) const
407 {return std::sqrt(this->squared_interior_distance(b, tol));}
408
419 Real interior_distance(Box<Real, N> const & b, Point & p1, Point & p2, Real tol = DUMMY_TOL) const
420 {return std::sqrt(static_cast<Real>(this->squared_interior_distance(b, p1, p2, tol)));}
421
429 Real squared_exterior_distance(Box<Real, N> const & b, Real tol = DUMMY_TOL) const
430 {Point p1, p2; return this->squared_exterior_distance(b, p1, p2, tol);}
431
441 Real squared_exterior_distance(Box<Real, N> const & b, Point & p1, Point & p2, Real tol = DUMMY_TOL)
442 const {
443 if (b.contains(m_origin)) {return 0.0;}
444 Point const & b_min{b.min()};
445 Point const & b_max{b.max()};
446
447 // Compute intersection parameters
448 Vector t_min, t_max; t_min.setConstant(-INF); t_max.setConstant(INF);
449 for (Integer i{0}; i < N; ++i) {
450 if (std::abs(m_direction[i]) > tol) {
451 t_min[i] = (b_min[i] - m_origin[i])/m_direction[i];
452 t_max[i] = (b_max[i] - m_origin[i])/m_direction[i];
453 if (t_min[i] > t_max[i]) {std::swap(t_min[i], t_max[i]);}
454 } else if (m_origin[i] < b_min[i] || m_origin[i] > b_max[i]) {
455 // Ray is parallel and outside the box and non-intersecting
457 Vector sides{b_max - b_min};
458 this->distance(p2, p1);
459 for (Integer j{0}; j < N; ++j){
460 if (j == i) {continue;}
461 if (m_direction[j] > 0.0) {p1[j] -= 0.5*sides[j]; p2[j] -= 0.5*sides[j];}
462 else {p1[j] += 0.5*sides[j]; p2[j] += 0.5*sides[j];}
463 }
464 return (p2 - m_origin).norm();
465 }
466 }
467
468 // Compute global intersection range
469 Real t_entry{t_min.maxCoeff()}, t_exit{t_max.minCoeff()};
470 if (t_entry <= t_exit && t_exit >= 0) {return 0.0;}
471
472 // Compute closest point if no intersection
473 for (Integer i{0}; i < N; ++i) {
474 if (m_origin[i] < b_min[i]) {p2[i] = b_max[i];}
475 else if (m_origin[i] > b_max[i]) {p2[i] = b_min[i];}
476 else {p2[i] = m_origin[i];}
477 }
478
479 // Project closest point onto the ray
480 Vector v(p2 - m_origin);
481 Real t_proj{v.dot(m_direction)/m_direction.squaredNorm()};
482 if (t_proj < 0.0) {p1 = m_origin; return v.norm();}
483
484 p1 = m_origin + t_proj * m_direction;;
485 return (p2 - p1).squaredNorm();
486 }
487
495 Real exterior_distance(Box<Real, N> const & b, Real tol = DUMMY_TOL) const
496 {return std::sqrt(this->squared_exterior_distance(b, tol));}
497
508 Real exterior_distance(Box<Real, N> const & b, Point & p1, Point & p2, Real tol = DUMMY_TOL) const
509 {return std::sqrt(this->squared_exterior_distance(b, p1, p2, tol));}
510
515 void print(std::ostream & os) const {
516 os <<
517 "────────────────────────────────────────────────────────────────────────────────\n" <<
518 "RAY INFO\n" <<
519 "\to = " << m_origin.transpose() << '\n' <<
520 "\td = " << m_direction.transpose() << '\n' <<
521 "────────────────────────────────────────────────────────────────────────────────\n";
522 }
523
524 }; // class Ray
525
533 template <typename Real, Integer N>
534 std::ostream & operator<<(std::ostream & os, Ray<Real, N> const & r) {r.print(os); return os;}
535
536} // namespace AABBtree
537
538#endif // AABBTREE_Ray_HXX
A class representing an axis-aligned bounding box (AABB) in N-dimensional space.
Definition Box.hxx:49
Real interior_distance(Point const &p) const
Definition Box.hxx:515
Real exterior_distance(Point const &p) const
Definition Box.hxx:569
bool contains(Point const &p) const
Definition Box.hxx:428
Point const & min() const
Definition Box.hxx:172
Point const & max() const
Definition Box.hxx:184
A mathematical ray in N-dimensional space.
Definition Ray.hxx:39
Point const & origin() const
Definition Ray.hxx:151
static constexpr Real DUMMY_TOL
Definition Ray.hxx:46
void print(std::ostream &os) const
Definition Ray.hxx:515
Vector const & direction() const
Definition Ray.hxx:163
Real distance(Point const &p, Real tol=DUMMY_TOL) const
Definition Ray.hxx:319
AABBtree::Point< Real, N > Point
Definition Ray.hxx:48
Real distance(Point const &p, Point &c, Real tol=DUMMY_TOL) const
Definition Ray.hxx:329
Vector m_direction
Definition Ray.hxx:52
Ray(Ray const &r)
Definition Ray.hxx:73
bool intersects(Box< Real, N > const &b, Real tol=DUMMY_TOL) const
Definition Ray.hxx:239
Ray & transform(Transform const &t)
Definition Ray.hxx:216
Ray translated(Vector const &t) const
Definition Ray.hxx:197
Real interior_distance(Box< Real, N > const &b, Point &p1, Point &p2, Real tol=DUMMY_TOL) const
Definition Ray.hxx:419
Ray normalized() const
Definition Ray.hxx:175
bool is_approx(Ray const &r, Real const tol=DUMMY_TOL) const
Definition Ray.hxx:182
Ray(Ray< OtherReal, N > const &r)
Definition Ray.hxx:126
Ray transformed(Transform const &t) const
Definition Ray.hxx:206
Vector & direction()
Definition Ray.hxx:157
Real squared_interior_distance(Box< Real, N > const &b, Real tol=DUMMY_TOL) const
Definition Ray.hxx:340
bool contains(Point const &p, Real tol=DUMMY_TOL) const
Definition Ray.hxx:228
Ray(Point const &o, Vector const &d)
Definition Ray.hxx:80
AABBtree::Vector< Real, N > Vector
Definition Ray.hxx:49
Ray(Real const o, Real const d)
Definition Ray.hxx:90
Ray()=default
Ray< NewReal, N > cast() const
Definition Ray.hxx:136
Real interior_distance(Box< Real, N > const &b, Real tol=DUMMY_TOL) const
Definition Ray.hxx:406
Point & origin()
Definition Ray.hxx:145
Point m_origin
Definition Ray.hxx:51
Ray(Real const o_x, Real const o_y, Real const o_z, Real const d_x, Real const d_y, Real const d_z)
Definition Ray.hxx:117
static constexpr Real INF
Definition Ray.hxx:45
Ray & normalize()
Definition Ray.hxx:169
bool intersect(Box< Real, N > const &b, Point &c, Point &f, Real tol=DUMMY_TOL) const
Definition Ray.hxx:266
Real squared_interior_distance(Box< Real, N > const &b, Point &p1, Point &p2, Real tol=DUMMY_TOL) const
Definition Ray.hxx:353
static constexpr Real EPS
Definition Ray.hxx:44
Ray(Real const o_x, Real const o_y, Real const d_x, Real const d_y)
Definition Ray.hxx:102
Real exterior_distance(Box< Real, N > const &b, Real tol=DUMMY_TOL) const
Definition Ray.hxx:495
Real squared_distance(Point const &p, Point &c, Real tol=DUMMY_TOL) const
Definition Ray.hxx:306
Real squared_exterior_distance(Box< Real, N > const &b, Real tol=DUMMY_TOL) const
Definition Ray.hxx:429
~Ray()=default
Real squared_exterior_distance(Box< Real, N > const &b, Point &p1, Point &p2, Real tol=DUMMY_TOL) const
Definition Ray.hxx:441
Real exterior_distance(Box< Real, N > const &b, Point &p1, Point &p2, Real tol=DUMMY_TOL) const
Definition Ray.hxx:508
Real squared_distance(Point const &p, Real tol=DUMMY_TOL) const
Definition Ray.hxx:294
Ray & translate(Vector const &t)
Definition Ray.hxx:190
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
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