Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-17 07:46:38

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/detail/AlignablePortalVisitor.hpp"
0010 
0011 #include "Acts/Definitions/Tolerance.hpp"
0012 #include "Acts/Geometry/VolumeBounds.hpp"
0013 #include "Acts/Geometry/detail/TrackingGeometryPrintVisitor.hpp"
0014 #include "Acts/Surfaces/RegularSurface.hpp"
0015 #include "Acts/Utilities/StringHelpers.hpp"
0016 
0017 #include <cassert>
0018 
0019 namespace {
0020 /// @brief checks whether the two transforms are the same
0021 /// @param a: First transform to check
0022 /// @param b: Second transform to check
0023 inline bool isSame(const Acts::Transform3& a, const Acts::Transform3& b) {
0024   const Acts::Transform3 c = a * b.inverse();
0025   if (c.translation().norm() > Acts::s_onSurfaceTolerance) {
0026     return false;
0027   }
0028   for (std::size_t d = 0; d < 3; ++d) {
0029     const Acts::Vector3 e = Acts::Vector3::Unit(d);
0030     if (std::abs(e.dot(c * e) - 1.) > Acts::s_onSurfaceTolerance) {
0031       return false;
0032     }
0033   }
0034   return true;
0035 }
0036 }  // namespace
0037 
0038 namespace Acts::detail {
0039 
0040 AlignablePortalVisitor::AlignablePortalVisitor(const GeometryContext& gctx,
0041                                                const Logger& logger)
0042     : TrackingGeometryMutableVisitor{true}, m_gctx{gctx}, m_logger{logger} {}
0043 
0044 void AlignablePortalVisitor::visitVolume(TrackingVolume& volume) {
0045   if (!volume.isAlignable()) {
0046     ACTS_VERBOSE("AlignablePortalVisitor() - the volume "
0047                  << volume.geometryId() << ", " << volume.volumeBounds()
0048                  << " is not alignable");
0049     return;
0050   }
0051   ACTS_DEBUG("AlignablePortalVisitor() - Found alignable volume "
0052              << volume.geometryId() << ", " << volume.volumeBounds());
0053   std::vector<std::shared_ptr<RegularSurface>> alignable{};
0054   // We start with the most inside volume
0055   for (Portal& portal : volume.portals()) {
0056     ACTS_DEBUG("AlignablePortalVisitor() - Check wheher portal "
0057                << portal.surface().geometryId() << " is a boundary surface");
0058     if (portal.surface().isAlignable()) {
0059       continue;
0060     }
0061     alignable.push_back(
0062         dynamic_pointer_cast<RegularSurface>(portal.surface().getSharedPtr()));
0063     assert(alignable.back() != nullptr);
0064   }
0065   ACTS_DEBUG("AlignablePortalVisitor() - Associate "
0066              << alignable.size() << " portals with the volume.");
0067   std::vector<Transform3> portalTrfBefore{};
0068   // If the visitor is in inspection mode, cache the transforms of the
0069   // unaligned portals
0070   if (m_doInspect) {
0071     std::ranges::transform(alignable, std::back_inserter(portalTrfBefore),
0072                            [&](const std::shared_ptr<RegularSurface>& surface) {
0073                              return surface->localToGlobalTransform(m_gctx);
0074                            });
0075   }
0076   volume.volumePlacement()->makePortalsAlignable(m_gctx, alignable);
0077 
0078   // Check whether the children volumes are also alignable. Don't throw an
0079   // exception as it's the user's choice to declare the volumes alignable
0080   if (std::ranges::any_of(volume.volumes(), [](const Volume& childVol) {
0081         return !childVol.isAlignable();
0082       })) {
0083     TrackingGeometryPrintVisitor printVisitor{m_gctx};
0084     volume.apply(printVisitor);
0085     ACTS_ERROR("AlignablePortalVisitor() - The volume "
0086                << volume.volumeName() << " has non alignable children: \n"
0087                << printVisitor.stream().str());
0088     throw std::logic_error(
0089         "AlignablePortalVisitor() - Subvolumes of aliganble volumes must be "
0090         "also alignable");
0091   }
0092   if (!m_doInspect) {
0093     return;
0094   }
0095   // Ensure that the portal remain where they were supposed to be
0096   for (std::size_t p = 0; p < alignable.size(); ++p) {
0097     if (!alignable[p]->isAlignable()) {
0098       ACTS_ERROR("AlignablePortalVisitor() - the "
0099                  << p << "-the portal remains not alignable");
0100       throw std::runtime_error(
0101           "AlignablePortalVisitor() - The portal alignment failed");
0102     }
0103     if (alignable[p]->isSensitive()) {
0104       ACTS_ERROR("AlignablePortalVisitor() - the "
0105                  << p << "-the portal became sensitive");
0106       throw std::runtime_error(
0107           "AlignablePortalVisitor() - The portal alignment failed");
0108     }
0109     if (!isSame(alignable[p]->localToGlobalTransform(m_gctx),
0110                 portalTrfBefore[p])) {
0111       ACTS_ERROR("AlignablePortalVisitor() - the "
0112                  << p << "-the portal transforms\n --- aligned:   "
0113                  << toString(alignable[p]->localToGlobalTransform(m_gctx))
0114                  << "\n --- unaligned: " << toString(portalTrfBefore[p])
0115                  << " are not the same");
0116       throw std::runtime_error(
0117           "AlignablePortalVisitor() - The portal alignment failed");
0118     }
0119   }
0120 }
0121 
0122 const Logger& AlignablePortalVisitor::logger() const {
0123   return m_logger;
0124 }
0125 
0126 void AlignablePortalVisitor::enableInspection() {
0127   m_doInspect = true;
0128 }
0129 
0130 }  // namespace Acts::detail