Back to home page

EIC code displayed by LXR

 
 

    


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

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/definitions/units.hpp"
0018 #include "detray/geometry/coordinates/concentric_cylindrical2D.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 Geometrical shape of a 2D concentric cylinder.
0029 ///
0030 /// It is defined by r and the two half lengths rel to the coordinate center.
0031 class concentric_cylinder2D {
0032  public:
0033   /// The name for this shape
0034   static constexpr std::string_view name = "concentric_cylinder2D";
0035 
0036   enum boundaries : unsigned int {
0037     e_r = 0u,
0038     e_lower_z = 1u,
0039     e_upper_z = 2u,
0040     e_size = 3u,
0041   };
0042 
0043   /// Container definition for the shape boundary values
0044   template <concepts::scalar scalar_t>
0045   using bounds_type = darray<scalar_t, boundaries::e_size>;
0046 
0047   /// Local coordinate frame for boundary checks
0048   template <concepts::algebra algebra_t>
0049   using local_frame_type = concentric_cylindrical2D<algebra_t>;
0050 
0051   /// Result type of a boundary check
0052   template <typename bool_t>
0053   using result_type = bool_t;
0054 
0055   /// Dimension of the local coordinate system
0056   static constexpr std::size_t dim{2u};
0057 
0058   /// @brief Find the minimum distance to any boundary.
0059   ///
0060   /// @note the point is expected to be given in local coordinates by the
0061   /// caller.
0062   ///
0063   /// @param bounds the boundary values for this shape
0064   /// @param loc_p the point to be checked in the local coordinate system
0065   ///
0066   /// @return the minimum distance.
0067   template <concepts::scalar scalar_t, concepts::point point_t>
0068   DETRAY_HOST_DEVICE inline scalar_t min_dist_to_boundary(
0069       const bounds_type<scalar_t> &bounds, const point_t &loc_p) const {
0070     return math::min(math::fabs(loc_p[1] - bounds[e_lower_z]),
0071                      math::fabs(bounds[e_upper_z] - loc_p[1]));
0072   }
0073 
0074   /// @brief Check boundary values for a local point.
0075   /// @{
0076   /// @param bounds the boundary values for this shape
0077   /// @param trf the surface transform
0078   /// @param glob_p the point to be checked in the global coordinate system
0079   /// @param tol dynamic tolerance determined by caller
0080   ///
0081   /// @return true if the local point lies within the given boundaries.
0082   template <concepts::algebra algebra_t>
0083   DETRAY_HOST_DEVICE constexpr result_type<dbool<algebra_t>> check_boundaries(
0084       const bounds_type<dscalar<algebra_t>> &bounds,
0085       const dtransform3D<algebra_t> & /*trf*/,
0086       const dpoint3D<algebra_t> &glob_p,
0087       const dscalar<algebra_t> tol =
0088           std::numeric_limits<dscalar<algebra_t>>::epsilon(),
0089       const dscalar<algebra_t> /*edge_tol*/ = 0.f) const {
0090     // Only need the z-position for the check
0091     return check_boundaries(
0092         bounds,
0093         dpoint2D<algebra_t>{static_cast<dscalar<algebra_t>>(0.f), glob_p[2]},
0094         tol);
0095   }
0096 
0097   /// @note the point is expected to be given in local coordinates by the
0098   /// caller. For the conversion from global cartesian coordinates, the
0099   /// nested @c shape struct can be used. The point is assumed to be in
0100   /// the cylinder 2D frame (r * phi, z).
0101   ///
0102   /// @tparam is_rad_check whether the radial bound should be checked in this
0103   /// call.
0104   ///
0105   /// @param bounds the boundary values for this shape
0106   /// @param loc_p the point to be checked in the local coordinate system
0107   /// @param tol dynamic tolerance determined by caller
0108   ///
0109   /// @return true if the local point lies within the given boundaries.
0110   template <concepts::scalar scalar_t, concepts::point point_t>
0111   DETRAY_HOST_DEVICE constexpr auto check_boundaries(
0112       const bounds_type<scalar_t> &bounds, const point_t &loc_p,
0113       const scalar_t tol = std::numeric_limits<scalar_t>::epsilon(),
0114       const scalar_t /*edge_tol*/ = 0.f) const {
0115     return (bounds[e_lower_z] - tol <= loc_p[1] &&
0116             loc_p[1] <= bounds[e_upper_z] + tol);
0117   }
0118   /// @}
0119 
0120   /// @brief Measure of the shape: Area
0121   ///
0122   /// @param bounds the boundary values for this shape
0123   ///
0124   /// @returns the cylinder area on the cylinder of radius r.
0125   template <concepts::scalar scalar_t>
0126   DETRAY_HOST_DEVICE constexpr scalar_t measure(
0127       const bounds_type<scalar_t> &bounds) const {
0128     return area(bounds);
0129   }
0130 
0131   /// @brief The area of a the shape
0132   ///
0133   /// @param bounds the boundary values for this shape
0134   ///
0135   /// @returns the cylinder area.
0136   template <concepts::scalar scalar_t>
0137   DETRAY_HOST_DEVICE constexpr scalar_t area(
0138       const bounds_type<scalar_t> &bounds) const {
0139     return 2.f * constant<scalar_t>::pi * bounds[e_r] *
0140            (bounds[e_upper_z] - bounds[e_lower_z]);
0141   }
0142 
0143   /// @brief Merge two concentric cylinder shapes
0144   ///
0145   /// @param bounds the boundary values for this shape
0146   /// @param o_bounds the boundary values for the other shape
0147   ///
0148   /// @returns merged bound values
0149   template <concepts::scalar scalar_t>
0150   DETRAY_HOST_DEVICE constexpr bounds_type<scalar_t> merge(
0151       const bounds_type<scalar_t> &bounds,
0152       const bounds_type<scalar_t> &o_bounds) const {
0153     bounds_type<scalar_t> new_bounds{};
0154 
0155     new_bounds[e_r] = math::max(bounds[e_r], o_bounds[e_r]);
0156     new_bounds[e_lower_z] = math::min(bounds[e_lower_z], o_bounds[e_lower_z]);
0157     new_bounds[e_upper_z] = math::max(bounds[e_upper_z], o_bounds[e_upper_z]);
0158 
0159     return new_bounds;
0160   }
0161 
0162   /// @brief Lower and upper point for minimal axis aligned bounding box.
0163   ///
0164   /// Computes the min and max vertices in a local cartesian frame.
0165   ///
0166   /// @param bounds the boundary values for this shape
0167   /// @param env dynamic envelope around the shape
0168   ///
0169   /// @returns an array of coordinates that contains the lower point (first
0170   /// three values) and the upper point (latter three values) .
0171   template <concepts::algebra algebra_t>
0172   DETRAY_HOST_DEVICE inline darray<dscalar<algebra_t>, 6> local_min_bounds(
0173       const bounds_type<dscalar<algebra_t>> &bounds,
0174       const dscalar<algebra_t> env =
0175           std::numeric_limits<dscalar<algebra_t>>::epsilon()) const {
0176     assert(env > 0.f);
0177     const dscalar<algebra_t> xy_bound{bounds[e_r] + env};
0178     return {-xy_bound, -xy_bound, bounds[e_lower_z] - env,
0179             xy_bound,  xy_bound,  bounds[e_upper_z] + env};
0180   }
0181 
0182   /// @returns the shapes centroid in local cartesian coordinates
0183   template <concepts::algebra algebra_t>
0184   DETRAY_HOST_DEVICE dpoint3D<algebra_t> centroid(
0185       const bounds_type<dscalar<algebra_t>> &bounds) const {
0186     return {static_cast<dscalar<algebra_t>>(0.f),
0187             static_cast<dscalar<algebra_t>>(0.f),
0188             0.5f * (bounds[e_lower_z] + bounds[e_upper_z])};
0189   }
0190 
0191   /// Generate vertices in local cartesian frame
0192   ///
0193   /// @param bounds the boundary values for the cylinder
0194   /// @param n_seg is the number of line segments
0195   ///
0196   /// @return a generated list of vertices
0197   template <concepts::algebra algebra_t>
0198   DETRAY_HOST dvector<dpoint3D<algebra_t>> vertices(
0199       const bounds_type<dscalar<algebra_t>> & /*unused*/,
0200       dindex /*unused*/) const {
0201     throw std::runtime_error(
0202         "Vertex generation for cylinders is not implemented");
0203     return {};
0204   }
0205 
0206   /// @brief Check consistency of boundary values.
0207   ///
0208   /// @param bounds the boundary values for this shape
0209   /// @param os output stream for error messages
0210   ///
0211   /// @return true if the bounds are consistent.
0212   template <concepts::scalar scalar_t>
0213   DETRAY_HOST constexpr bool check_consistency(
0214       const bounds_type<scalar_t> &bounds, std::ostream &os) const {
0215     constexpr auto tol{10.f * std::numeric_limits<scalar_t>::epsilon()};
0216 
0217     if (bounds[e_r] < tol) {
0218       os << "DETRAY ERROR (HOST): Radius must be in the range (0, "
0219             "numeric_max)"
0220          << std::endl;
0221       return false;
0222     }
0223     if (bounds[e_lower_z] >= bounds[e_upper_z] ||
0224         math::fabs(bounds[e_lower_z] - bounds[e_upper_z]) < tol) {
0225       os << "DETRAY ERROR (HOST): Neg. half length must be smaller than "
0226             "pos. half "
0227             "length.";
0228       return false;
0229     }
0230 
0231     return true;
0232   }
0233 };
0234 
0235 }  // namespace detray