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/algorithms.hpp"
0014 #include "detray/definitions/detail/qualifiers.hpp"
0015 #include "detray/definitions/units.hpp"
0016 #include "detray/geometry/concepts.hpp"
0017 #include "detray/navigation/intersection/intersection.hpp"
0018 #include "detray/navigation/intersection/intersection_config.hpp"
0019 #include "detray/tracks/ray.hpp"
0020 #include "detray/utils/ranges.hpp"
0021
0022 namespace detray::detail {
0023
0024
0025 template <template <typename, typename, bool> class intersector_t>
0026 struct intersection_initialize {
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 template <typename mask_group_t, typename mask_range_t,
0046 typename is_container_t, typename traj_t, typename surface_t,
0047 typename transform_container_t, concepts::scalar scalar_t>
0048 DETRAY_HOST_DEVICE inline void operator()(
0049 const mask_group_t &mask_group, const mask_range_t &mask_range,
0050 is_container_t &is_container, const traj_t &traj,
0051 const surface_t &sf_desc,
0052 const transform_container_t &contextual_transforms,
0053 const typename transform_container_t::context_type &ctx,
0054 const intersection::config &cfg,
0055 const scalar_t external_mask_tolerance = 0.f) const {
0056 using mask_t = typename mask_group_t::value_type;
0057 using shape_t = typename mask_t::shape;
0058 using algebra_t = typename mask_t::algebra_type;
0059 using intersection_t = typename is_container_t::value_type;
0060
0061
0062 const auto &ctf = contextual_transforms.at(sf_desc.transform(), ctx);
0063
0064 constexpr intersector_t<shape_t, algebra_t, intersection_t::contains_pos()>
0065 intersector{};
0066
0067 constexpr std::uint8_t n_sol{decltype(intersector)::n_solutions};
0068
0069 typename decltype(intersector)::result_type result{};
0070
0071 if constexpr (concepts::cylindrical<mask_t>) {
0072 std::size_t mask_idx{detail::invalid_value<std::size_t>()};
0073 if constexpr (concepts::interval<mask_range_t>) {
0074 mask_idx = mask_range.lower();
0075 } else {
0076 mask_idx = mask_range;
0077 }
0078 assert(mask_idx < mask_group.size());
0079
0080 result = intersector.point_of_intersection(
0081 traj, ctf, mask_group[mask_idx], cfg.overstep_tolerance);
0082 } else {
0083 result =
0084 intersector.point_of_intersection(traj, ctf, cfg.overstep_tolerance);
0085 }
0086
0087
0088 if constexpr (n_sol > 1) {
0089 bool found_any{false};
0090 for (const auto &ip : result) {
0091 if (ip.is_valid()) {
0092 found_any = true;
0093 }
0094 }
0095 if (!found_any) [[unlikely]] {
0096 return;
0097 }
0098 } else {
0099 if (!result.is_valid()) [[unlikely]] {
0100 return;
0101 }
0102 }
0103
0104
0105 for (const auto &mask : detray::ranges::subrange(mask_group, mask_range)) {
0106 intersection_t is{};
0107
0108
0109 if constexpr (n_sol > 1) {
0110 std::uint8_t n_found{0u};
0111
0112 for (std::size_t i = 0u; i < n_sol; ++i) {
0113 resolve_mask(is, traj, result[i], sf_desc, mask, ctf, cfg,
0114 external_mask_tolerance);
0115
0116 if (is.is_probably_inside()) {
0117 insert_sorted(is, is_container);
0118 ++n_found;
0119 }
0120 if (n_found == n_sol) {
0121 return;
0122 }
0123 }
0124 } else {
0125 resolve_mask(is, traj, result, sf_desc, mask, ctf, cfg,
0126 external_mask_tolerance);
0127
0128 if (is.is_probably_inside()) {
0129 insert_sorted(is, is_container);
0130 return;
0131 }
0132 }
0133 }
0134 }
0135
0136 template <typename intersection_t>
0137 DETRAY_HOST_DEVICE void insert_sorted(
0138 const intersection_t &sfi,
0139 std::vector<intersection_t> &intersections) const {
0140 auto itr_pos =
0141 detray::upper_bound(intersections.cbegin(), intersections.cend(), sfi);
0142
0143 intersections.insert(itr_pos, sfi);
0144 }
0145
0146
0147 template <typename nav_state_t>
0148 DETRAY_HOST_DEVICE void insert_sorted(
0149 const typename nav_state_t::value_type &sfi,
0150 nav_state_t &intersections) const {
0151 auto itr_pos{intersections.cbegin()};
0152
0153
0154
0155 if constexpr (nav_state_t::capacity() > 2u) {
0156 itr_pos = detray::upper_bound(intersections.cbegin(),
0157 intersections.cend(), sfi);
0158 }
0159
0160 intersections.insert(itr_pos, sfi);
0161 }
0162 };
0163
0164
0165
0166 template <template <typename, typename, bool> class intersector_t>
0167 struct intersection_update {
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186 template <typename mask_group_t, typename mask_range_t, typename traj_t,
0187 typename intersection_t, typename transform_container_t,
0188 concepts::scalar scalar_t>
0189 DETRAY_HOST_DEVICE inline bool operator()(
0190 const mask_group_t &mask_group, const mask_range_t &mask_range,
0191 const traj_t &traj, intersection_t &sfi,
0192 const transform_container_t &contextual_transforms,
0193 const typename transform_container_t::context_type &ctx,
0194 const intersection::config &cfg,
0195 const scalar_t external_mask_tolerance = 0.f) const {
0196 using mask_t = typename mask_group_t::value_type;
0197 using shape_t = typename mask_t::shape;
0198 using algebra_t = typename mask_t::algebra_type;
0199
0200
0201 const auto &ctf = contextual_transforms.at(sfi.surface().transform(), ctx);
0202
0203 constexpr intersector_t<shape_t, algebra_t, intersection_t::contains_pos()>
0204 intersector{};
0205 constexpr std::uint8_t n_sol{decltype(intersector)::n_solutions};
0206
0207 typename decltype(intersector)::result_type result{};
0208
0209 if constexpr (concepts::cylindrical<mask_t>) {
0210 std::size_t mask_idx{detail::invalid_value<std::size_t>()};
0211 if constexpr (concepts::interval<mask_range_t>) {
0212 mask_idx = mask_range.lower();
0213 } else {
0214 mask_idx = mask_range;
0215 }
0216 assert(mask_idx < mask_group.size());
0217
0218 result = intersector.point_of_intersection(
0219 traj, ctf, mask_group[mask_idx], cfg.overstep_tolerance);
0220 } else {
0221 result =
0222 intersector.point_of_intersection(traj, ctf, cfg.overstep_tolerance);
0223 }
0224
0225
0226 if constexpr (n_sol > 1) {
0227 bool found_any{false};
0228 for (const auto &ip : result) {
0229 if (ip.is_valid()) {
0230 found_any = true;
0231 }
0232 }
0233 if (!found_any) [[unlikely]] {
0234 return false;
0235 }
0236 } else {
0237 if (!result.is_valid()) [[unlikely]] {
0238 return false;
0239 }
0240 }
0241
0242
0243 for (const auto &mask : detray::ranges::subrange(mask_group, mask_range)) {
0244
0245 if constexpr (n_sol > 1) {
0246 resolve_mask(sfi, traj, result[0], sfi.surface(), mask, ctf, cfg,
0247 external_mask_tolerance);
0248 } else {
0249 resolve_mask(sfi, traj, result, sfi.surface(), mask, ctf, cfg,
0250 external_mask_tolerance);
0251 }
0252
0253 if (sfi.is_probably_inside()) {
0254 return true;
0255 }
0256 }
0257
0258 return false;
0259 }
0260 };
0261
0262 }