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/cartesian3D.hpp"
0019 #include "detray/geometry/coordinates/polar2D.hpp"
0020 #include "detray/geometry/detail/shape_utils.hpp"
0021 
0022 // System include(s)
0023 #include <limits>
0024 #include <ostream>
0025 #include <string_view>
0026 
0027 namespace detray {
0028 
0029 /// @brief Geometrical shape of a closed ring.
0030 ///
0031 /// It is defined by the two radii bounds[0] and bounds[1],
0032 /// and can be checked with a tolerance in t[0] and t[1].
0033 class ring2D {
0034  public:
0035   /// The name for this shape
0036   static constexpr std::string_view name = "ring2D";
0037 
0038   enum boundaries : unsigned int {
0039     e_inner_r = 0u,
0040     e_outer_r = 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 = polar2D<algebra_t>;
0051 
0052   /// Result type of a boundary check
0053   template <typename bool_t>
0054   using result_type = bool_t;
0055 
0056   /// Dimension of the local coordinate system
0057   static constexpr std::size_t dim{2u};
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[0] - bounds[e_inner_r]),
0072                      math::fabs(bounds[e_outer_r] - loc_p[0]));
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     // Rotate to the local cartesian frame
0092     const dpoint3D<algebra_t> loc_p =
0093         cartesian3D<algebra_t>::global_to_local(trf, glob_p, {});
0094 
0095     // Only check the radius
0096     return check_boundaries(
0097         bounds,
0098         dpoint2D<algebra_t>{vector::perp(loc_p),
0099                             static_cast<dscalar<algebra_t>>(0.f)},
0100         tol);
0101   }
0102 
0103   /// @note the point is expected to be given in local coordinates by the
0104   /// caller. For the conversion from global cartesian coordinates, the
0105   /// nested @c shape struct can be used.
0106   ///
0107   /// @param bounds the boundary values for this shape
0108   /// @param loc_p the point to be checked in the local coordinate system
0109   /// @param tol dynamic tolerance determined by caller
0110   ///
0111   /// @return true if the local point lies within the given boundaries.
0112   template <concepts::scalar scalar_t, concepts::point point_t>
0113   DETRAY_HOST_DEVICE constexpr auto check_boundaries(
0114       const bounds_type<scalar_t> &bounds, const point_t &loc_p,
0115       const scalar_t tol = std::numeric_limits<scalar_t>::epsilon(),
0116       const scalar_t /*edge_tol*/ = 0.f) const {
0117     return ((loc_p[0] + tol) >= bounds[e_inner_r] &&
0118             loc_p[0] <= (bounds[e_outer_r] + tol));
0119   }
0120   /// @}
0121 
0122   /// @brief Measure of the shape: Area
0123   ///
0124   /// @param bounds the boundary values for this shape
0125   ///
0126   /// @returns the ring area on the plane
0127   template <concepts::scalar scalar_t>
0128   DETRAY_HOST_DEVICE constexpr scalar_t measure(
0129       const bounds_type<scalar_t> &bounds) const {
0130     return area(bounds);
0131   }
0132 
0133   /// @brief The area of a the shape
0134   ///
0135   /// @param bounds the boundary values for this shape
0136   ///
0137   /// @returns the ring area.
0138   template <concepts::scalar scalar_t>
0139   DETRAY_HOST_DEVICE constexpr scalar_t area(
0140       const bounds_type<scalar_t> &bounds) const {
0141     return (bounds[e_outer_r] * bounds[e_outer_r] -
0142             bounds[e_inner_r] * bounds[e_inner_r]) *
0143            constant<scalar_t>::pi;
0144   }
0145 
0146   /// @brief Merge two ring/disc shapes
0147   ///
0148   /// @param bounds the boundary values for this shape
0149   /// @param o_bounds the boundary values for the other shape
0150   ///
0151   /// @returns merged bound values
0152   template <concepts::scalar scalar_t>
0153   DETRAY_HOST_DEVICE constexpr bounds_type<scalar_t> merge(
0154       const bounds_type<scalar_t> &bounds,
0155       const bounds_type<scalar_t> &o_bounds) const {
0156     bounds_type<scalar_t> new_bounds{};
0157 
0158     new_bounds[e_inner_r] = math::min(bounds[e_inner_r], o_bounds[e_inner_r]);
0159     new_bounds[e_outer_r] = math::max(bounds[e_outer_r], o_bounds[e_outer_r]);
0160 
0161     return new_bounds;
0162   }
0163 
0164   /// @brief Lower and upper point for minimal axis aligned bounding box.
0165   ///
0166   /// Computes the min and max vertices in a local cartesian frame.
0167   ///
0168   /// @param bounds the boundary values for this shape
0169   /// @param env dynamic envelope around the shape
0170   ///
0171   /// @returns and array of coordinates that contains the lower point (first
0172   /// three values) and the upper point (latter three values) .
0173   template <concepts::algebra algebra_t>
0174   DETRAY_HOST_DEVICE inline darray<dscalar<algebra_t>, 6> local_min_bounds(
0175       const bounds_type<dscalar<algebra_t>> &bounds,
0176       const dscalar<algebra_t> env =
0177           std::numeric_limits<dscalar<algebra_t>>::epsilon()) const {
0178     assert(env > 0.f);
0179     const dscalar<algebra_t> r_bound{env + bounds[e_outer_r]};
0180     return {-r_bound, -r_bound, -env, r_bound, r_bound, env};
0181   }
0182 
0183   /// @returns the shapes centroid in local cartesian coordinates
0184   template <concepts::algebra algebra_t>
0185   DETRAY_HOST_DEVICE dpoint3D<algebra_t> centroid(
0186       const bounds_type<dscalar<algebra_t>> & /*unused*/) const {
0187     return {0.f, 0.f, 0.f};
0188   }
0189 
0190   /// Generate vertices in local cartesian frame
0191   ///
0192   /// @param bounds the boundary values for the stereo annulus
0193   /// @param n_seg is the number of line segments
0194   ///
0195   /// @return a generated list of vertices
0196   template <concepts::algebra algebra_t>
0197   DETRAY_HOST dvector<dpoint3D<algebra_t>> vertices(
0198       const bounds_type<dscalar<algebra_t>> & /*unused*/,
0199       dindex /*unused*/) const {
0200     throw std::runtime_error("Vertex generation for rings is not implemented");
0201     return {};
0202   }
0203 
0204   /// @brief Check consistency of boundary values.
0205   ///
0206   /// @param bounds the boundary values for this shape
0207   /// @param os output stream for error messages
0208   ///
0209   /// @return true if the bounds are consistent.
0210   template <concepts::scalar scalar_t>
0211   DETRAY_HOST constexpr bool check_consistency(
0212       const bounds_type<scalar_t> &bounds, std::ostream &os) const {
0213     constexpr auto tol{10.f * std::numeric_limits<scalar_t>::epsilon()};
0214 
0215     if (math::signbit(bounds[e_inner_r]) || bounds[e_outer_r] < tol) {
0216       os << "DETRAY ERROR (HOST): Radius must be in the range [0, "
0217             "numeric_max)"
0218          << std::endl;
0219       return false;
0220     }
0221     if (bounds[e_inner_r] >= bounds[e_outer_r] ||
0222         math::fabs(bounds[e_inner_r] - bounds[e_outer_r]) < tol) {
0223       os << "DETRAY ERROR (HOST): Inner radius must be smaller outer "
0224             "radius.";
0225       return false;
0226     }
0227 
0228     return true;
0229   }
0230 };
0231 
0232 }  // namespace detray