File indexing completed on 2025-06-30 07:52:11
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Geometry/TrackingVolume.hpp"
0010
0011 #include "Acts/Definitions/Direction.hpp"
0012 #include "Acts/Geometry/GeometryIdentifier.hpp"
0013 #include "Acts/Geometry/GlueVolumesDescriptor.hpp"
0014 #include "Acts/Geometry/Portal.hpp"
0015 #include "Acts/Geometry/TrackingGeometryVisitor.hpp"
0016 #include "Acts/Geometry/VolumeBounds.hpp"
0017 #include "Acts/Material/IMaterialDecorator.hpp"
0018 #include "Acts/Material/IVolumeMaterial.hpp"
0019 #include "Acts/Material/ProtoVolumeMaterial.hpp"
0020 #include "Acts/Navigation/INavigationPolicy.hpp"
0021 #include "Acts/Navigation/NavigationStream.hpp"
0022 #include "Acts/Propagator/Navigator.hpp"
0023 #include "Acts/Surfaces/RegularSurface.hpp"
0024 #include "Acts/Surfaces/Surface.hpp"
0025 #include "Acts/Utilities/Intersection.hpp"
0026
0027 #include <algorithm>
0028 #include <memory>
0029 #include <ostream>
0030 #include <string>
0031 #include <utility>
0032
0033 #include <boost/container/small_vector.hpp>
0034
0035 namespace Acts {
0036
0037
0038 TrackingVolume::TrackingVolume(
0039 const Transform3& transform, std::shared_ptr<VolumeBounds> volumeBounds,
0040 std::shared_ptr<const IVolumeMaterial> volumeMaterial,
0041 std::unique_ptr<const LayerArray> staticLayerArray,
0042 std::shared_ptr<const TrackingVolumeArray> containedVolumeArray,
0043 MutableTrackingVolumeVector denseVolumeVector,
0044 const std::string& volumeName)
0045 : Volume(transform, std::move(volumeBounds)),
0046 m_confinedLayers(std::move(staticLayerArray)),
0047 m_confinedVolumes(std::move(containedVolumeArray)),
0048 m_confinedDenseVolumes({}),
0049 m_volumeMaterial(std::move(volumeMaterial)),
0050 m_name(volumeName) {
0051 createBoundarySurfaces();
0052 interlinkLayers();
0053 connectDenseBoundarySurfaces(denseVolumeVector);
0054
0055 DelegateChainBuilder{m_navigationDelegate}
0056 .add<&INavigationPolicy::noopInitializeCandidates>()
0057 .store(m_navigationDelegate);
0058 }
0059
0060 TrackingVolume::TrackingVolume(Volume& volume, const std::string& volumeName)
0061 : TrackingVolume(volume.transform(), volume.volumeBoundsPtr(), nullptr,
0062 nullptr, nullptr, MutableTrackingVolumeVector{},
0063 volumeName) {}
0064
0065 TrackingVolume::TrackingVolume(const Transform3& transform,
0066 std::shared_ptr<VolumeBounds> volbounds,
0067 const std::string& volumeName)
0068 : TrackingVolume(transform, std::move(volbounds), nullptr, nullptr, nullptr,
0069 {}, volumeName) {}
0070
0071 TrackingVolume::~TrackingVolume() = default;
0072 TrackingVolume::TrackingVolume(TrackingVolume&&) noexcept = default;
0073 TrackingVolume& TrackingVolume::operator=(TrackingVolume&&) noexcept = default;
0074
0075 const TrackingVolume* TrackingVolume::lowestTrackingVolume(
0076 const GeometryContext& gctx, const Vector3& position,
0077 const double tol) const {
0078 if (!inside(position, tol)) {
0079 return nullptr;
0080 }
0081
0082
0083 if (m_confinedVolumes) {
0084 const TrackingVolume* volume = m_confinedVolumes->object(position).get();
0085 if (volume != nullptr) {
0086 return volume->lowestTrackingVolume(gctx, position, tol);
0087 }
0088 }
0089
0090
0091 if (!m_confinedDenseVolumes.empty()) {
0092 for (auto& denseVolume : m_confinedDenseVolumes) {
0093 if (denseVolume->inside(position, tol)) {
0094 return denseVolume.get();
0095 }
0096 }
0097 }
0098
0099
0100 for (const auto& volume : volumes()) {
0101 if (volume.inside(position, tol)) {
0102 return volume.lowestTrackingVolume(gctx, position, tol);
0103 }
0104 }
0105
0106
0107 return this;
0108 }
0109
0110 const TrackingVolumeBoundaries& TrackingVolume::boundarySurfaces() const {
0111 return m_boundarySurfaces;
0112 }
0113
0114 void TrackingVolume::connectDenseBoundarySurfaces(
0115 MutableTrackingVolumeVector& confinedDenseVolumes) {
0116 if (!confinedDenseVolumes.empty()) {
0117 Direction dir = Direction::Positive();
0118
0119 for (auto& confDenseVol : confinedDenseVolumes) {
0120
0121 auto& boundSur = confDenseVol->boundarySurfaces();
0122 for (std::size_t i = 0; i < boundSur.size(); i++) {
0123
0124
0125 if (boundSur.at(i) == nullptr) {
0126 continue;
0127 }
0128
0129
0130
0131 auto mutableBs =
0132 std::const_pointer_cast<BoundarySurfaceT<TrackingVolume>>(
0133 boundSur.at(i));
0134 if (mutableBs->m_oppositeVolume != nullptr &&
0135 mutableBs->m_alongVolume == nullptr) {
0136 dir = Direction::Positive();
0137 mutableBs->attachVolume(this, dir);
0138 } else {
0139 if (mutableBs->m_oppositeVolume == nullptr &&
0140 mutableBs->m_alongVolume != nullptr) {
0141 dir = Direction::Negative();
0142 mutableBs->attachVolume(this, dir);
0143 }
0144 }
0145
0146
0147 confDenseVol->updateBoundarySurface(static_cast<BoundarySurfaceFace>(i),
0148 mutableBs);
0149 }
0150
0151 m_confinedDenseVolumes.push_back(std::move(confDenseVol));
0152 }
0153 }
0154 }
0155
0156 void TrackingVolume::createBoundarySurfaces() {
0157 using Boundary = BoundarySurfaceT<TrackingVolume>;
0158
0159
0160 auto orientedSurfaces = Volume::volumeBounds().orientedSurfaces(m_transform);
0161
0162 m_boundarySurfaces.reserve(orientedSurfaces.size());
0163 for (auto& osf : orientedSurfaces) {
0164 TrackingVolume* opposite = nullptr;
0165 TrackingVolume* along = nullptr;
0166 if (osf.direction == Direction::OppositeNormal()) {
0167 opposite = this;
0168 } else {
0169 along = this;
0170 }
0171 m_boundarySurfaces.push_back(std::make_shared<const Boundary>(
0172 std::move(osf.surface), opposite, along));
0173 }
0174 }
0175
0176 void TrackingVolume::clearBoundarySurfaces() {
0177 m_boundarySurfaces.clear();
0178 }
0179
0180 void TrackingVolume::glueTrackingVolume(const GeometryContext& gctx,
0181 BoundarySurfaceFace bsfMine,
0182 TrackingVolume* neighbor,
0183 BoundarySurfaceFace bsfNeighbor) {
0184
0185
0186 Vector3 bPosition(referencePosition(gctx, AxisDirection::AxisR));
0187 Vector3 distance = Vector3(
0188 neighbor->referencePosition(gctx, AxisDirection::AxisR) - bPosition);
0189
0190 std::shared_ptr<const BoundarySurfaceT<TrackingVolume>> bSurfaceMine =
0191 boundarySurfaces().at(bsfMine);
0192
0193
0194
0195
0196 Vector3 nvector =
0197 bSurfaceMine->surfaceRepresentation().normal(gctx, bPosition);
0198
0199 Direction dir = Direction::fromScalar(nvector.dot(distance));
0200
0201
0202 if ((m_glueVolumeDescriptor == nullptr) ||
0203 m_glueVolumeDescriptor->glueVolumes(bsfMine) == nullptr) {
0204
0205 auto mutableBSurfaceMine =
0206 std::const_pointer_cast<BoundarySurfaceT<TrackingVolume>>(bSurfaceMine);
0207 mutableBSurfaceMine->attachVolume(neighbor, dir);
0208
0209 const Surface& neighborSurface =
0210 neighbor->m_boundarySurfaces.at(bsfNeighbor)->surfaceRepresentation();
0211 auto neighborMaterial = neighborSurface.surfaceMaterialSharedPtr();
0212 const Surface& mySurface = bSurfaceMine->surfaceRepresentation();
0213 auto myMaterial = mySurface.surfaceMaterialSharedPtr();
0214
0215 if (myMaterial == nullptr && neighborMaterial != nullptr) {
0216 Surface* myMutbableSurface = const_cast<Surface*>(&mySurface);
0217 myMutbableSurface->assignSurfaceMaterial(neighborMaterial);
0218 }
0219
0220 (neighbor->m_boundarySurfaces).at(bsfNeighbor) = bSurfaceMine;
0221 }
0222 }
0223
0224 void TrackingVolume::glueTrackingVolumes(
0225 const GeometryContext& gctx, BoundarySurfaceFace bsfMine,
0226 const std::shared_ptr<TrackingVolumeArray>& neighbors,
0227 BoundarySurfaceFace bsfNeighbor) {
0228
0229
0230 std::shared_ptr<const TrackingVolume> nRefVolume =
0231 neighbors->arrayObjects().at(0);
0232
0233 Vector3 bPosition(referencePosition(gctx, AxisDirection::AxisR));
0234 Vector3 distance(nRefVolume->referencePosition(gctx, AxisDirection::AxisR) -
0235 bPosition);
0236
0237 std::shared_ptr<const BoundarySurfaceT<TrackingVolume>> bSurfaceMine =
0238 boundarySurfaces().at(bsfMine);
0239
0240
0241
0242
0243 Vector3 nvector =
0244 bSurfaceMine->surfaceRepresentation().normal(gctx, bPosition);
0245
0246 Direction dir = Direction::fromScalar(nvector.dot(distance));
0247
0248
0249 if ((m_glueVolumeDescriptor == nullptr) ||
0250 !m_glueVolumeDescriptor->glueVolumes(bsfMine)) {
0251
0252 auto mutableBSurfaceMine =
0253 std::const_pointer_cast<BoundarySurfaceT<TrackingVolume>>(bSurfaceMine);
0254 mutableBSurfaceMine->attachVolumeArray(neighbors, dir);
0255
0256 for (auto& nVolume : neighbors->arrayObjects()) {
0257 auto mutableNVolume = std::const_pointer_cast<TrackingVolume>(nVolume);
0258 (mutableNVolume->m_boundarySurfaces).at(bsfNeighbor) = bSurfaceMine;
0259 }
0260 }
0261 }
0262
0263 void TrackingVolume::assignBoundaryMaterial(
0264 std::shared_ptr<const ISurfaceMaterial> surfaceMaterial,
0265 BoundarySurfaceFace bsFace) {
0266 auto bSurface = m_boundarySurfaces.at(bsFace);
0267 RegularSurface* surface =
0268 const_cast<RegularSurface*>(&bSurface->surfaceRepresentation());
0269 surface->assignSurfaceMaterial(std::move(surfaceMaterial));
0270 }
0271
0272 void TrackingVolume::updateBoundarySurface(
0273 BoundarySurfaceFace bsf,
0274 std::shared_ptr<const BoundarySurfaceT<TrackingVolume>> bs,
0275 bool checkmaterial) {
0276 if (checkmaterial) {
0277 auto cMaterialPtr = m_boundarySurfaces.at(bsf)
0278 ->surfaceRepresentation()
0279 .surfaceMaterialSharedPtr();
0280 auto bsMaterial = bs->surfaceRepresentation().surfaceMaterial();
0281 if (cMaterialPtr != nullptr && bsMaterial == nullptr) {
0282 RegularSurface* surface =
0283 const_cast<RegularSurface*>(&bs->surfaceRepresentation());
0284 surface->assignSurfaceMaterial(cMaterialPtr);
0285 }
0286 }
0287 m_boundarySurfaces.at(bsf) = std::move(bs);
0288 }
0289
0290 void TrackingVolume::registerGlueVolumeDescriptor(
0291 std::unique_ptr<GlueVolumesDescriptor> gvd) {
0292 m_glueVolumeDescriptor = std::move(gvd);
0293 }
0294
0295 GlueVolumesDescriptor& TrackingVolume::glueVolumesDescriptor() {
0296 if (m_glueVolumeDescriptor == nullptr) {
0297 m_glueVolumeDescriptor = std::make_unique<GlueVolumesDescriptor>();
0298 }
0299 return *m_glueVolumeDescriptor;
0300 }
0301
0302 void TrackingVolume::synchronizeLayers(double envelope) const {
0303
0304
0305
0306
0307 if (m_confinedLayers) {
0308
0309
0310
0311 for (auto& clayIter : m_confinedLayers->arrayObjects()) {
0312 if (clayIter) {
0313
0314
0315
0316
0317
0318
0319 }
0320
0321
0322 }
0323 }
0324
0325
0326 if (m_confinedVolumes) {
0327
0328
0329
0330 for (auto& cVolumesIter : m_confinedVolumes->arrayObjects()) {
0331 cVolumesIter->synchronizeLayers(envelope);
0332 }
0333 }
0334 }
0335
0336 void TrackingVolume::interlinkLayers() {
0337 if (m_confinedLayers) {
0338 auto& layers = m_confinedLayers->arrayObjects();
0339
0340
0341
0342 const Layer* lastLayer = nullptr;
0343 for (auto& layerPtr : layers) {
0344
0345 Layer& mutableLayer = *(std::const_pointer_cast<Layer>(layerPtr));
0346
0347 mutableLayer.m_nextLayerUtility = m_confinedLayers->binUtility();
0348 mutableLayer.m_nextLayers.first = lastLayer;
0349
0350 mutableLayer.encloseTrackingVolume(*this);
0351
0352 lastLayer = &mutableLayer;
0353 }
0354
0355 lastLayer = nullptr;
0356 for (auto layerIter = layers.rbegin(); layerIter != layers.rend();
0357 ++layerIter) {
0358
0359 Layer& mutableLayer = *(std::const_pointer_cast<Layer>(*layerIter));
0360 mutableLayer.m_nextLayers.second = lastLayer;
0361 lastLayer = &mutableLayer;
0362 }
0363 }
0364 }
0365
0366
0367 boost::container::small_vector<BoundaryIntersection, 4>
0368 TrackingVolume::compatibleBoundaries(const GeometryContext& gctx,
0369 const Vector3& position,
0370 const Vector3& direction,
0371 const NavigationOptions<Surface>& options,
0372 const Logger& logger) const {
0373 ACTS_VERBOSE("Finding compatibleBoundaries");
0374
0375 boost::container::small_vector<BoundaryIntersection, 4> intersections;
0376
0377
0378 double nearLimit = options.nearLimit;
0379 double farLimit = options.farLimit;
0380
0381
0382 auto checkIntersection =
0383 [&](SurfaceMultiIntersection& candidates,
0384 const BoundarySurface* boundary) -> BoundaryIntersection {
0385 for (const auto& intersection : candidates.split()) {
0386 if (!intersection.isValid()) {
0387 continue;
0388 }
0389
0390 ACTS_VERBOSE("Check intersection with surface "
0391 << boundary->surfaceRepresentation().geometryId());
0392 if (detail::checkPathLength(intersection.pathLength(), nearLimit,
0393 farLimit, logger)) {
0394 return BoundaryIntersection(intersection, boundary);
0395 }
0396 }
0397
0398 ACTS_VERBOSE("No intersection accepted");
0399 return BoundaryIntersection(SurfaceIntersection::invalid(), nullptr);
0400 };
0401
0402
0403 auto processBoundaries =
0404 [&](const TrackingVolumeBoundaries& boundaries) -> void {
0405
0406 for (auto& boundary : boundaries) {
0407
0408 const auto& surface = boundary->surfaceRepresentation();
0409 ACTS_VERBOSE("Consider boundary surface " << surface.geometryId());
0410
0411
0412
0413
0414 if (&surface == options.startObject) {
0415 ACTS_VERBOSE(" - Surface is excluded surface");
0416 continue;
0417 }
0418
0419 auto candidates = surface.intersect(gctx, position, direction,
0420 options.boundaryTolerance);
0421
0422 auto intersection = checkIntersection(candidates, boundary.get());
0423 if (intersection.first.isValid()) {
0424 ACTS_VERBOSE(" - Proceed with surface");
0425 intersections.push_back(intersection);
0426 } else {
0427 ACTS_VERBOSE(" - Surface intersecion invalid");
0428 }
0429 }
0430 };
0431
0432
0433 const auto& surfaces = boundarySurfaces();
0434 ACTS_VERBOSE("Volume reports " << surfaces.size() << " boundary surfaces");
0435 processBoundaries(surfaces);
0436
0437
0438 auto confinedDenseVolumes = denseVolumes();
0439 ACTS_VERBOSE("Volume reports " << confinedDenseVolumes.size()
0440 << " confined dense volumes");
0441 for (const auto& volume : confinedDenseVolumes) {
0442 const auto& surfacesConfined = volume->boundarySurfaces();
0443 ACTS_VERBOSE(" -> " << surfacesConfined.size() << " boundary surfaces");
0444 processBoundaries(surfacesConfined);
0445 }
0446
0447 return intersections;
0448 }
0449
0450 boost::container::small_vector<LayerIntersection, 10>
0451 TrackingVolume::compatibleLayers(
0452 const GeometryContext& gctx, const Vector3& position,
0453 const Vector3& direction, const NavigationOptions<Layer>& options) const {
0454
0455 boost::container::small_vector<LayerIntersection, 10> lIntersections;
0456
0457
0458 if (m_confinedLayers == nullptr) {
0459 return {};
0460 }
0461
0462
0463 const Layer* tLayer = options.startObject != nullptr
0464 ? static_cast<const Layer*>(options.startObject)
0465 : associatedLayer(gctx, position);
0466 while (tLayer != nullptr) {
0467
0468
0469
0470
0471
0472 if (tLayer != options.startObject && tLayer->resolve(options)) {
0473
0474
0475 auto atIntersection =
0476 tLayer->surfaceOnApproach(gctx, position, direction, options);
0477
0478 if (atIntersection.isValid()) {
0479
0480 lIntersections.push_back(LayerIntersection(atIntersection, tLayer));
0481 }
0482 }
0483
0484 tLayer = (tLayer == options.endObject)
0485 ? nullptr
0486 : tLayer->nextLayer(gctx, position, direction);
0487 }
0488
0489
0490
0491
0492 auto min = std::min_element(
0493 lIntersections.begin(), lIntersections.end(),
0494 [](const LayerIntersection& a, const LayerIntersection& b) {
0495 return a.first.pathLength() < b.first.pathLength();
0496 });
0497 std::rotate(lIntersections.begin(), min, lIntersections.end());
0498 lIntersections.resize(std::distance(min, lIntersections.end()),
0499 {SurfaceIntersection::invalid(), nullptr});
0500
0501 return lIntersections;
0502 }
0503
0504 const std::string& TrackingVolume::volumeName() const {
0505 return m_name;
0506 }
0507
0508 void TrackingVolume::setVolumeName(const std::string& volumeName) {
0509 m_name = volumeName;
0510 }
0511
0512 const IVolumeMaterial* TrackingVolume::volumeMaterial() const {
0513 return m_volumeMaterial.get();
0514 }
0515
0516 const std::shared_ptr<const IVolumeMaterial>&
0517 TrackingVolume::volumeMaterialPtr() const {
0518 return m_volumeMaterial;
0519 }
0520
0521 void TrackingVolume::assignVolumeMaterial(
0522 std::shared_ptr<const IVolumeMaterial> material) {
0523 m_volumeMaterial = std::move(material);
0524 }
0525
0526 const LayerArray* TrackingVolume::confinedLayers() const {
0527 return m_confinedLayers.get();
0528 }
0529
0530 const MutableTrackingVolumeVector TrackingVolume::denseVolumes() const {
0531 return m_confinedDenseVolumes;
0532 }
0533
0534 std::shared_ptr<const TrackingVolumeArray> TrackingVolume::confinedVolumes()
0535 const {
0536 return m_confinedVolumes;
0537 }
0538
0539 const TrackingVolume* TrackingVolume::motherVolume() const {
0540 return m_motherVolume;
0541 }
0542
0543 TrackingVolume* TrackingVolume::motherVolume() {
0544 return m_motherVolume;
0545 }
0546
0547 void TrackingVolume::setMotherVolume(TrackingVolume* mvol) {
0548 m_motherVolume = mvol;
0549 }
0550
0551 const Acts::Layer* TrackingVolume::associatedLayer(
0552 const GeometryContext& , const Vector3& position) const {
0553
0554 if (m_confinedLayers != nullptr) {
0555 return (m_confinedLayers->object(position).get());
0556 }
0557
0558
0559 return nullptr;
0560 }
0561
0562 TrackingVolume::VolumeRange TrackingVolume::volumes() const {
0563 return VolumeRange{m_volumes};
0564 }
0565
0566 TrackingVolume::MutableVolumeRange TrackingVolume::volumes() {
0567 return MutableVolumeRange{m_volumes};
0568 }
0569
0570 TrackingVolume& TrackingVolume::addVolume(
0571 std::unique_ptr<TrackingVolume> volume) {
0572 if (volume->motherVolume() != nullptr) {
0573 throw std::invalid_argument("Volume already has a mother volume");
0574 }
0575
0576 volume->setMotherVolume(this);
0577 m_volumes.push_back(std::move(volume));
0578 return *m_volumes.back();
0579 }
0580
0581 TrackingVolume::PortalRange TrackingVolume::portals() const {
0582 return PortalRange{m_portals};
0583 }
0584
0585 TrackingVolume::MutablePortalRange TrackingVolume::portals() {
0586 return MutablePortalRange{m_portals};
0587 }
0588
0589 void TrackingVolume::addPortal(std::shared_ptr<Portal> portal) {
0590 if (portal == nullptr) {
0591 throw std::invalid_argument("Portal is nullptr");
0592 }
0593 m_portals.push_back(std::move(portal));
0594 }
0595
0596 TrackingVolume::SurfaceRange TrackingVolume::surfaces() const {
0597 return SurfaceRange{m_surfaces};
0598 }
0599
0600 TrackingVolume::MutableSurfaceRange TrackingVolume::surfaces() {
0601 return MutableSurfaceRange{m_surfaces};
0602 }
0603
0604 void TrackingVolume::addSurface(std::shared_ptr<Surface> surface) {
0605 if (surface == nullptr) {
0606 throw std::invalid_argument("Surface is nullptr");
0607 }
0608 m_surfaces.push_back(std::move(surface));
0609 }
0610
0611 void TrackingVolume::visualize(IVisualization3D& helper,
0612 const GeometryContext& gctx,
0613 const ViewConfig& viewConfig,
0614 const ViewConfig& portalViewConfig,
0615 const ViewConfig& sensitiveViewConfig) const {
0616 helper.object(volumeName());
0617 if (viewConfig.visible) {
0618 Volume::visualize(helper, gctx, viewConfig);
0619 }
0620
0621 if (sensitiveViewConfig.visible) {
0622 if (!surfaces().empty()) {
0623 helper.object(volumeName() + "_sensitives");
0624 for (const auto& surface : surfaces()) {
0625 surface.visualize(helper, gctx, sensitiveViewConfig);
0626 }
0627 }
0628 }
0629
0630 if (portalViewConfig.visible) {
0631 helper.object(volumeName() + "_portals");
0632 for (const auto& portal : portals()) {
0633 portal.surface().visualize(helper, gctx, portalViewConfig);
0634 }
0635 }
0636
0637 for (const auto& child : volumes()) {
0638 child.visualize(helper, gctx, viewConfig, portalViewConfig,
0639 sensitiveViewConfig);
0640 }
0641 }
0642
0643 void TrackingVolume::setNavigationPolicy(
0644 std::unique_ptr<INavigationPolicy> policy) {
0645 if (policy == nullptr) {
0646 throw std::invalid_argument("Navigation policy is nullptr");
0647 }
0648
0649 m_navigationPolicy = std::move(policy);
0650 m_navigationPolicy->connect(m_navigationDelegate);
0651 }
0652
0653 void TrackingVolume::initializeNavigationCandidates(
0654 const NavigationArguments& args, AppendOnlyNavigationStream& stream,
0655 const Logger& logger) const {
0656 m_navigationDelegate(args, stream, logger);
0657 }
0658
0659 namespace {
0660
0661 void visitLayer(const Acts::Layer& layer, TrackingGeometryVisitor& visitor) {
0662 visitor.visitLayer(layer);
0663
0664 if (layer.surfaceArray() != nullptr) {
0665 for (const auto& srf : layer.surfaceArray()->surfaces()) {
0666 visitor.visitSurface(*srf);
0667 }
0668 }
0669 visitor.visitSurface(layer.surfaceRepresentation());
0670 if (layer.approachDescriptor() != nullptr) {
0671 for (const auto& srf : layer.approachDescriptor()->containedSurfaces()) {
0672 visitor.visitSurface(*srf);
0673 }
0674 }
0675 }
0676
0677 }
0678
0679
0680 void TrackingVolume::apply(TrackingGeometryVisitor& visitor) const {
0681 visitor.visitVolume(*this);
0682
0683
0684 for (const auto& bs : m_boundarySurfaces) {
0685 visitor.visitBoundarySurface(*bs);
0686 visitor.visitSurface(bs->surfaceRepresentation());
0687 }
0688
0689 for (const auto& portal : portals()) {
0690 visitor.visitPortal(portal);
0691 visitor.visitSurface(portal.surface());
0692 }
0693
0694
0695 if (m_confinedLayers != nullptr) {
0696 std::ranges::for_each(
0697 m_confinedLayers->arrayObjects(),
0698 [&](const auto& layer) { visitLayer(*layer, visitor); });
0699 }
0700
0701 if (m_confinedVolumes != nullptr) {
0702
0703 for (const auto& volume : m_confinedVolumes->arrayObjects()) {
0704 volume->apply(visitor);
0705 }
0706 }
0707
0708 for (const auto& surface : surfaces()) {
0709 visitor.visitSurface(surface);
0710 }
0711
0712 for (const auto& volume : volumes()) {
0713 volume.apply(visitor);
0714 }
0715 }
0716
0717 void Acts::TrackingVolume::apply(TrackingGeometryMutableVisitor& visitor) {
0718
0719
0720 if (visitor.visitDepthFirst()) {
0721 for (auto& volume : volumes()) {
0722 volume.apply(visitor);
0723 }
0724 }
0725
0726 visitor.visitVolume(*this);
0727
0728
0729
0730
0731
0732
0733
0734 for (const auto& bs : m_boundarySurfaces) {
0735 visitor.visitBoundarySurface(
0736 const_cast<BoundarySurfaceT<TrackingVolume>&>(*bs));
0737 visitor.visitSurface(
0738 const_cast<RegularSurface&>(bs->surfaceRepresentation()));
0739 }
0740
0741 for (auto& portal : portals()) {
0742 visitor.visitPortal(portal);
0743 visitor.visitSurface(portal.surface());
0744 }
0745
0746
0747
0748
0749
0750 if (m_confinedVolumes == nullptr) {
0751
0752 if (m_confinedLayers != nullptr) {
0753 for (const auto& layer : m_confinedLayers->arrayObjects()) {
0754 visitor.visitLayer(const_cast<Layer&>(*layer));
0755
0756 if (layer->surfaceArray() != nullptr) {
0757 for (const auto& srf : layer->surfaceArray()->surfaces()) {
0758 visitor.visitSurface(const_cast<Surface&>(*srf));
0759 }
0760 }
0761
0762 visitor.visitSurface(
0763 const_cast<Surface&>(layer->surfaceRepresentation()));
0764
0765 if (layer->approachDescriptor() != nullptr) {
0766 for (const auto& srf :
0767 layer->approachDescriptor()->containedSurfaces()) {
0768 visitor.visitSurface(const_cast<Surface&>(*srf));
0769 }
0770 }
0771 }
0772 }
0773 } else {
0774
0775 for (const auto& volume : m_confinedVolumes->arrayObjects()) {
0776 const_cast<TrackingVolume&>(*volume).apply(visitor);
0777 }
0778 }
0779
0780 for (auto& surface : surfaces()) {
0781 visitor.visitSurface(surface);
0782 }
0783
0784 if (!visitor.visitDepthFirst()) {
0785
0786
0787 for (auto& volume : volumes()) {
0788 volume.apply(visitor);
0789 }
0790 }
0791 }
0792
0793 }