File indexing completed on 2026-05-27 07:23:59
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/geometry/concepts.hpp"
0016 #include "detray/geometry/shapes/cuboid3D.hpp"
0017 #include "detray/navigation/intersection/intersection.hpp"
0018
0019
0020 #include <algorithm>
0021 #include <cassert>
0022 #include <ostream>
0023 #include <sstream>
0024 #include <string>
0025 #include <vector>
0026
0027 namespace detray {
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 template <typename shape_t, concepts::algebra algebra_t,
0043 typename links_t = std::uint_least16_t>
0044 requires concepts::shape<shape_t, algebra_t>
0045 class mask {
0046 public:
0047
0048 using algebra_type = algebra_t;
0049 using scalar_type = dscalar<algebra_t>;
0050 using point2_type = dpoint2D<algebra_t>;
0051 using point3_type = dpoint3D<algebra_t>;
0052 using vector3_type = dvector3D<algebra_t>;
0053 using transform3_type = dtransform3D<algebra_t>;
0054
0055 using links_type = links_t;
0056 using shape = shape_t;
0057 using boundaries = typename shape::boundaries;
0058 using mask_values = typename shape::template bounds_type<scalar_type>;
0059 using local_frame = typename shape::template local_frame_type<algebra_t>;
0060 using result_type = typename shape::template result_type<dbool<algebra_t>>;
0061
0062
0063 constexpr mask() = default;
0064
0065
0066
0067 template <typename... Args>
0068 requires(sizeof...(Args) == shape::boundaries::e_size)
0069 DETRAY_HOST_DEVICE explicit constexpr mask(const links_type& link,
0070 Args&&... args)
0071 : _values({{std::forward<Args>(args)...}}), _volume_link(link) {}
0072
0073
0074
0075 DETRAY_HOST_DEVICE
0076 constexpr mask(const mask_values& values, const links_type& link)
0077 : _values{values}, _volume_link{link} {}
0078
0079
0080
0081 DETRAY_HOST mask(const std::vector<scalar_type>& values,
0082 const links_type& link)
0083 : _volume_link(link) {
0084 assert(values.size() == boundaries::e_size &&
0085 " Given number of boundaries does not match mask shape.");
0086 std::ranges::copy(values, std::begin(_values));
0087 }
0088
0089
0090
0091
0092 DETRAY_HOST
0093 auto operator=(const mask_values& rhs) -> mask<shape_t, algebra_t, links_t>& {
0094 _values = rhs;
0095 return (*this);
0096 }
0097
0098
0099
0100
0101
0102
0103 bool operator==(const mask& rhs) const = default;
0104
0105
0106
0107
0108 DETRAY_HOST_DEVICE
0109 constexpr auto operator[](const std::size_t value_index) -> scalar_type& {
0110 return _values[value_index];
0111 }
0112
0113
0114
0115
0116 DETRAY_HOST_DEVICE
0117 constexpr auto operator[](const std::size_t value_index) const
0118 -> scalar_type {
0119 return _values[value_index];
0120 }
0121
0122
0123 DETRAY_HOST_DEVICE
0124 static consteval auto get_shape() -> shape { return shape{}; }
0125
0126
0127 DETRAY_HOST_DEVICE static consteval local_frame get_local_frame() {
0128 return local_frame{};
0129 }
0130
0131
0132 DETRAY_HOST_DEVICE constexpr static auto to_local_frame3D(
0133 const transform3_type& trf, const point3_type& glob_p,
0134 const point3_type& glob_dir = {}) -> point3_type {
0135 return get_local_frame().global_to_local_3D(trf, glob_p, glob_dir);
0136 }
0137
0138
0139 DETRAY_HOST_DEVICE constexpr static auto to_local_frame(
0140 const transform3_type& trf, const point3_type& glob_p,
0141 const point3_type& glob_dir = {}) -> point2_type {
0142 return get_local_frame().global_to_local(trf, glob_p, glob_dir);
0143 }
0144
0145
0146 DETRAY_HOST_DEVICE constexpr static auto to_global_frame(
0147 const transform3_type& trf, const point3_type& loc) -> point3_type {
0148 return get_local_frame().local_to_global(trf, loc);
0149 }
0150
0151
0152 DETRAY_HOST_DEVICE constexpr auto to_global_frame(
0153 const transform3_type& trf, const point2_type& loc,
0154 const vector3_type& dir) const -> point3_type {
0155 return get_local_frame().local_to_global(trf, *this, loc, dir);
0156 }
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 template <concepts::point point_t>
0174 DETRAY_HOST_DEVICE constexpr result_type resolve(
0175 const point_t& loc_p,
0176 const scalar_type tol = std::numeric_limits<scalar_type>::epsilon(),
0177 const scalar_type edge_tol = 0.f) const {
0178 return get_shape().check_boundaries(_values, loc_p, tol, edge_tol);
0179 }
0180
0181
0182
0183
0184
0185
0186
0187 DETRAY_HOST_DEVICE constexpr result_type resolve(
0188 const transform3_type& trf, const point3_type& glob_p,
0189 const scalar_type tol = std::numeric_limits<scalar_type>::epsilon(),
0190 const scalar_type edge_tol = 0.f) const {
0191 return get_shape().template check_boundaries<algebra_type>(
0192 _values, trf, glob_p, tol, edge_tol);
0193 }
0194
0195
0196
0197
0198
0199 template <concepts::point point_t>
0200 DETRAY_HOST_DEVICE constexpr dbool<algebra_t> is_inside(
0201 const point_t& loc_p,
0202 const scalar_type tol =
0203 std::numeric_limits<scalar_type>::epsilon()) const {
0204 return detray::get<check_type::e_precise>(
0205 get_shape().check_boundaries(_values, loc_p, tol, scalar_type{0.f}));
0206 }
0207
0208
0209
0210
0211
0212
0213 DETRAY_HOST_DEVICE constexpr dbool<algebra_type> is_inside(
0214 const transform3_type& trf, const point3_type& glob_p,
0215 const scalar_type tol =
0216 std::numeric_limits<scalar_type>::epsilon()) const {
0217 return detray::get<check_type::e_precise>(
0218 get_shape().template check_boundaries<algebra_type>(
0219 _values, trf, glob_p, tol, scalar_type{0.f}));
0220 }
0221
0222
0223
0224 DETRAY_HOST_DEVICE
0225 auto values() const -> const mask_values& { return _values; }
0226
0227
0228 DETRAY_HOST_DEVICE
0229 auto volume_link() const -> const links_type& { return _volume_link; }
0230
0231
0232 DETRAY_HOST_DEVICE
0233 auto volume_link() -> links_type& { return _volume_link; }
0234
0235
0236
0237 DETRAY_HOST_DEVICE constexpr auto measure() const -> scalar_type {
0238 return get_shape().measure(_values);
0239 }
0240
0241
0242 template <typename S = shape_t>
0243 requires(S::dim == 2)
0244 DETRAY_HOST_DEVICE constexpr auto area() const -> scalar_type {
0245 return get_shape().area(_values);
0246 }
0247
0248
0249 template <typename S = shape_t>
0250 requires(S::dim == 3)
0251 DETRAY_HOST_DEVICE constexpr auto volume() const -> scalar_type {
0252 return get_shape().volume(_values);
0253 }
0254
0255
0256 DETRAY_HOST_DEVICE auto centroid() const {
0257 return get_shape().template centroid<algebra_t>(_values);
0258 }
0259
0260
0261
0262
0263
0264
0265 DETRAY_HOST_DEVICE
0266 auto min_dist_to_boundary(const point3_type& loc_p) const -> scalar_type {
0267 return get_shape().min_dist_to_boundary(_values, loc_p);
0268 }
0269
0270
0271
0272
0273
0274
0275
0276
0277 DETRAY_HOST_DEVICE
0278 auto local_min_bounds(
0279 const scalar_type env = std::numeric_limits<scalar_type>::epsilon()) const
0280 -> mask<cuboid3D, algebra_t, unsigned int> {
0281 const auto bounds =
0282 get_shape().template local_min_bounds<algebra_t>(_values, env);
0283 static_assert(bounds.size() == cuboid3D::e_size,
0284 "Shape returns incompatible bounds for bound box");
0285 return {bounds, std::numeric_limits<unsigned int>::max()};
0286 }
0287
0288
0289
0290
0291
0292
0293
0294
0295 DETRAY_HOST
0296 auto vertices(const dindex n_seg) const -> dvector<point3_type> {
0297 return get_shape().template vertices<algebra_t>(_values, n_seg);
0298 }
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309 DETRAY_HOST
0310 friend mask operator+(const mask& left, const mask& right) {
0311 links_type vol_link{left.volume_link() == right.volume_link()
0312 ? left.volume_link()
0313 : detail::invalid_value<links_type>()};
0314 mask_values merged_vals =
0315 mask::get_shape().merge(left.values(), right.values());
0316
0317 return {std::move(merged_vals), vol_link};
0318 }
0319
0320
0321 DETRAY_HOST
0322 constexpr bool self_check(std::ostream& os) const {
0323 const bool result = get_shape().check_consistency(_values, os);
0324
0325 if (!result) {
0326 os << to_string();
0327 }
0328
0329 return result;
0330 }
0331
0332
0333 DETRAY_HOST
0334 auto to_string() const -> std::string {
0335 std::stringstream ss;
0336 ss << std::string(shape::name);
0337 for (const auto& v : _values) {
0338 ss << ", " << v;
0339 }
0340 return ss.str();
0341 }
0342
0343
0344 DETRAY_HOST
0345 friend std::ostream& operator<<(std::ostream& os, const mask& m) {
0346 os << m.to_string();
0347 return os;
0348 }
0349
0350 private:
0351 mask_values _values{};
0352 links_type _volume_link{std::numeric_limits<links_type>::max()};
0353 };
0354
0355 }