File indexing completed on 2026-05-27 07:23:58
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/definitions/algebra.hpp"
0013 #include "detray/definitions/containers.hpp"
0014 #include "detray/definitions/detail/qualifiers.hpp"
0015 #include "detray/definitions/indexing.hpp"
0016 #include "detray/definitions/math.hpp"
0017 #include "detray/definitions/units.hpp"
0018 #include "detray/geometry/coordinates/cartesian3D.hpp"
0019 #include "detray/geometry/coordinates/line2D.hpp"
0020 #include "detray/geometry/detail/shape_utils.hpp"
0021
0022
0023 #include <limits>
0024 #include <ostream>
0025 #include <string_view>
0026 #include <type_traits>
0027
0028 namespace detray {
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 template <bool kSquareCrossSect = false>
0040 class line {
0041 public:
0042
0043 static constexpr std::string_view name = "line";
0044
0045
0046 static constexpr bool square_cross_sect = kSquareCrossSect;
0047
0048 enum boundaries : unsigned int {
0049 e_cross_section = 0u,
0050 e_half_z = 1u,
0051 e_size = 2u
0052 };
0053
0054
0055 template <concepts::scalar scalar_t>
0056 using bounds_type = darray<scalar_t, boundaries::e_size>;
0057
0058
0059 template <concepts::algebra algebra_t>
0060 using local_frame_type = line2D<algebra_t>;
0061
0062
0063 template <typename bool_t>
0064 using result_type = detail::boundary_check_result<bool_t>;
0065
0066
0067 static constexpr std::size_t dim{2u};
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 template <concepts::scalar scalar_t, concepts::point point_t>
0079 DETRAY_HOST_DEVICE inline scalar_t min_dist_to_boundary(
0080 const bounds_type<scalar_t> &bounds, const point_t &loc_p) const {
0081 if constexpr (square_cross_sect) {
0082 const scalar_t dist_x = math::fabs(
0083 math::fabs(loc_p[0] * math::cos(loc_p[2])) - bounds[e_cross_section]);
0084 const scalar_t dist_y = math::fabs(
0085 math::fabs(loc_p[0] * math::sin(loc_p[2])) - bounds[e_cross_section]);
0086 const scalar_t dist_z =
0087 math::fabs(math::fabs(loc_p[1]) - bounds[e_half_z]);
0088
0089 return math::min(math::min(dist_x, dist_y), dist_z);
0090
0091 } else {
0092 return math::min(
0093 math::fabs(math::fabs(loc_p[0]) - bounds[e_cross_section]),
0094 math::fabs(math::fabs(loc_p[1]) - bounds[e_half_z]));
0095 }
0096 }
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 template <concepts::algebra algebra_t>
0107 DETRAY_HOST_DEVICE constexpr result_type<dbool<algebra_t>> check_boundaries(
0108 const bounds_type<dscalar<algebra_t>> &bounds,
0109 const dtransform3D<algebra_t> &trf, const dpoint3D<algebra_t> &glob_p,
0110 const dscalar<algebra_t> tol =
0111 std::numeric_limits<dscalar<algebra_t>>::epsilon(),
0112 const dscalar<algebra_t> edge_tol = 0.f) const {
0113 const auto loc_3D{cartesian3D<algebra_t>::global_to_local(trf, glob_p, {})};
0114
0115 if constexpr (square_cross_sect) {
0116 using scalar_t = dscalar<algebra_t>;
0117
0118 const scalar_t loc_0{math::fabs(loc_3D[0])};
0119 const scalar_t loc_1{math::fabs(loc_3D[1])};
0120 const scalar_t loc_2{math::fabs(loc_3D[2])};
0121
0122
0123 auto inside_mask{(loc_0 <= (bounds[e_cross_section] + tol) &&
0124 loc_1 <= (bounds[e_cross_section] + tol) &&
0125 loc_2 <= (bounds[e_half_z] + tol))};
0126
0127 decltype(inside_mask) inside_edge{false};
0128 if (detail::any_of(edge_tol > 0.f)) {
0129 const scalar_t full_tol{tol + edge_tol};
0130
0131 inside_edge = (loc_0 <= (bounds[e_cross_section] + full_tol) &&
0132 loc_1 <= (bounds[e_cross_section] + full_tol) &&
0133 loc_2 <= (bounds[e_half_z] + full_tol));
0134 }
0135
0136 return result_type<dbool<algebra_t>>{inside_mask, inside_edge};
0137 } else {
0138
0139 return check_boundaries(
0140 bounds, dpoint2D<algebra_t>{vector::perp(loc_3D), loc_3D[2]}, tol,
0141 edge_tol);
0142 }
0143 }
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 template <concepts::scalar scalar_t, concepts::point point_t>
0157 DETRAY_HOST_DEVICE constexpr auto check_boundaries(
0158 const bounds_type<scalar_t> &bounds, const point_t &loc_p,
0159 const scalar_t tol = std::numeric_limits<scalar_t>::epsilon(),
0160 const scalar_t edge_tol = 0.f) const {
0161
0162
0163
0164
0165 if constexpr (square_cross_sect) {
0166 const scalar_t loc_0{math::fabs(loc_p[0] * math::cos(loc_p[2]))};
0167 const scalar_t loc_1{math::fabs(loc_p[0] * math::sin(loc_p[2]))};
0168 const scalar_t loc_2{math::fabs(loc_p[1])};
0169
0170 auto inside_mask{(loc_0 <= (bounds[e_cross_section] + tol) &&
0171 loc_1 <= (bounds[e_cross_section] + tol) &&
0172 loc_2 <= bounds[e_half_z] + tol)};
0173
0174 decltype(inside_mask) inside_edge{false};
0175 if (detail::any_of(edge_tol > 0.f)) {
0176 const scalar_t full_tol{tol + edge_tol};
0177
0178 inside_edge = (loc_0 <= (bounds[e_cross_section] + full_tol) &&
0179 loc_1 <= (bounds[e_cross_section] + full_tol) &&
0180 loc_2 <= bounds[e_half_z] + full_tol);
0181 }
0182
0183 return result_type<decltype(inside_mask)>{inside_mask, inside_edge};
0184 }
0185
0186
0187
0188
0189 else {
0190 const scalar_t loc_0{math::fabs(loc_p[0])};
0191 const scalar_t loc_1{math::fabs(loc_p[1])};
0192
0193 auto inside_mask{(loc_0 <= (bounds[e_cross_section] + tol) &&
0194 loc_1 <= (bounds[e_half_z] + tol))};
0195
0196 decltype(inside_mask) inside_edge{false};
0197 if (detail::any_of(edge_tol > 0.f)) {
0198 const scalar_t full_tol{tol + edge_tol};
0199
0200 inside_edge = (loc_0 <= (bounds[e_cross_section] + full_tol) &&
0201 loc_1 <= (bounds[e_half_z] + full_tol));
0202 }
0203
0204 return result_type<decltype(inside_mask)>{inside_mask, inside_edge};
0205 }
0206 }
0207
0208
0209
0210
0211
0212
0213
0214 template <concepts::scalar scalar_t>
0215 DETRAY_HOST_DEVICE constexpr scalar_t measure(
0216 const bounds_type<scalar_t> &bounds) const {
0217 if constexpr (square_cross_sect) {
0218 return 8.f * bounds[e_half_z] * bounds[e_cross_section] *
0219 bounds[e_cross_section];
0220 } else {
0221 return constant<scalar_t>::pi * 2.f * bounds[e_half_z] *
0222 bounds[e_cross_section] * bounds[e_cross_section];
0223 }
0224 }
0225
0226
0227
0228
0229
0230
0231 template <concepts::scalar scalar_t>
0232 DETRAY_HOST_DEVICE constexpr scalar_t area(
0233 const bounds_type<scalar_t> &bounds) const {
0234 if constexpr (square_cross_sect) {
0235 return 16.f * bounds[e_half_z] * bounds[e_cross_section];
0236 } else {
0237 return 4.f * constant<scalar_t>::pi * bounds[e_cross_section] *
0238 bounds[e_half_z];
0239 }
0240 }
0241
0242
0243
0244
0245
0246
0247
0248 template <concepts::scalar scalar_t>
0249 DETRAY_HOST_DEVICE constexpr bounds_type<scalar_t> merge(
0250 const bounds_type<scalar_t> &bounds,
0251 const bounds_type<scalar_t> &o_bounds) const {
0252 bounds_type<scalar_t> new_bounds{};
0253
0254 new_bounds[e_cross_section] =
0255 math::max(bounds[e_cross_section], o_bounds[e_cross_section]);
0256 new_bounds[e_half_z] = math::max(bounds[e_half_z], o_bounds[e_half_z]);
0257
0258 return new_bounds;
0259 }
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270 template <concepts::algebra algebra_t>
0271 DETRAY_HOST_DEVICE inline darray<dscalar<algebra_t>, 6> local_min_bounds(
0272 const bounds_type<dscalar<algebra_t>> &bounds,
0273 const dscalar<algebra_t> env =
0274 std::numeric_limits<dscalar<algebra_t>>::epsilon()) const {
0275 using scalar_t = dscalar<algebra_t>;
0276
0277 assert(env > 0.f);
0278 const scalar_t xy_bound{bounds[e_cross_section] + env};
0279 const scalar_t z_bound{bounds[e_half_z] + env};
0280
0281 return {-xy_bound, -xy_bound, -z_bound, xy_bound, xy_bound, z_bound};
0282 }
0283
0284
0285 template <concepts::algebra algebra_t>
0286 DETRAY_HOST_DEVICE dpoint3D<algebra_t> centroid(
0287 const bounds_type<dscalar<algebra_t>> & ) const {
0288 return {0.f, 0.f, 0.f};
0289 }
0290
0291
0292
0293
0294
0295
0296
0297 template <concepts::algebra algebra_t>
0298 DETRAY_HOST dvector<dpoint3D<algebra_t>> vertices(
0299 const bounds_type<dscalar<algebra_t>> &bounds, dindex ) const {
0300 using point3_t = dpoint3D<algebra_t>;
0301
0302 point3_t lc = {0.f, 0.f, -bounds[e_half_z]};
0303 point3_t rc = {0.f, 0.f, bounds[e_half_z]};
0304
0305 return {lc, rc};
0306 }
0307
0308
0309
0310
0311
0312
0313
0314 template <concepts::scalar scalar_t>
0315 DETRAY_HOST constexpr bool check_consistency(
0316 const bounds_type<scalar_t> &bounds, std::ostream &os) const {
0317 constexpr auto tol{10.f * std::numeric_limits<scalar_t>::epsilon()};
0318
0319 if (bounds[e_cross_section] < tol) {
0320 os << "DETRAY ERROR (HOST): Radius/sides must be in the range (0, "
0321 "numeric_max)"
0322 << std::endl;
0323 return false;
0324 }
0325 if (bounds[e_half_z] < tol) {
0326 os << "DETRAY ERROR (HOST): Half length z must be in the range (0, "
0327 "numeric_max)"
0328 << std::endl;
0329 return false;
0330 }
0331
0332 return true;
0333 }
0334 };
0335
0336
0337 using line_circular = line<false>;
0338
0339 using line_square = line<true>;
0340
0341 }