Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-27 07:23:59

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 // Project include(s)
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/geometry/coordinates/cartesian2D.hpp"
0018 #include "detray/geometry/coordinates/cartesian3D.hpp"
0019 #include "detray/geometry/detail/shape_utils.hpp"
0020 
0021 // System include(s)
0022 #include <limits>
0023 #include <ostream>
0024 #include <string_view>
0025 
0026 namespace detray {
0027 
0028 /// @brief Underlying geometry for a single parameter bound mask
0029 ///
0030 /// @tparam kCheckIndex is the index of the local point on which the mask is
0031 ///         applied
0032 template <unsigned int kCheckIndex = 0u>
0033 class single3D {
0034  public:
0035   /// The name for this shape
0036   static constexpr std::string_view name = "single3D";
0037 
0038   enum boundaries : unsigned int {
0039     e_lower = 0u,
0040     e_upper = 1u,
0041     e_size = 2u,
0042   };
0043 
0044   /// Container definition for the shape boundary values
0045   template <concepts::scalar scalar_t>
0046   using bounds_type = darray<scalar_t, boundaries::e_size>;
0047 
0048   /// Local coordinate frame for boundary checks
0049   template <concepts::algebra algebra_t>
0050   using local_frame_type = cartesian2D<algebra_t>;
0051 
0052   /// Result type of a boundary check
0053   template <typename bool_t>
0054   using result_type = detail::boundary_check_result<bool_t>;
0055 
0056   /// Dimension of the local coordinate system
0057   static constexpr std::size_t dim{1u};
0058 
0059   /// @brief Find the minimum distance to any boundary.
0060   ///
0061   /// @note the point is expected to be given in local coordinates by the
0062   /// caller.
0063   ///
0064   /// @param bounds the boundary values for this shape
0065   /// @param loc_p the point to be checked in the local coordinate system
0066   ///
0067   /// @return the minimum distance.
0068   template <concepts::scalar scalar_t, concepts::point point_t>
0069   DETRAY_HOST_DEVICE inline scalar_t min_dist_to_boundary(
0070       const bounds_type<scalar_t> &bounds, const point_t &loc_p) const {
0071     return math::min(math::fabs(loc_p[kCheckIndex] - bounds[e_lower]),
0072                      math::fabs(bounds[e_upper] - loc_p[kCheckIndex]));
0073   }
0074 
0075   /// @brief Check boundary values for a local point.
0076   ///
0077   /// @{
0078   /// @param bounds the boundary values for this shape
0079   /// @param trf the surface transform
0080   /// @param glob_p the point to be checked in the global coordinate system
0081   /// @param tol dynamic tolerance determined by caller
0082   ///
0083   /// @return true if the local point lies within the given boundaries.
0084   template <concepts::algebra algebra_t>
0085   DETRAY_HOST_DEVICE constexpr result_type<dbool<algebra_t>> check_boundaries(
0086       const bounds_type<dscalar<algebra_t>> &bounds,
0087       const dtransform3D<algebra_t> &trf, const dpoint3D<algebra_t> &glob_p,
0088       const dscalar<algebra_t> tol =
0089           std::numeric_limits<dscalar<algebra_t>>::epsilon(),
0090       const dscalar<algebra_t> edge_tol = 0.f) const {
0091     // Get the full local position
0092     const dpoint3D<algebra_t> loc_p =
0093         cartesian3D<algebra_t>::global_to_local(trf, glob_p, {});
0094 
0095     return check_boundaries(bounds, loc_p, tol, edge_tol);
0096   }
0097 
0098   /// @note the point is expected to be given in local coordinates by the
0099   /// caller. For the conversion from global cartesian coordinates, the
0100   /// nested @c shape struct can be used.
0101   ///
0102   /// @param bounds the boundary values for this shape
0103   /// @param loc_p the point to be checked in the local coordinate system
0104   /// @param tol dynamic tolerance determined by caller
0105   ///
0106   /// @return true if the local point lies within the given boundaries.
0107   template <concepts::scalar scalar_t, concepts::point point_t>
0108   DETRAY_HOST_DEVICE constexpr auto check_boundaries(
0109       const bounds_type<scalar_t> &bounds, const point_t &loc_p,
0110       const scalar_t tol = std::numeric_limits<scalar_t>::epsilon(),
0111       const scalar_t edge_tol = 0.f) const {
0112     auto inside_mask{(bounds[e_lower] - tol <= loc_p[kCheckIndex] &&
0113                       loc_p[kCheckIndex] <= bounds[e_upper] + tol)};
0114 
0115     decltype(inside_mask) inside_edge{false};
0116     if (detail::any_of(edge_tol > 0.f)) {
0117       const scalar_t full_tol{tol + edge_tol};
0118 
0119       inside_edge = (bounds[e_lower] - full_tol <= loc_p[kCheckIndex] &&
0120                      loc_p[kCheckIndex] <= bounds[e_upper] + full_tol);
0121     }
0122 
0123     return result_type<decltype(inside_mask)>{inside_mask, inside_edge};
0124   }
0125   /// @}
0126 
0127   /// @brief Measure of the shape: Range
0128   ///
0129   /// @param bounds the boundary values for this shape
0130   ///
0131   /// @returns the range.
0132   template <concepts::scalar scalar_t>
0133   DETRAY_HOST_DEVICE constexpr scalar_t measure(
0134       const bounds_type<scalar_t> &bounds) const {
0135     return area(bounds);
0136   }
0137 
0138   /// @brief The area of a the shape
0139   ///
0140   /// @param bounds the boundary values for this shape
0141   ///
0142   /// @returns the range.
0143   template <concepts::scalar scalar_t>
0144   DETRAY_HOST_DEVICE constexpr scalar_t area(
0145       const bounds_type<scalar_t> &bounds) const {
0146     return math::fabs(bounds[e_upper] - bounds[e_lower]);
0147   }
0148 
0149   /// @brief Merge two 'single' shapes
0150   ///
0151   /// @param bounds the boundary values for this shape
0152   /// @param o_bounds the boundary values for the other shape
0153   ///
0154   /// @returns merged bound values
0155   template <concepts::scalar scalar_t>
0156   DETRAY_HOST_DEVICE constexpr bounds_type<scalar_t> merge(
0157       const bounds_type<scalar_t> &bounds,
0158       const bounds_type<scalar_t> &o_bounds) const {
0159     bounds_type<scalar_t> new_bounds{};
0160 
0161     new_bounds[e_lower] = math::min(bounds[e_lower], o_bounds[e_lower]);
0162     new_bounds[e_upper] = math::max(bounds[e_upper], o_bounds[e_upper]);
0163 
0164     return new_bounds;
0165   }
0166 
0167   /// @brief Lower and upper point for minimal axis aligned bounding box.
0168   ///
0169   /// Computes the min and max vertices in a local cartesian frame.
0170   ///
0171   /// @param bounds the boundary values for this shape
0172   /// @param env dynamic envelope around the shape
0173   ///
0174   /// @returns and array of coordinates that contains the lower point (first
0175   /// three values) and the upper point (latter three values) .
0176   template <concepts::algebra algebra_t>
0177   DETRAY_HOST_DEVICE inline darray<dscalar<algebra_t>, 6> local_min_bounds(
0178       const bounds_type<dscalar<algebra_t>> &bounds,
0179       const dscalar<algebra_t> env =
0180           std::numeric_limits<dscalar<algebra_t>>::epsilon()) const {
0181     assert(env > 0.f);
0182     darray<dscalar<algebra_t>, 6> o_bounds{-env, -env, -env, env, env, env};
0183     o_bounds[kCheckIndex] += bounds[e_lower];
0184     o_bounds[3u + kCheckIndex] += bounds[e_upper];
0185     return o_bounds;
0186   }
0187 
0188   /// @returns the shapes centroid in local cartesian coordinates
0189   template <concepts::algebra algebra_t>
0190   DETRAY_HOST_DEVICE auto centroid(
0191       const bounds_type<dscalar<algebra_t>> &bounds) const {
0192     using point3_t = dpoint3D<algebra_t>;
0193 
0194     point3_t centr{0.f, 0.f, 0.f};
0195     centr[kCheckIndex] = 0.5f * (bounds[e_lower] + bounds[e_upper]);
0196 
0197     return centr;
0198   }
0199 
0200   /// Generate vertices in local cartesian frame
0201   ///
0202   /// @param bounds the boundary values for the single value
0203   /// @param n_seg is the number of line segments
0204   ///
0205   /// @return a generated list of vertices
0206   template <concepts::algebra algebra_t>
0207   DETRAY_HOST dvector<dpoint3D<algebra_t>> vertices(
0208       const bounds_type<dscalar<algebra_t>> & /*unused*/,
0209       dindex /*unused*/) const {
0210     throw std::runtime_error(
0211         "Vertex generation for single value shapes is not implemented");
0212     return {};
0213   }
0214 
0215   /// @brief Check consistency of boundary values.
0216   ///
0217   /// @param bounds the boundary values for this shape
0218   /// @param os output stream for error messages
0219   ///
0220   /// @return true if the bounds are consistent.
0221   template <concepts::scalar scalar_t>
0222   DETRAY_HOST constexpr bool check_consistency(
0223       const bounds_type<scalar_t> &bounds, std::ostream &os) const {
0224     if (bounds[e_upper] < bounds[e_lower]) {
0225       os << "DETRAY ERROR (HOST): Upper bounds must be smaller than "
0226             "lower bounds ";
0227       return false;
0228     }
0229 
0230     return true;
0231   }
0232 };
0233 
0234 }  // namespace detray