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