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/cylindrical3D.hpp"
0019 #include "detray/geometry/detail/shape_utils.hpp"
0020
0021
0022 #include <limits>
0023 #include <ostream>
0024 #include <string_view>
0025
0026 namespace detray {
0027
0028
0029
0030
0031 class cylinder3D {
0032 public:
0033
0034 static constexpr std::string_view name = "cylinder3D";
0035
0036 enum boundaries : unsigned int {
0037 e_min_r = 0u,
0038 e_min_phi = 1u,
0039 e_min_z = 2u,
0040 e_max_r = 3u,
0041 e_max_phi = 4u,
0042 e_max_z = 5u,
0043 e_size = 6u,
0044 };
0045
0046
0047 template <concepts::scalar scalar_t>
0048 using bounds_type = darray<scalar_t, boundaries::e_size>;
0049
0050
0051 template <concepts::algebra algebra_t>
0052 using local_frame_type = cylindrical3D<algebra_t>;
0053
0054
0055 template <typename bool_t>
0056 using result_type = bool_t;
0057
0058
0059 static constexpr std::size_t dim{3u};
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070 template <concepts::scalar scalar_t, concepts::point point_t>
0071 DETRAY_HOST_DEVICE inline scalar_t min_dist_to_boundary(
0072 const bounds_type<scalar_t> &bounds, const point_t &loc_p) const {
0073 const scalar_t min_r_dist =
0074 math::min(math::fabs(loc_p[0] - bounds[e_min_r]),
0075 math::fabs(bounds[e_max_r] - loc_p[0]));
0076 const scalar_t min_phi_dist =
0077 math::min(math::fabs(loc_p[1] - bounds[e_min_phi]),
0078 math::fabs(bounds[e_max_phi] - loc_p[1]));
0079 const scalar_t min_z_dist =
0080 math::min(math::fabs(loc_p[2] - bounds[e_min_z]),
0081 math::fabs(bounds[e_max_z] - loc_p[2]));
0082
0083
0084 return math::min(
0085 math::min(min_r_dist, 2.f * loc_p[0] * math::sin(0.5f * min_phi_dist)),
0086 min_z_dist);
0087 }
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 template <concepts::algebra algebra_t>
0098 DETRAY_HOST_DEVICE constexpr result_type<dbool<algebra_t>> check_boundaries(
0099 const bounds_type<dscalar<algebra_t>> &bounds,
0100 const dtransform3D<algebra_t> &trf, const dpoint3D<algebra_t> &glob_p,
0101 const dscalar<algebra_t> tol =
0102 std::numeric_limits<dscalar<algebra_t>>::epsilon(),
0103 const dscalar<algebra_t> = 0.f) const {
0104
0105 const auto loc_p =
0106 local_frame_type<algebra_t>::global_to_local(trf, glob_p, {});
0107
0108 return check_boundaries(bounds, loc_p, tol);
0109 }
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121 template <concepts::scalar scalar_t, concepts::point point_t>
0122 DETRAY_HOST_DEVICE constexpr auto check_boundaries(
0123 const bounds_type<scalar_t> &bounds, const point_t &loc_p,
0124 const scalar_t tol = std::numeric_limits<scalar_t>::epsilon(),
0125 const scalar_t = 0.f) const {
0126 const scalar_t phi_tol = detail::phi_tolerance(tol, loc_p[0]);
0127
0128 return ((bounds[e_min_r] - tol) <= loc_p[0] &&
0129 (bounds[e_min_phi] - phi_tol) <= loc_p[1] &&
0130 (bounds[e_min_z] - tol) <= loc_p[2] &&
0131 loc_p[0] <= (bounds[e_max_r] + tol) &&
0132 loc_p[1] <= (bounds[e_max_phi] + phi_tol) &&
0133 loc_p[2] <= (bounds[e_max_z] + tol));
0134 }
0135
0136
0137
0138
0139
0140
0141
0142 template <concepts::scalar scalar_t>
0143 DETRAY_HOST_DEVICE constexpr scalar_t measure(
0144 const bounds_type<scalar_t> &bounds) const {
0145 return volume(bounds);
0146 }
0147
0148
0149
0150
0151
0152
0153 template <concepts::scalar scalar_t>
0154 DETRAY_HOST_DEVICE constexpr scalar_t volume(
0155 const bounds_type<scalar_t> &bounds) const {
0156 return constant<scalar_t>::pi * (bounds[e_max_z] - bounds[e_min_z]) *
0157 (bounds[e_max_r] * bounds[e_max_r] -
0158 bounds[e_min_r] * bounds[e_min_r]);
0159 }
0160
0161
0162
0163
0164
0165
0166
0167 template <concepts::scalar scalar_t>
0168 DETRAY_HOST_DEVICE constexpr bounds_type<scalar_t> merge(
0169 const bounds_type<scalar_t> &bounds,
0170 const bounds_type<scalar_t> &o_bounds) const {
0171 bounds_type<scalar_t> new_bounds{};
0172
0173 new_bounds[e_min_r] = math::min(bounds[e_min_r], o_bounds[e_min_r]);
0174 new_bounds[e_min_phi] = math::min(bounds[e_min_phi], o_bounds[e_min_phi]);
0175 new_bounds[e_min_z] = math::min(bounds[e_min_z], o_bounds[e_min_z]);
0176 new_bounds[e_max_r] = math::max(bounds[e_max_r], o_bounds[e_max_r]);
0177 new_bounds[e_max_phi] = math::max(bounds[e_max_phi], o_bounds[e_max_phi]);
0178 new_bounds[e_max_z] = math::max(bounds[e_max_z], o_bounds[e_max_z]);
0179
0180 return new_bounds;
0181 }
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193 template <concepts::algebra algebra_t>
0194 DETRAY_HOST_DEVICE inline darray<dscalar<algebra_t>, 6> local_min_bounds(
0195 const bounds_type<dscalar<algebra_t>> &bounds,
0196 const dscalar<algebra_t> env =
0197 std::numeric_limits<dscalar<algebra_t>>::epsilon()) const {
0198 assert(env > 0.f);
0199 const dscalar<algebra_t> r_bound{bounds[e_max_r] + env};
0200 return {-r_bound, -r_bound, bounds[e_min_z] - env,
0201 r_bound, r_bound, bounds[e_max_z] + env};
0202 }
0203
0204
0205 template <concepts::algebra algebra_t>
0206 DETRAY_HOST_DEVICE dpoint3D<algebra_t> centroid(
0207 const bounds_type<dscalar<algebra_t>> &bounds) const {
0208 return 0.5f * dpoint3D<algebra_t>{static_cast<dscalar<algebra_t>>(0.f),
0209 (bounds[e_min_phi] + bounds[e_max_phi]),
0210 (bounds[e_min_z] + bounds[e_max_z])};
0211 }
0212
0213
0214
0215
0216
0217
0218
0219 template <concepts::algebra algebra_t>
0220 DETRAY_HOST dvector<dpoint3D<algebra_t>> vertices(
0221 const bounds_type<dscalar<algebra_t>> & ,
0222 dindex ) const {
0223 throw std::runtime_error(
0224 "Vertex generation for 3D cylinders is not implemented");
0225 return {};
0226 }
0227
0228
0229
0230
0231
0232
0233
0234 template <concepts::scalar scalar_t>
0235 DETRAY_HOST constexpr bool check_consistency(
0236 const bounds_type<scalar_t> &bounds, std::ostream &os) const {
0237 constexpr auto tol{10.f * std::numeric_limits<scalar_t>::epsilon()};
0238
0239 if (bounds[e_min_r] < tol) {
0240 os << "DETRAY ERROR (HOST): Radii must be in the range (0, "
0241 "numeric_max)"
0242 << std::endl;
0243 return false;
0244 }
0245 if (bounds[e_min_r] >= bounds[e_max_r] ||
0246 math::fabs(bounds[e_min_r] - bounds[e_max_r]) < tol) {
0247 os << "DETRAY ERROR (HOST): Min Radius must be smaller than max "
0248 "Radius.";
0249 return false;
0250 }
0251 if (bounds[e_min_z] >= bounds[e_max_z] ||
0252 math::fabs(bounds[e_min_z] - bounds[e_max_z]) < tol) {
0253 os << "DETRAY ERROR (HOST): Min z must be smaller than max z.";
0254 return false;
0255 }
0256
0257 return true;
0258 }
0259 };
0260
0261 }