Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:34

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2022-2023 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 http://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Detector/DetectorVolume.hpp"
0010 
0011 #include "Acts/Definitions/Direction.hpp"
0012 #include "Acts/Detector/Portal.hpp"
0013 #include "Acts/Geometry/Polyhedron.hpp"
0014 #include "Acts/Geometry/VolumeBounds.hpp"
0015 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0016 #include "Acts/Navigation/DetectorVolumeUpdaters.hpp"
0017 #include "Acts/Navigation/NavigationState.hpp"
0018 #include "Acts/Surfaces/Surface.hpp"
0019 #include "Acts/Utilities/Delegate.hpp"
0020 #include "Acts/Utilities/Enumerate.hpp"
0021 
0022 #include <cassert>
0023 #include <iterator>
0024 
0025 namespace Acts {
0026 class IVolumeMaterial;
0027 }  // namespace Acts
0028 
0029 Acts::Experimental::DetectorVolume::DetectorVolume(
0030     const GeometryContext& gctx, std::string name, const Transform3& transform,
0031     std::shared_ptr<VolumeBounds> bounds,
0032     std::vector<std::shared_ptr<Surface>> surfaces,
0033     std::vector<std::shared_ptr<DetectorVolume>> volumes,
0034     DetectorVolumeUpdater detectorVolumeUpdater,
0035     SurfaceCandidatesUpdater surfaceCandidateUpdater)
0036     : m_name(std::move(name)),
0037       m_transform(transform),
0038       m_bounds(std::move(bounds)),
0039       m_surfaces(std::move(surfaces)),
0040       m_volumes(std::move(volumes)),
0041       m_detectorVolumeUpdater(std::move(detectorVolumeUpdater)),
0042       m_surfaceCandidatesUpdater(std::move(surfaceCandidateUpdater)),
0043       m_volumeMaterial(nullptr) {
0044   if (m_bounds == nullptr) {
0045     throw std::invalid_argument(
0046         "DetectorVolume: construction with nullptr bounds.");
0047   }
0048   if (!m_detectorVolumeUpdater.connected()) {
0049     throw std::invalid_argument(
0050         "DetectorVolume: navigation state updator delegate is not connected.");
0051   }
0052   if (!m_surfaceCandidatesUpdater.connected()) {
0053     throw std::invalid_argument(
0054         "DetectorVolume: navigation state updator delegate is not connected.");
0055   }
0056 
0057   [[maybe_unused]] const auto& gctx_ref = gctx;
0058 }
0059 
0060 Acts::Experimental::DetectorVolume::DetectorVolume(
0061     const GeometryContext& gctx, std::string name, const Transform3& transform,
0062     std::shared_ptr<VolumeBounds> bounds,
0063     SurfaceCandidatesUpdater surfaceCandidateUpdater)
0064     : DetectorVolume(gctx, std::move(name), transform, std::move(bounds), {},
0065                      {}, tryNoVolumes(), std::move(surfaceCandidateUpdater)) {}
0066 
0067 std::shared_ptr<Acts::Experimental::DetectorVolume>
0068 Acts::Experimental::DetectorVolume::makeShared(
0069     const GeometryContext& gctx, std::string name, const Transform3& transform,
0070     std::shared_ptr<VolumeBounds> bounds,
0071     std::vector<std::shared_ptr<Surface>> surfaces,
0072     std::vector<std::shared_ptr<DetectorVolume>> volumes,
0073     DetectorVolumeUpdater detectorVolumeUpdater,
0074     SurfaceCandidatesUpdater surfaceCandidateUpdater) {
0075   return std::shared_ptr<DetectorVolume>(new DetectorVolume(
0076       gctx, std::move(name), transform, std::move(bounds), std::move(surfaces),
0077       std::move(volumes), std::move(detectorVolumeUpdater),
0078       std::move(surfaceCandidateUpdater)));
0079 }
0080 
0081 std::shared_ptr<Acts::Experimental::DetectorVolume>
0082 Acts::Experimental::DetectorVolume::makeShared(
0083     const GeometryContext& gctx, std::string name, const Transform3& transform,
0084     std::shared_ptr<VolumeBounds> bounds,
0085     SurfaceCandidatesUpdater surfaceCandidateUpdater) {
0086   return std::shared_ptr<DetectorVolume>(
0087       new DetectorVolume(gctx, std::move(name), transform, std::move(bounds),
0088                          std::move(surfaceCandidateUpdater)));
0089 }
0090 
0091 const Acts::Transform3& Acts::Experimental::DetectorVolume::transform(
0092     const GeometryContext& /*gctx*/) const {
0093   return m_transform;
0094 }
0095 
0096 Acts::Vector3 Acts::Experimental::DetectorVolume::center(
0097     const GeometryContext& gctx) const {
0098   return transform(gctx).translation();
0099 }
0100 
0101 const Acts::VolumeBounds& Acts::Experimental::DetectorVolume::volumeBounds()
0102     const {
0103   return (*m_bounds.get());
0104 }
0105 
0106 std::vector<std::shared_ptr<Acts::Experimental::Portal>>&
0107 Acts::Experimental::DetectorVolume::portalPtrs() {
0108   return m_portals.internal;
0109 }
0110 
0111 std::vector<std::shared_ptr<Acts::Surface>>&
0112 Acts::Experimental::DetectorVolume::surfacePtrs() {
0113   return m_surfaces.internal;
0114 }
0115 
0116 std::vector<std::shared_ptr<Acts::Experimental::DetectorVolume>>&
0117 Acts::Experimental::DetectorVolume::volumePtrs() {
0118   return m_volumes.internal;
0119 }
0120 
0121 const std::vector<const Acts::Experimental::Portal*>&
0122 Acts::Experimental::DetectorVolume::portals() const {
0123   return m_portals.external;
0124 }
0125 
0126 const std::vector<const Acts::Surface*>&
0127 Acts::Experimental::DetectorVolume::surfaces() const {
0128   return m_surfaces.external;
0129 }
0130 
0131 const std::vector<const Acts::Experimental::DetectorVolume*>&
0132 Acts::Experimental::DetectorVolume::volumes() const {
0133   return m_volumes.external;
0134 }
0135 
0136 const Acts::Experimental::DetectorVolumeUpdater&
0137 Acts::Experimental::DetectorVolume::detectorVolumeUpdater() const {
0138   return m_detectorVolumeUpdater;
0139 }
0140 
0141 const Acts::Experimental::SurfaceCandidatesUpdater&
0142 Acts::Experimental::DetectorVolume::surfaceCandidatesUpdater() const {
0143   return m_surfaceCandidatesUpdater;
0144 }
0145 
0146 void Acts::Experimental::DetectorVolume::assignVolumeMaterial(
0147     std::shared_ptr<IVolumeMaterial> material) {
0148   m_volumeMaterial = std::move(material);
0149 }
0150 
0151 std::shared_ptr<Acts::IVolumeMaterial>
0152 Acts::Experimental::DetectorVolume::volumeMaterialPtr() {
0153   return m_volumeMaterial;
0154 }
0155 
0156 const Acts::IVolumeMaterial*
0157 Acts::Experimental::DetectorVolume::volumeMaterial() const {
0158   return m_volumeMaterial.get();
0159 }
0160 
0161 const Acts::GeometryIdentifier& Acts::Experimental::DetectorVolume::geometryId()
0162     const {
0163   return m_geometryId;
0164 }
0165 
0166 void Acts::Experimental::DetectorVolume::assignGeometryId(
0167     const GeometryIdentifier& geoID) {
0168   m_geometryId = geoID;
0169 }
0170 
0171 const std::string& Acts::Experimental::DetectorVolume::name() const {
0172   return m_name;
0173 }
0174 
0175 void Acts::Experimental::DetectorVolume::assignDetector(
0176     const Detector& detector) {
0177   m_detector = &detector;
0178 
0179   for (auto& v : m_volumes.internal) {
0180     v->assignDetector(detector);
0181   }
0182 }
0183 
0184 const Acts::Experimental::Detector*
0185 Acts::Experimental::DetectorVolume::detector() const {
0186   return m_detector;
0187 }
0188 
0189 void Acts::Experimental::DetectorVolume::updatePortal(
0190     std::shared_ptr<Portal> portal, unsigned int pIndex) {
0191   if (pIndex >= m_portals.internal.size()) {
0192     throw std::invalid_argument(
0193         "DetectorVolume: trying to update a portal that does not exist.");
0194   }
0195   m_portals.internal[pIndex] = std::move(portal);
0196   m_portals = ObjectStore<std::shared_ptr<Portal>>(m_portals.internal);
0197 }
0198 
0199 void Acts::Experimental::DetectorVolume::construct(
0200     const GeometryContext& gctx, const PortalGenerator& portalGenerator) {
0201   // Create portals with the given generator
0202   auto portalSurfaces =
0203       portalGenerator(transform(gctx), *(m_bounds.get()), getSharedPtr());
0204   m_portals = ObjectStore<std::shared_ptr<Portal>>(portalSurfaces);
0205   createBoundingBox(gctx);
0206 }
0207 
0208 std::shared_ptr<Acts::Experimental::DetectorVolume>
0209 Acts::Experimental::DetectorVolume::getSharedPtr() {
0210   return shared_from_this();
0211 }
0212 
0213 std::shared_ptr<const Acts::Experimental::DetectorVolume>
0214 Acts::Experimental::DetectorVolume::getSharedPtr() const {
0215   return shared_from_this();
0216 }
0217 
0218 bool Acts::Experimental::DetectorVolume::inside(const GeometryContext& gctx,
0219                                                 const Vector3& position) const {
0220   Vector3 posInVolFrame(transform(gctx).inverse() * position);
0221   return volumeBounds().inside(posInVolFrame);
0222 }
0223 
0224 bool Acts::Experimental::DetectorVolume::exclusivelyInside(
0225     const GeometryContext& gctx, const Vector3& position) const {
0226   if (!inside(gctx, position)) {
0227     return false;
0228   }
0229   // Check exclusion through subvolume
0230   for (const auto& v : volumes()) {
0231     if (v->inside(gctx, position)) {
0232       return false;
0233     }
0234   }
0235   return true;
0236 }
0237 
0238 void Acts::Experimental::DetectorVolume::updateNavigationState(
0239     const GeometryContext& gctx, NavigationState& nState) const {
0240   nState.currentVolume = this;
0241   m_surfaceCandidatesUpdater(gctx, nState);
0242   nState.surfaceCandidateIndex = 0;
0243 }
0244 
0245 void Acts::Experimental::DetectorVolume::assignSurfaceCandidatesUpdater(
0246     SurfaceCandidatesUpdater surfaceCandidateUpdater,
0247     const std::vector<std::shared_ptr<Surface>>& surfaces,
0248     const std::vector<std::shared_ptr<DetectorVolume>>& volumes) {
0249   m_surfaceCandidatesUpdater = std::move(surfaceCandidateUpdater);
0250   m_surfaces = ObjectStore<std::shared_ptr<Surface>>(surfaces);
0251   m_volumes = ObjectStore<std::shared_ptr<DetectorVolume>>(volumes);
0252 }
0253 
0254 Acts::Extent Acts::Experimental::DetectorVolume::extent(
0255     const GeometryContext& gctx, std::size_t nseg) const {
0256   Extent volumeExtent;
0257   for (const auto* p : portals()) {
0258     volumeExtent.extend(
0259         p->surface().polyhedronRepresentation(gctx, nseg).extent());
0260   }
0261   return volumeExtent;
0262 }
0263 
0264 bool Acts::Experimental::DetectorVolume::checkContainment(
0265     const GeometryContext& gctx, std::size_t nseg) const {
0266   // We don't have a logging instance here
0267   // so can't throw a warning for shapes that are
0268   // using the bounding box
0269   auto binningValues = volumeBounds().canonicalBinning();
0270 
0271   // Create the volume extent
0272   auto volumeExtent = extent(gctx, nseg);
0273   // Check surfaces
0274   for (auto b : binningValues) {
0275     for (const auto* s : surfaces()) {
0276       auto sExtent = s->polyhedronRepresentation(gctx, nseg).extent();
0277       if (!volumeExtent.contains(sExtent, b)) {
0278         return false;
0279       }
0280     }
0281     // Check volumes
0282     for (const auto* v : volumes()) {
0283       auto vExtent = v->extent(gctx, nseg);
0284       if (!volumeExtent.contains(vExtent, b)) {
0285         return false;
0286       }
0287     }
0288   }
0289   // All contained
0290   return true;
0291 }
0292 
0293 void Acts::Experimental::DetectorVolume::closePortals() {
0294   for (auto& p : m_portals.internal) {
0295     // Create a null link
0296     for (auto [ivu, vu] : enumerate(p->detectorVolumeUpdaters())) {
0297       if (!vu.connected()) {
0298         auto eowDir = Direction::fromIndex(ivu);
0299         auto eow = std::make_unique<const EndOfWorldImpl>();
0300         Acts::Experimental::DetectorVolumeUpdater eowLink;
0301         eowLink.connect<&EndOfWorldImpl::update>(std::move(eow));
0302         p->assignDetectorVolumeUpdater(eowDir, std::move(eowLink), {});
0303       }
0304     }
0305   }
0306 
0307   for (auto& v : m_volumes.internal) {
0308     v->closePortals();
0309   }
0310 }
0311 
0312 void Acts::Experimental::DetectorVolume::createBoundingBox(
0313     const GeometryContext& gctx) {
0314   std::vector<Vector3> vertices;
0315   for (auto p : m_portals.external) {
0316     auto surface = p->surface().polyhedronRepresentation(gctx, 1);
0317     auto pVertices = surface.vertices;
0318     for (const auto& v : pVertices) {
0319       vertices.push_back(v);
0320     }
0321   }
0322   Acts::Vector3 vmin = Acts::Vector3::Zero();
0323   Acts::Vector3 vmax = Acts::Vector3::Zero();
0324   for (const auto& v : vertices) {
0325     vmin = vmin.cwiseMin(v);
0326     vmax = vmax.cwiseMax(v);
0327   }
0328   std::shared_ptr<Acts::Experimental::DetectorVolume::BoundingBox> box =
0329       std::make_shared<Acts::Experimental::DetectorVolume::BoundingBox>(
0330           this, vmin, vmax);
0331   m_boundingBox = box;
0332 }
0333 
0334 const Acts::Experimental::DetectorVolume::BoundingBox&
0335 Acts::Experimental::DetectorVolume::getBoundingBox() const {
0336   return *m_boundingBox;
0337 }