File indexing completed on 2026-05-27 07:24:12
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/builders/surface_factory_interface.hpp"
0013 #include "detray/core/detail/data_context.hpp"
0014 #include "detray/definitions/detail/qualifiers.hpp"
0015 #include "detray/definitions/geometry.hpp"
0016 #include "detray/definitions/indexing.hpp"
0017 #include "detray/geometry/mask.hpp"
0018 #include "detray/geometry/shapes/rectangle2D.hpp"
0019 #include "detray/tracks/ray.hpp"
0020 #include "detray/utils/axis_rotation.hpp"
0021 #include "detray/utils/logging.hpp"
0022 #include "detray/utils/unit_vectors.hpp"
0023
0024
0025 #include <cassert>
0026 #include <limits>
0027
0028 namespace detray {
0029
0030
0031
0032
0033 template <typename detector_t, typename mask_shape_t = rectangle2D,
0034 typename trajectory_t =
0035 detail::ray<typename detector_t::algebra_type>>
0036 class telescope_generator final : public surface_factory_interface<detector_t> {
0037 using algebra_t = typename detector_t::algebra_type;
0038 using scalar_t = dscalar<algebra_t>;
0039 using transform3_t = dtransform3D<algebra_t>;
0040 using point3_t = dpoint3D<algebra_t>;
0041 using vector3_t = dvector3D<algebra_t>;
0042
0043 public:
0044
0045
0046 DETRAY_HOST
0047 telescope_generator(
0048 std::vector<scalar_t> positions,
0049 const darray<scalar_t, mask_shape_t::boundaries::e_size> &boundaries,
0050 trajectory_t traj)
0051 : m_traj{traj},
0052 m_positions{std::move(positions)},
0053 m_boundaries{boundaries} {}
0054
0055
0056
0057
0058
0059
0060 DETRAY_HOST
0061 telescope_generator(
0062 scalar_t length, std::size_t n_surfaces,
0063 darray<scalar_t, mask_shape_t::boundaries::e_size> boundaries,
0064 trajectory_t traj)
0065 : m_traj{traj}, m_positions{}, m_boundaries{boundaries} {
0066 scalar_t pos{0.f};
0067 scalar_t dist{n_surfaces > 1u
0068 ? length / static_cast<scalar_t>(n_surfaces - 1u)
0069 : 0.f};
0070 for (std::size_t i = 0u; i < n_surfaces; ++i) {
0071 m_positions.push_back(pos);
0072 pos += dist;
0073 }
0074 }
0075
0076
0077 DETRAY_HOST
0078 auto size() const -> dindex override {
0079 return static_cast<dindex>(m_positions.size());
0080 }
0081
0082
0083 DETRAY_HOST
0084 void clear() override {
0085 m_positions.clear();
0086 m_boundaries = {};
0087 };
0088
0089
0090
0091 DETRAY_HOST
0092 void push_back(
0093 surface_data<detector_t> && ) override { }
0094 DETRAY_HOST
0095 auto push_back(std::vector<surface_data<detector_t>> && )
0096 -> void override { }
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 DETRAY_HOST
0107 auto operator()(typename detector_t::volume_type &volume,
0108 typename detector_t::surface_lookup_container &surfaces,
0109 typename detector_t::transform_container &transforms,
0110 typename detector_t::mask_container &masks,
0111 typename detector_t::geometry_context ctx = {})
0112 -> dindex_range override {
0113 DETRAY_VERBOSE_HOST("Generate telescope modules...");
0114 DETRAY_VERBOSE_HOST("-> Generate " << size() << " surfaces");
0115
0116 using surface_t = typename detector_t::surface_type;
0117 using nav_link_t = typename surface_t::navigation_link;
0118 using mask_link_t = typename surface_t::mask_link;
0119 using material_link_t = typename surface_t::material_link;
0120
0121 const dindex surfaces_offset{static_cast<dindex>(surfaces.size())};
0122 constexpr auto invalid_src_link{detail::invalid_value<std::uint64_t>()};
0123
0124
0125 constexpr auto mask_id{
0126 types::id<typename detector_t::masks, mask<mask_shape_t, algebra_t>>};
0127
0128
0129 constexpr auto no_material{surface_t::material_id::e_none};
0130
0131 auto volume_idx{volume.index()};
0132
0133
0134 const auto mod_placements = module_positions(m_traj, m_positions);
0135
0136
0137 for (const auto &mod_placement : mod_placements) {
0138 auto mask_volume_link{static_cast<nav_link_t>(volume_idx)};
0139
0140
0141 mask_link_t mask_link{mask_id, masks.template size<mask_id>()};
0142 material_link_t material_link{no_material, dindex_invalid};
0143
0144 const auto trf_index = transforms.size(ctx);
0145 surfaces.push_back({trf_index, mask_link, material_link, volume_idx,
0146 surface_id::e_sensitive},
0147 invalid_src_link);
0148
0149
0150 masks.template emplace_back<mask_id>(empty_context{}, m_boundaries,
0151 mask_volume_link);
0152
0153
0154
0155 vector3_t m_local_z = vector::normalize(mod_placement.dir);
0156
0157 if constexpr (std::is_same_v<mask_shape_t, detray::line_square> ||
0158 std::is_same_v<mask_shape_t, detray::line_circular>) {
0159
0160
0161 auto curvi_u =
0162 unit_vectors<vector3_t>().make_curvilinear_unit_u(m_local_z);
0163 axis_rotation<algebra_t> axis_rot(curvi_u,
0164 -constant<scalar_t>::pi / 2.f);
0165 m_local_z = axis_rot(m_local_z);
0166 }
0167
0168
0169 auto m_local_x =
0170 unit_vectors<vector3_t>().make_curvilinear_unit_u(m_local_z);
0171
0172
0173 transforms.emplace_back(ctx, mod_placement.pos, m_local_z, m_local_x);
0174 }
0175
0176 return {surfaces_offset, static_cast<dindex>(surfaces.size())};
0177 }
0178
0179 private:
0180
0181 struct module_placement {
0182
0183 point3_t pos;
0184
0185 vector3_t dir;
0186 };
0187
0188
0189
0190
0191
0192
0193
0194
0195 inline std::vector<module_placement> module_positions(
0196 const trajectory_t &traj, const std::vector<scalar_t> &steps) const {
0197
0198 std::vector<module_placement> placements;
0199 placements.reserve(steps.size());
0200
0201 for (const auto s : steps) {
0202 placements.push_back({traj.pos(s), traj.dir(s)});
0203 }
0204
0205 return placements;
0206 }
0207
0208
0209 trajectory_t m_traj;
0210
0211 std::vector<scalar_t> m_positions;
0212
0213 darray<scalar_t, mask_shape_t::boundaries::e_size> m_boundaries;
0214 };
0215
0216 }