Line data Source code
1 : #pragma once 2 : 3 : #include "elsaDefines.h" 4 : #include "BoundingBox.h" 5 : 6 : #include "spdlog/fmt/fmt.h" 7 : 8 : #include <Eigen/Geometry> 9 : #include <limits> 10 : #include <optional> 11 : #include <functional> 12 : 13 : namespace elsa 14 : { 15 : /** 16 : * @brief min helper function which behaves like the IEEE standard suggests 17 : * 18 : * @param[in] x first value to find minimum of 19 : * @param[in] y second value to find minimum of 20 : * @returns the smaller value of x and y 21 : * 22 : * This function is used, because it tries to suppress NaN's. This behavior is 23 : * crucial for edge cases of the intersection algorithm. std::min(x,y) does 24 : * not provide this security and should be avoided in this case 25 : */ 26 : template <typename T1, typename T2> 27 : constexpr T1 minNum(T1 x, T2 y) 28 260780 : { 29 260780 : return std::not_equal_to<>()(y, y) ? x : (std::less<>()(x, y) ? x : y); 30 260780 : } 31 : 32 : /** 33 : * @brief max helper function which behaves like the IEEE standard suggests 34 : * 35 : * @param[in] x first value to find maximum of 36 : * @param[in] y second value to find maximum of 37 : * @returns the bigger value of x and y 38 : * 39 : * Same thing for NaN's as for the min function 40 : */ 41 : template <typename T1, typename T2> 42 : constexpr T1 maxNum(T1 x, T2 y) 43 496219 : { 44 496219 : return std::not_equal_to<>()(y, y) ? x : (std::greater<>()(x, y) ? x : y); 45 496219 : } 46 : 47 : /** 48 : * @brief Helper struct for results of intersection tests 49 : */ 50 : template <class data_t> 51 : struct IntersectionResult { 52 : /// the parameters for entry/exit points 53 : data_t _tmin, _tmax; 54 : 55 : /// default constructor 56 : IntersectionResult() 57 : : _tmin{std::numeric_limits<data_t>::infinity()}, 58 : _tmax{std::numeric_limits<data_t>::infinity()} 59 0 : { 60 0 : } 61 : 62 : /// simple constructor with values tmin, tmax 63 225794 : IntersectionResult(data_t tmin, data_t tmax) : _tmin{tmin}, _tmax{tmax} {} 64 : }; 65 : 66 : namespace detail 67 : { 68 : template <class data_t, int Dim> 69 : std::tuple<data_t, data_t, data_t, data_t> 70 : intersect(const BoundingBox& aabb, const Eigen::ParametrizedLine<data_t, Dim>& r); 71 : } // namespace detail 72 : 73 : /** 74 : * @brief Compute entry and exit point of ray in a volume (given as an AABB) 75 : * 76 : * If the ray is running along a border of the bounding box, the lower bound will 77 : * be counted as in the bounding and the upper bound will be counted as outside. 78 : * 79 : * Method adapted from 80 : * https://tavianator.com/fast-branchless-raybounding-box-intersections-part-2-nans/ 81 : * 82 : * @param[in] aabb the volume specified through an axis-aligned bounding box 83 : * @param[in] r the ray which we test for intersection with aabb 84 : * 85 : * @returns nullopt if the volume is not hit, otherwise IntersectionResult 86 : * with entry/exit parameters tmin/tmax 87 : */ 88 : template <class data_t, int Dim> 89 : std::optional<IntersectionResult<data_t>> 90 : intersectRay(const BoundingBox& aabb, const Eigen::ParametrizedLine<data_t, Dim>& r); 91 : 92 : /** 93 : * @brief Compute the intersection of a ray with the nearest x-plane 94 : * 95 : * @param[in] aabb the volume specified through an axis-aligned bounding box 96 : * @param[in] r the ray which we test for intersection with aabb 97 : * 98 : * @returns nullopt if the volume is not hit, otherwise IntersectionResult 99 : * with entry/exit parameters tmin/tmax 100 : */ 101 : template <class data_t, int Dim> 102 : std::optional<IntersectionResult<data_t>> 103 : intersectXPlanes(BoundingBox aabb, const Eigen::ParametrizedLine<data_t, Dim>& r); 104 : } // namespace elsa 105 : 106 : template <class data_t> 107 : struct fmt::formatter<elsa::IntersectionResult<data_t>> { 108 : template <typename ParseContext> 109 : constexpr auto parse(ParseContext& ctx) 110 0 : { 111 0 : return ctx.begin(); 112 0 : } 113 : 114 : template <typename FormatContext> 115 : auto format(const elsa::IntersectionResult<data_t>& hit, FormatContext& ctx) 116 0 : { 117 0 : return fmt::format_to(ctx.out(), "{{ tmin: {}, tmax: {} }}", hit._tmin, hit._tmax); 118 0 : } 119 : };