Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-14 08:18:16

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 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0010 
0011 #include "Acts/Definitions/Direction.hpp"
0012 #include "Acts/Surfaces/LineSurface.hpp"
0013 #include "Acts/Surfaces/PlaneSurface.hpp"
0014 #include "Acts/Surfaces/RectangleBounds.hpp"
0015 #include "Acts/Surfaces/Surface.hpp"
0016 #include "Acts/Utilities/BoundingBox.hpp"
0017 #include "Acts/Utilities/detail/OstreamStateGuard.hpp"
0018 
0019 #include <algorithm>
0020 #include <array>
0021 #include <iomanip>
0022 #include <stdexcept>
0023 #include <utility>
0024 
0025 namespace Acts {
0026 
0027 CuboidVolumeBounds::CuboidVolumeBounds(double halex, double haley, double halez)
0028     : VolumeBounds(), m_values({halex, haley, halez}) {
0029   checkConsistency();
0030   buildSurfaceBounds();
0031 }
0032 
0033 CuboidVolumeBounds::CuboidVolumeBounds(const std::array<double, eSize>& values)
0034     : m_values(values) {
0035   checkConsistency();
0036   buildSurfaceBounds();
0037 }
0038 
0039 CuboidVolumeBounds::CuboidVolumeBounds(
0040     std::initializer_list<std::pair<BoundValues, double>> keyValues)
0041     : m_values({-1, -1, -1}) {
0042   for (const auto& [key, value] : keyValues) {
0043     m_values[key] = value;
0044   }
0045   // Throw error here instead of consistency check for clarity
0046   if (std::ranges::any_of(m_values,
0047                           [](const auto& val) { return val == -1; })) {
0048     throw std::logic_error("Missing bound values");
0049   }
0050   checkConsistency();
0051   buildSurfaceBounds();
0052 }
0053 
0054 std::vector<double> CuboidVolumeBounds::values() const {
0055   return {m_values.begin(), m_values.end()};
0056 }
0057 
0058 std::vector<Acts::OrientedSurface> Acts::CuboidVolumeBounds::orientedSurfaces(
0059     const Transform3& transform) const {
0060   std::vector<OrientedSurface> oSurfaces;
0061   oSurfaces.reserve(6);
0062   // Face surfaces xy -------------------------------------
0063   //   (1) - at negative local z
0064   auto sf = Surface::makeShared<PlaneSurface>(
0065       transform * Translation3(0., 0., -get(eHalfLengthZ)), m_xyBounds);
0066   oSurfaces.emplace_back(std::move(sf), Direction::AlongNormal());
0067   //   (2) - at positive local z
0068   sf = Surface::makeShared<PlaneSurface>(
0069       transform * Translation3(0., 0., get(eHalfLengthZ)), m_xyBounds);
0070   oSurfaces.emplace_back(std::move(sf), Direction::OppositeNormal());
0071   // Face surfaces yz -------------------------------------
0072   //   (3) - at negative local x
0073   sf = Surface::makeShared<PlaneSurface>(
0074       transform * Translation3(-get(eHalfLengthX), 0., 0.) * s_planeYZ,
0075       m_yzBounds);
0076   oSurfaces.emplace_back(std::move(sf), Direction::AlongNormal());
0077   //   (4) - at positive local x
0078   sf = Surface::makeShared<PlaneSurface>(
0079       transform * Translation3(get(eHalfLengthX), 0., 0.) * s_planeYZ,
0080       m_yzBounds);
0081   oSurfaces.emplace_back(std::move(sf), Direction::OppositeNormal());
0082   // Face surfaces zx -------------------------------------
0083   //   (5) - at negative local y
0084   sf = Surface::makeShared<PlaneSurface>(
0085       transform * Translation3(0., -get(eHalfLengthY), 0.) * s_planeZX,
0086       m_zxBounds);
0087   oSurfaces.emplace_back(std::move(sf), Direction::AlongNormal());
0088   //   (6) - at positive local y
0089   sf = Surface::makeShared<PlaneSurface>(
0090       transform * Translation3(0., get(eHalfLengthY), 0.) * s_planeZX,
0091       m_zxBounds);
0092   oSurfaces.emplace_back(std::move(sf), Direction::OppositeNormal());
0093 
0094   return oSurfaces;
0095 }
0096 
0097 std::ostream& CuboidVolumeBounds::toStream(std::ostream& os) const {
0098   detail::OstreamStateGuard guard{os};
0099   os << std::fixed << std::setprecision(5);
0100   os << "Acts::CuboidVolumeBounds: (halfLengthX, halfLengthY, halfLengthZ) = ";
0101   os << "(" << get(eHalfLengthX) << ", " << get(eHalfLengthY) << ", "
0102      << get(eHalfLengthZ) << ")";
0103   return os;
0104 }
0105 
0106 Volume::BoundingBox CuboidVolumeBounds::boundingBox(
0107     const Transform3* trf, const Vector3& envelope,
0108     const Volume* entity) const {
0109   Vector3 vmin(-get(eHalfLengthX), -get(eHalfLengthY), -get(eHalfLengthZ));
0110   Vector3 vmax(get(eHalfLengthX), get(eHalfLengthY), get(eHalfLengthZ));
0111 
0112   Volume::BoundingBox box(entity, vmin - envelope, vmax + envelope);
0113   return trf == nullptr ? box : box.transformed(*trf);
0114 }
0115 
0116 void CuboidVolumeBounds::buildSurfaceBounds() {
0117   m_xyBounds = std::make_shared<const RectangleBounds>(get(eHalfLengthX),
0118                                                        get(eHalfLengthY));
0119   m_yzBounds = std::make_shared<const RectangleBounds>(get(eHalfLengthY),
0120                                                        get(eHalfLengthZ));
0121   m_zxBounds = std::make_shared<const RectangleBounds>(get(eHalfLengthZ),
0122                                                        get(eHalfLengthX));
0123 }
0124 
0125 double CuboidVolumeBounds::referenceBorder(AxisDirection aDir) const {
0126   if (aDir <= AxisDirection::AxisZ) {
0127     return m_values[toUnderlying(aDir)];
0128   }
0129   if (aDir == AxisDirection::AxisR) {
0130     return std::sqrt(m_values[toUnderlying(AxisDirection::AxisX)] *
0131                          m_values[toUnderlying(AxisDirection::AxisX)] +
0132                      m_values[toUnderlying(AxisDirection::AxisY)] *
0133                          m_values[toUnderlying(AxisDirection::AxisY)]);
0134   }
0135   return 0.0;
0136 }
0137 
0138 bool CuboidVolumeBounds::inside(const Vector3& pos, double tol) const {
0139   return (std::abs(pos.x()) <= get(eHalfLengthX) + tol &&
0140           std::abs(pos.y()) <= get(eHalfLengthY) + tol &&
0141           std::abs(pos.z()) <= get(eHalfLengthZ) + tol);
0142 }
0143 
0144 void CuboidVolumeBounds::checkConsistency() noexcept(false) {
0145   if (get(eHalfLengthX) <= 0 || get(eHalfLengthY) <= 0 ||
0146       get(eHalfLengthZ) <= 0.) {
0147     throw std::invalid_argument(
0148         "CuboidVolumeBounds: invalid input, zero or negative.");
0149   }
0150 }
0151 
0152 void CuboidVolumeBounds::set(BoundValues bValue, double value) {
0153   set({{bValue, value}});
0154 }
0155 
0156 void CuboidVolumeBounds::set(
0157     std::initializer_list<std::pair<BoundValues, double>> keyValues) {
0158   std::array<double, eSize> previous = m_values;
0159   for (const auto& [key, value] : keyValues) {
0160     m_values[key] = value;
0161   }
0162   try {
0163     checkConsistency();
0164     buildSurfaceBounds();
0165   } catch (std::invalid_argument& e) {
0166     m_values = previous;
0167     throw e;
0168   }
0169 }
0170 
0171 CuboidVolumeBounds::BoundValues CuboidVolumeBounds::boundsFromAxisDirection(
0172     AxisDirection direction) {
0173   using enum AxisDirection;
0174   switch (direction) {
0175     case AxisX:
0176       return BoundValues::eHalfLengthX;
0177     case AxisY:
0178       return BoundValues::eHalfLengthY;
0179     case AxisZ:
0180       return BoundValues::eHalfLengthZ;
0181     default:
0182       throw std::invalid_argument("Invalid axis direction");
0183   }
0184 }
0185 
0186 std::tuple<CuboidVolumeBounds::Face, CuboidVolumeBounds::Face,
0187            std::array<CuboidVolumeBounds::Face, 4>>
0188 CuboidVolumeBounds::facesFromAxisDirection(AxisDirection direction) {
0189   using enum AxisDirection;
0190   using enum CuboidVolumeBounds::Face;
0191   if (direction == AxisX) {
0192     return {NegativeXFace,
0193             PositiveXFace,
0194             {NegativeZFace, PositiveZFace, NegativeYFace, PositiveYFace}};
0195   } else if (direction == AxisY) {
0196     return {NegativeYFace,
0197             PositiveYFace,
0198             {NegativeZFace, PositiveZFace, NegativeXFace, PositiveXFace}};
0199   } else if (direction == AxisZ) {
0200     return {NegativeZFace,
0201             PositiveZFace,
0202             {NegativeXFace, PositiveXFace, NegativeYFace, PositiveYFace}};
0203   } else {
0204     throw std::invalid_argument("Invalid axis direction");
0205   }
0206 }
0207 
0208 }  // namespace Acts
0209 
0210 // Define operator<< for CuboidVolumeBounds::Face outside the class
0211 std::ostream& operator<<(std::ostream& os,
0212                          Acts::CuboidVolumeBounds::Face face) {
0213   using enum Acts::CuboidVolumeBounds::Face;
0214   switch (face) {
0215     case NegativeXFace:
0216       return os << "NegativeXFace";
0217     case PositiveXFace:
0218       return os << "PositiveXFace";
0219     case NegativeYFace:
0220       return os << "NegativeYFace";
0221     case PositiveYFace:
0222       return os << "PositiveYFace";
0223     case NegativeZFace:
0224       return os << "NegativeZFace";
0225     case PositiveZFace:
0226       return os << "PositiveZFace";
0227     default:
0228       return os << "UnknownFace";
0229   }
0230 }