File indexing completed on 2025-08-05 08:09:11
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Common.hpp"
0013 #include "Acts/Detector/DetectorVolumeVisitorConcept.hpp"
0014 #include "Acts/Detector/Portal.hpp"
0015 #include "Acts/Detector/PortalGenerators.hpp"
0016 #include "Acts/Geometry/Extent.hpp"
0017 #include "Acts/Geometry/GeometryContext.hpp"
0018 #include "Acts/Geometry/GeometryIdentifier.hpp"
0019 #include "Acts/Geometry/VolumeBounds.hpp"
0020 #include "Acts/Material/IVolumeMaterial.hpp"
0021 #include "Acts/Navigation/NavigationDelegates.hpp"
0022 #include "Acts/Navigation/NavigationState.hpp"
0023 #include "Acts/Surfaces/BoundaryCheck.hpp"
0024 #include "Acts/Surfaces/SurfaceVisitorConcept.hpp"
0025 #include "Acts/Utilities/BoundingBox.hpp"
0026 #include "Acts/Utilities/Concepts.hpp"
0027 #include "Acts/Utilities/Delegate.hpp"
0028 #include "Acts/Utilities/Helpers.hpp"
0029
0030 #include <algorithm>
0031 #include <cstddef>
0032 #include <memory>
0033 #include <stdexcept>
0034 #include <string>
0035 #include <utility>
0036 #include <vector>
0037
0038 namespace Acts {
0039
0040 class Surface;
0041 class IVolumeMaterial;
0042 class VolumeBounds;
0043
0044 namespace Experimental {
0045
0046 class DetectorVolume;
0047 class Detector;
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 class DetectorVolume : public std::enable_shared_from_this<DetectorVolume> {
0063 public:
0064 using BoundingBox =
0065 Acts::AxisAlignedBoundingBox<Acts::Experimental::DetectorVolume,
0066 Acts::ActsScalar, 3>;
0067
0068 friend class DetectorVolumeFactory;
0069
0070
0071
0072
0073
0074
0075
0076
0077 template <typename internal_type>
0078 struct ObjectStore {
0079
0080 std::vector<internal_type> internal = {};
0081
0082
0083 std::vector<const typename internal_type::element_type*> external = {};
0084
0085
0086
0087
0088 ObjectStore(std::vector<internal_type> objects)
0089 : internal(std::move(objects)) {
0090 external = unpack_shared_const_vector(internal);
0091 }
0092
0093 ObjectStore() = default;
0094 };
0095
0096 protected:
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111 DetectorVolume(
0112 const GeometryContext& gctx, std::string name,
0113 const Transform3& transform, std::shared_ptr<VolumeBounds> bounds,
0114 std::vector<std::shared_ptr<Surface>> surfaces,
0115 std::vector<std::shared_ptr<DetectorVolume>> volumes,
0116 DetectorVolumeUpdater detectorVolumeUpdater,
0117 SurfaceCandidatesUpdater surfaceCandidateUpdater) noexcept(false);
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 DetectorVolume(
0131 const GeometryContext& gctx, std::string name,
0132 const Transform3& transform, std::shared_ptr<VolumeBounds> bounds,
0133 SurfaceCandidatesUpdater surfaceCandidateUpdater) noexcept(false);
0134
0135
0136
0137
0138 static std::shared_ptr<DetectorVolume> makeShared(
0139 const GeometryContext& gctx, std::string name,
0140 const Transform3& transform, std::shared_ptr<VolumeBounds> bounds,
0141 std::vector<std::shared_ptr<Surface>> surfaces,
0142 std::vector<std::shared_ptr<DetectorVolume>> volumes,
0143 DetectorVolumeUpdater detectorVolumeUpdater,
0144 SurfaceCandidatesUpdater surfaceCandidateUpdater);
0145
0146
0147
0148
0149 static std::shared_ptr<DetectorVolume> makeShared(
0150 const GeometryContext& gctx, std::string name,
0151 const Transform3& transform, std::shared_ptr<VolumeBounds> bounds,
0152 SurfaceCandidatesUpdater surfaceCandidateUpdater);
0153
0154 public:
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164 std::shared_ptr<DetectorVolume> getSharedPtr();
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 std::shared_ptr<const DetectorVolume> getSharedPtr() const;
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185 const Transform3& transform(
0186 const GeometryContext& gctx = GeometryContext()) const;
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196 Vector3 center(const GeometryContext& gctx = GeometryContext()) const;
0197
0198
0199
0200
0201 const VolumeBounds& volumeBounds() const;
0202
0203
0204
0205
0206
0207
0208
0209 bool inside(const GeometryContext& gctx, const Vector3& position) const;
0210
0211
0212
0213
0214
0215
0216
0217
0218 bool exclusivelyInside(const GeometryContext& gctx,
0219 const Vector3& position) const;
0220
0221
0222
0223
0224
0225
0226
0227 Extent extent(const GeometryContext& gctx, std::size_t nseg = 1) const;
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240 void updateNavigationState(const GeometryContext& gctx,
0241 NavigationState& nState) const;
0242
0243
0244
0245
0246 std::vector<std::shared_ptr<Portal>>& portalPtrs();
0247
0248
0249
0250
0251 std::vector<std::shared_ptr<Surface>>& surfacePtrs();
0252
0253
0254
0255
0256 std::vector<std::shared_ptr<DetectorVolume>>& volumePtrs();
0257
0258
0259
0260
0261
0262
0263
0264 const std::vector<const Portal*>& portals() const;
0265
0266
0267
0268
0269
0270
0271
0272
0273 const std::vector<const Surface*>& surfaces() const;
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283 const std::vector<const DetectorVolume*>& volumes() const;
0284
0285
0286 const DetectorVolumeUpdater& detectorVolumeUpdater() const;
0287
0288
0289
0290
0291
0292
0293
0294 template <ACTS_CONCEPT(SurfaceVisitor) visitor_t>
0295 void visitSurfaces(visitor_t&& visitor) const {
0296 for (const auto& s : surfaces()) {
0297 visitor(s);
0298 }
0299 for (const auto& p : portals()) {
0300 p->visitSurface(std::forward<visitor_t>(visitor));
0301 }
0302 for (const auto& v : volumes()) {
0303 v->visitSurfaces(std::forward<visitor_t>(visitor));
0304 }
0305 }
0306
0307
0308
0309
0310
0311
0312
0313 template <ACTS_CONCEPT(MutableSurfaceVisitor) visitor_t>
0314 void visitMutableSurfaces(visitor_t&& visitor) {
0315 for (auto& s : surfacePtrs()) {
0316 visitor(s.get());
0317 }
0318 for (auto& p : portalPtrs()) {
0319 p->visitMutableSurface(std::forward<visitor_t>(visitor));
0320 }
0321 for (auto& v : volumePtrs()) {
0322 v->visitMutableSurfaces(std::forward<visitor_t>(visitor));
0323 }
0324 }
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336 template <ACTS_CONCEPT(DetectorVolumeVisitor) visitor_t>
0337 void visitVolumes(visitor_t&& visitor) const {
0338 visitor(this);
0339 for (const auto& v : volumes()) {
0340 v->visitVolumes(std::forward<visitor_t>(visitor));
0341 }
0342 }
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354 template <ACTS_CONCEPT(MutableDetectorVolumeVisitor) visitor_t>
0355 void visitMutableVolumes(visitor_t&& visitor) {
0356 visitor(this);
0357 for (auto& v : volumePtrs()) {
0358 v->visitMutableVolumes(std::forward<visitor_t>(visitor));
0359 }
0360 }
0361
0362
0363
0364
0365
0366
0367
0368
0369 void assignSurfaceCandidatesUpdater(
0370 SurfaceCandidatesUpdater surfaceCandidateUpdater,
0371 const std::vector<std::shared_ptr<Surface>>& surfaces = {},
0372 const std::vector<std::shared_ptr<DetectorVolume>>& volumes = {});
0373
0374
0375 const SurfaceCandidatesUpdater& surfaceCandidatesUpdater() const;
0376
0377
0378
0379
0380
0381
0382
0383 void updatePortal(std::shared_ptr<Portal> portal,
0384 unsigned int pIndex) noexcept(false);
0385
0386
0387 void closePortals();
0388
0389
0390
0391
0392
0393
0394
0395
0396 void assignVolumeMaterial(std::shared_ptr<IVolumeMaterial> material);
0397
0398
0399 std::shared_ptr<IVolumeMaterial> volumeMaterialPtr();
0400
0401
0402 const IVolumeMaterial* volumeMaterial() const;
0403
0404
0405 const std::string& name() const;
0406
0407
0408 const GeometryIdentifier& geometryId() const;
0409
0410
0411
0412
0413
0414 void assignGeometryId(const GeometryIdentifier& geoID);
0415
0416
0417
0418 void assignDetector(const Detector& detector);
0419
0420
0421 const Detector* detector() const;
0422
0423 const BoundingBox& getBoundingBox() const;
0424
0425 private:
0426
0427
0428
0429
0430
0431
0432 void construct(const GeometryContext& gctx,
0433 const PortalGenerator& portalGenerator) noexcept(false);
0434
0435
0436
0437
0438
0439
0440
0441 bool checkContainment(const GeometryContext& gctx,
0442 std::size_t nseg = 1) const;
0443
0444
0445
0446 void createBoundingBox(const GeometryContext& gctx);
0447
0448
0449 std::string m_name = "Unnamed";
0450
0451
0452 Transform3 m_transform = Transform3::Identity();
0453
0454
0455 std::shared_ptr<VolumeBounds> m_bounds = nullptr;
0456
0457
0458 ObjectStore<std::shared_ptr<Portal>> m_portals;
0459
0460
0461 ObjectStore<std::shared_ptr<Surface>> m_surfaces;
0462
0463
0464 ObjectStore<std::shared_ptr<DetectorVolume>> m_volumes;
0465
0466
0467 std::shared_ptr<const BoundingBox> m_boundingBox;
0468
0469 DetectorVolumeUpdater m_detectorVolumeUpdater;
0470
0471
0472 SurfaceCandidatesUpdater m_surfaceCandidatesUpdater;
0473
0474
0475 std::shared_ptr<IVolumeMaterial> m_volumeMaterial = nullptr;
0476
0477
0478 GeometryIdentifier m_geometryId{0};
0479
0480
0481 const Detector* m_detector = nullptr;
0482 };
0483
0484
0485
0486
0487
0488
0489
0490 class DetectorVolumeFactory {
0491 public:
0492
0493 static std::shared_ptr<DetectorVolume> construct(
0494 const PortalGenerator& portalGenerator, const GeometryContext& gctx,
0495 const std::string& name, const Transform3& transform,
0496 std::shared_ptr<VolumeBounds> bounds,
0497 const std::vector<std::shared_ptr<Surface>>& surfaces,
0498 const std::vector<std::shared_ptr<DetectorVolume>>& volumes,
0499 DetectorVolumeUpdater detectorVolumeUpdater,
0500 SurfaceCandidatesUpdater surfaceCandidateUpdater, int nSeg = -1) {
0501 auto dVolume = DetectorVolume::makeShared(
0502 gctx, name, transform, std::move(bounds), surfaces, volumes,
0503 std::move(detectorVolumeUpdater), std::move(surfaceCandidateUpdater));
0504 dVolume->construct(gctx, portalGenerator);
0505
0506
0507
0508
0509 if (nSeg > 0 && !dVolume->checkContainment(gctx, nSeg)) {
0510 throw std::invalid_argument(
0511 "DetectorVolume: surfaces or subvolumes are not contained by volume");
0512 }
0513 return dVolume;
0514 }
0515
0516
0517 static std::shared_ptr<DetectorVolume> construct(
0518 const PortalGenerator& portalGenerator, const GeometryContext& gctx,
0519 std::string name, const Transform3& transform,
0520 std::shared_ptr<VolumeBounds> bounds,
0521 SurfaceCandidatesUpdater surfaceCandidateUpdater) {
0522 auto dVolume = DetectorVolume::makeShared(
0523 gctx, std::move(name), transform, std::move(bounds),
0524 std::move(surfaceCandidateUpdater));
0525 dVolume->construct(gctx, portalGenerator);
0526 return dVolume;
0527 }
0528 };
0529
0530
0531 struct AllPortalsExtractor {
0532
0533
0534
0535
0536
0537
0538 inline static const std::vector<const Portal*> extract(
0539 [[maybe_unused]] const GeometryContext& gctx,
0540 const NavigationState& nState) {
0541 if (nState.currentVolume == nullptr) {
0542 throw std::runtime_error(
0543 "AllPortalsExtractor: no detector volume given.");
0544 }
0545 return nState.currentVolume->portals();
0546 }
0547 };
0548
0549
0550 struct AllSurfacesExtractor {
0551
0552
0553
0554
0555
0556
0557
0558 inline static const std::vector<const Surface*> extract(
0559 [[maybe_unused]] const GeometryContext& gctx,
0560 const NavigationState& nState,
0561 [[maybe_unused]] const std::vector<std::size_t>& indices = {}) {
0562 if (nState.currentVolume == nullptr) {
0563 throw std::runtime_error(
0564 "AllSurfacesExtractor: no detector volume given.");
0565 }
0566 return nState.currentVolume->surfaces();
0567 }
0568 };
0569
0570
0571 struct IndexedSurfacesExtractor {
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581 inline static const std::vector<const Surface*> extract(
0582 [[maybe_unused]] const GeometryContext& gctx,
0583 const NavigationState& nState, const std::vector<std::size_t>& indices) {
0584 if (nState.currentVolume == nullptr) {
0585 throw std::runtime_error(
0586 "IndexedSurfacesExtractor: no detector volume given.");
0587 }
0588
0589 const auto& surfaces = nState.currentVolume->surfaces();
0590
0591 std::vector<const Surface*> eSurfaces;
0592 eSurfaces.reserve(indices.size());
0593 std::for_each(indices.begin(), indices.end(),
0594 [&](const auto& i) { eSurfaces.push_back(surfaces[i]); });
0595 return eSurfaces;
0596 }
0597 };
0598
0599
0600 struct AllSubVolumesExtractor {
0601
0602
0603
0604
0605
0606
0607
0608 inline static const std::vector<const DetectorVolume*> extract(
0609 [[maybe_unused]] const GeometryContext& gctx,
0610 const NavigationState& nState,
0611 [[maybe_unused]] const std::vector<std::size_t>& indices = {}) {
0612 if (nState.currentVolume == nullptr) {
0613 throw std::runtime_error(
0614 "AllSubVolumesExtractor: no detector volume given.");
0615 }
0616 return nState.currentVolume->volumes();
0617 }
0618 };
0619
0620
0621 struct IndexedSubVolumesExtractor {
0622
0623
0624
0625
0626
0627
0628
0629 inline static const std::vector<const DetectorVolume*> extract(
0630 [[maybe_unused]] const GeometryContext& gctx,
0631 const NavigationState& nState, const std::vector<std::size_t>& indices) {
0632 if (nState.currentVolume == nullptr) {
0633 throw std::runtime_error(
0634 "AllSubVolumesExtractor: no detector volume given.");
0635 }
0636
0637 const auto& volumes = nState.currentVolume->volumes();
0638
0639 std::vector<const DetectorVolume*> eVolumes;
0640 eVolumes.reserve(indices.size());
0641 std::for_each(indices.begin(), indices.end(),
0642 [&](const auto& i) { eVolumes.push_back(volumes[i]); });
0643 return eVolumes;
0644 }
0645 };
0646
0647 }
0648 }