File indexing completed on 2025-08-05 08:09:34
0001
0002
0003
0004
0005
0006
0007
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 }
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& ) 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
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
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
0267
0268
0269 auto binningValues = volumeBounds().canonicalBinning();
0270
0271
0272 auto volumeExtent = extent(gctx, nseg);
0273
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
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
0290 return true;
0291 }
0292
0293 void Acts::Experimental::DetectorVolume::closePortals() {
0294 for (auto& p : m_portals.internal) {
0295
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 }