File indexing completed on 2026-05-27 07:24:00
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/definitions/algebra.hpp"
0013 #include "detray/definitions/detail/qualifiers.hpp"
0014 #include "detray/definitions/indexing.hpp"
0015 #include "detray/definitions/math.hpp"
0016 #include "detray/definitions/units.hpp"
0017 #include "detray/utils/invalid_values.hpp"
0018
0019
0020 #include <cstdint>
0021 #include <limits>
0022 #include <ostream>
0023
0024 namespace detray {
0025
0026 namespace intersection {
0027
0028
0029 inline constexpr bool contains_pos{true};
0030
0031
0032 enum class status : std::uint_least8_t {
0033 e_inside = 0u,
0034 e_edge = 1u,
0035 e_outside = 2u,
0036 };
0037
0038 }
0039
0040
0041 template <concepts::algebra algebra_t, concepts::point point_t,
0042 bool has_pos = true>
0043 struct intersection_point {};
0044
0045
0046 template <concepts::algebra algebra_t, concepts::point point_t>
0047 struct intersection_point<algebra_t, point_t, !intersection::contains_pos> {
0048 using scalar_type = dscalar<algebra_t>;
0049
0050
0051 static consteval bool contains_pos() { return !intersection::contains_pos; }
0052
0053
0054 scalar_type path = detail::invalid_value<dvalue<algebra_t>>();
0055
0056
0057 constexpr bool is_valid() const {
0058 constexpr auto inv_path{10.f * unit<dvalue<algebra_t>>::m};
0059 return detray::detail::any_of(math::fabs(path) < inv_path);
0060 }
0061
0062
0063 DETRAY_HOST
0064 friend std::ostream &operator<<(std::ostream &out_stream,
0065 const intersection_point &ip) {
0066 out_stream << "dist:" << ip.path;
0067
0068 return out_stream;
0069 }
0070 };
0071
0072
0073 template <concepts::algebra algebra_t, concepts::point point_t>
0074 struct intersection_point<algebra_t, point_t, intersection::contains_pos>
0075 : public intersection_point<algebra_t, point_t,
0076 !intersection::contains_pos> {
0077 private:
0078 using base_type =
0079 intersection_point<algebra_t, point_t, !intersection::contains_pos>;
0080
0081 public:
0082 using scalar_type = dscalar<algebra_t>;
0083 using point_type = point_t;
0084
0085 constexpr intersection_point() = default;
0086
0087 DETRAY_HOST_DEVICE
0088 explicit constexpr intersection_point(const base_type ip) : base_type{ip} {}
0089
0090 DETRAY_HOST_DEVICE
0091 constexpr intersection_point(const scalar_type p, const point_type &pnt)
0092 : base_type{p}, point{pnt} {}
0093
0094
0095 static consteval bool contains_pos() { return intersection::contains_pos; }
0096
0097
0098 point_type point{init_point()};
0099
0100
0101 DETRAY_HOST
0102 friend std::ostream &operator<<(std::ostream &out_stream,
0103 const intersection_point &ip) {
0104 using base_t =
0105 intersection_point<algebra_t, point_t, !intersection::contains_pos>;
0106
0107 out_stream << static_cast<base_t>(ip);
0108
0109 out_stream << ", point [" << ip.point[0] << ", " << ip.point[1];
0110
0111 if constexpr (std::same_as<point_t, dpoint3D<algebra_t>>) {
0112 out_stream << ", " << ip.point[2] << "]";
0113 } else {
0114 out_stream << "]";
0115 }
0116
0117 return out_stream;
0118 }
0119
0120 private:
0121
0122 DETRAY_HOST_DEVICE
0123 constexpr point_t init_point() const {
0124 constexpr auto inv{detail::invalid_value<dvalue<algebra_t>>()};
0125 if constexpr (std::same_as<point_t, dpoint2D<algebra_t>>) {
0126 return {inv, inv};
0127 } else if constexpr (std::same_as<point_t, dpoint3D<algebra_t>>) {
0128 return {inv, inv, inv};
0129 } else {
0130 assert(false);
0131 return {};
0132 }
0133 }
0134 };
0135
0136
0137
0138 template <concepts::algebra algebra_t>
0139 struct intersection_point_err
0140 : public intersection_point<algebra_t, dpoint3D<algebra_t>,
0141 intersection::contains_pos> {
0142 private:
0143 using base_type = intersection_point<algebra_t, dpoint3D<algebra_t>,
0144 intersection::contains_pos>;
0145
0146 static constexpr auto inv{detail::invalid_value<dscalar<algebra_t>>()};
0147
0148 public:
0149 using scalar_type = dscalar<algebra_t>;
0150 using point3_type = dpoint3D<algebra_t>;
0151 using point2_type = dpoint2D<algebra_t>;
0152 using point_type = point3_type;
0153
0154 constexpr intersection_point_err() = default;
0155
0156 DETRAY_HOST_DEVICE
0157 explicit constexpr intersection_point_err(const base_type &base_ip)
0158 : base_type{base_ip} {}
0159
0160 DETRAY_HOST_DEVICE
0161 explicit constexpr intersection_point_err(
0162 const intersection_point<algebra_t, point3_type,
0163 !intersection::contains_pos> &ip)
0164 : base_type{ip.path, point3_type{inv, inv, inv}} {}
0165
0166 DETRAY_HOST_DEVICE
0167 explicit constexpr intersection_point_err(
0168 const intersection_point<algebra_t, point2_type,
0169 !intersection::contains_pos> &ip)
0170 : base_type{ip.path, point3_type{inv, inv, inv}} {}
0171
0172 DETRAY_HOST_DEVICE
0173 constexpr intersection_point_err(const scalar_type p, const point3_type &pnt,
0174 const scalar_type p_err)
0175 : base_type{p, pnt}, path_err{p_err} {}
0176
0177
0178 scalar_type path_err{inv};
0179 };
0180
0181
0182
0183
0184
0185
0186 template <typename surface_t, concepts::algebra algebra_t,
0187 bool has_pos = intersection::contains_pos>
0188 class intersection2D {
0189 using T = dvalue<algebra_t>;
0190 using bool_type = dbool<algebra_t>;
0191 using scalar_type = dscalar<algebra_t>;
0192 using point2_type = dpoint2D<algebra_t>;
0193 using point3_type = dpoint3D<algebra_t>;
0194 using vector3_type = dvector3D<algebra_t>;
0195
0196 public:
0197 using algebra_type = algebra_t;
0198 using surface_type = surface_t;
0199
0200
0201
0202
0203 using status_type =
0204 std::conditional_t<concepts::soa<algebra_t>, T, intersection::status>;
0205 using nav_link_type = typename surface_type::navigation_link;
0206
0207
0208 constexpr intersection2D() = default;
0209
0210
0211 template <bool B = has_pos>
0212 requires B
0213 DETRAY_HOST_DEVICE constexpr intersection2D(
0214 const surface_type &sf, const scalar_type path, const point3_type &local,
0215 const nav_link_type nl, const dsimd<algebra_t, status_type> status,
0216 const bool_type dir)
0217 : m_surface{sf},
0218 m_ip{path, local},
0219 m_volume_link{nl},
0220 m_status{status},
0221 m_direction{dir} {}
0222
0223
0224 template <bool B = has_pos>
0225 requires(!B)
0226 DETRAY_HOST_DEVICE constexpr intersection2D(
0227 const surface_type &sf, const scalar_type path, const nav_link_type nl,
0228 const dsimd<algebra_t, status_type> status, const bool_type dir)
0229 : m_surface{sf},
0230 m_ip{path},
0231 m_volume_link{nl},
0232 m_status{status},
0233 m_direction{dir} {}
0234
0235
0236 static consteval bool contains_pos() { return has_pos; }
0237
0238
0239 DETRAY_HOST_DEVICE
0240 constexpr surface_type surface() const { return m_surface; }
0241
0242
0243 DETRAY_HOST_DEVICE
0244 constexpr surface_type &surface() { return m_surface; }
0245
0246
0247 DETRAY_HOST_DEVICE
0248 constexpr void set_surface(const surface_type sf) { m_surface = sf; }
0249
0250
0251 DETRAY_HOST_DEVICE
0252 constexpr nav_link_type volume_link() const { return m_volume_link; }
0253
0254
0255 DETRAY_HOST_DEVICE
0256 constexpr void set_volume_link(const nav_link_type nl) { m_volume_link = nl; }
0257
0258
0259 DETRAY_HOST_DEVICE
0260 constexpr bool_type is_along() const { return m_direction; }
0261
0262
0263 DETRAY_HOST_DEVICE
0264 constexpr void set_direction(const bool_type dir) { m_direction = dir; }
0265
0266
0267 DETRAY_HOST_DEVICE
0268 constexpr scalar_type path() const { return m_ip.path; }
0269
0270
0271 DETRAY_HOST_DEVICE
0272 constexpr void set_path(scalar_type p) { m_ip.path = p; }
0273
0274
0275 template <bool B = has_pos>
0276 requires B
0277 DETRAY_HOST_DEVICE constexpr point3_type local() const {
0278 return m_ip.point;
0279 }
0280
0281
0282 template <bool B = has_pos>
0283 requires B
0284 DETRAY_HOST_DEVICE constexpr void set_local(const point3_type p) {
0285 m_ip.point = p;
0286 }
0287
0288
0289 DETRAY_HOST_DEVICE
0290 constexpr dsimd<algebra_t, status_type> status() const { return m_status; }
0291
0292
0293 DETRAY_HOST_DEVICE
0294 constexpr void set_status(intersection::status s) {
0295 m_status = static_cast<status_type>(s);
0296 }
0297
0298
0299 DETRAY_HOST_DEVICE
0300 constexpr void set_status_if(intersection::status s,
0301 dbool<algebra_t> result_mask) {
0302
0303 if constexpr (concepts::soa<algebra_t>) {
0304 m_status(result_mask) = static_cast<status_type>(s);
0305 } else {
0306 m_status = result_mask ? static_cast<status_type>(s) : m_status;
0307 }
0308 }
0309
0310
0311
0312
0313 DETRAY_HOST_DEVICE
0314 friend constexpr bool_type operator<(const intersection2D &lhs,
0315 const intersection2D &rhs) noexcept {
0316 return (math::fabs(lhs.path()) < math::fabs(rhs.path()));
0317 }
0318
0319
0320 DETRAY_HOST_DEVICE
0321 friend constexpr bool_type operator<=(const intersection2D &lhs,
0322 const intersection2D &rhs) noexcept {
0323 return (math::fabs(lhs.path()) <= math::fabs(rhs.path()));
0324 }
0325
0326
0327 DETRAY_HOST_DEVICE
0328 friend constexpr bool_type operator>(const intersection2D &lhs,
0329 const intersection2D &rhs) noexcept {
0330 return (math::fabs(lhs.path()) > math::fabs(rhs.path()));
0331 }
0332
0333
0334 DETRAY_HOST_DEVICE
0335 friend constexpr bool_type operator>=(const intersection2D &lhs,
0336 const intersection2D &rhs) noexcept {
0337 return (math::fabs(lhs.path()) > math::fabs(rhs.path()));
0338 }
0339
0340
0341
0342 DETRAY_HOST_DEVICE
0343 friend constexpr bool_type operator==(const intersection2D &lhs,
0344 const intersection2D &rhs) noexcept {
0345 return math::fabs(lhs.path() - rhs.path()) <
0346 std::numeric_limits<float>::epsilon();
0347 }
0348
0349
0350 DETRAY_HOST_DEVICE
0351 constexpr bool is_inside() const {
0352 const dsimd<algebra_t, status_type> comp(
0353 static_cast<status_type>(intersection::status::e_inside));
0354 return detail::any_of(this->m_status == comp);
0355 }
0356
0357
0358 DETRAY_HOST_DEVICE
0359 constexpr bool is_edge() const {
0360 const dsimd<algebra_t, status_type> comp(
0361 static_cast<status_type>(intersection::status::e_edge));
0362 return detail::any_of(this->m_status == comp);
0363 }
0364
0365
0366 DETRAY_HOST_DEVICE
0367 constexpr bool is_probably_inside() const {
0368 const dsimd<algebra_t, status_type> comp(
0369 static_cast<status_type>(intersection::status::e_edge));
0370 return detail::any_of(this->m_status <= comp);
0371 }
0372
0373
0374 DETRAY_HOST_DEVICE
0375 constexpr bool is_outside() const {
0376 const dsimd<algebra_t, status_type> comp(
0377 static_cast<status_type>(intersection::status::e_outside));
0378 return detail::all_of(this->m_status == comp);
0379 }
0380
0381 private:
0382
0383 DETRAY_HOST
0384 friend std::ostream &operator<<(std::ostream &out_stream,
0385 const intersection2D &is) {
0386 out_stream << is.m_ip << ", "
0387 << ", surface: " << is.surface().identifier()
0388 << ", type: " << static_cast<int>(is.surface().mask().id())
0389 << ", links to vol:" << is.volume_link() << ")";
0390
0391 if (is.is_inside()) {
0392 out_stream << ", status: inside";
0393 } else if (is.is_edge()) {
0394 out_stream << ", status: edge";
0395 } else {
0396 out_stream << ", status: outside";
0397 }
0398 if constexpr (std::is_scalar_v<bool_type>) {
0399 out_stream << (is.is_along() ? ", direction: along"
0400 : ", direction: opposite");
0401 } else {
0402 out_stream << ", status: " << is.status();
0403 out_stream << ", direction: " << is.is_along();
0404 }
0405
0406 return out_stream;
0407 }
0408
0409
0410 surface_type m_surface{};
0411
0412
0413 intersection_point<algebra_type, dpoint3D<algebra_type>, has_pos> m_ip{};
0414
0415
0416 nav_link_type m_volume_link{detail::invalid_value<nav_link_type>()};
0417
0418
0419 dsimd<algebra_t, status_type> m_status =
0420 static_cast<status_type>(intersection::status::e_outside);
0421
0422
0423
0424 bool_type m_direction{true};
0425 };
0426
0427 }