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