File indexing completed on 2025-09-17 08:01:34
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Units.hpp"
0012 #include "Acts/Geometry/GeometryContext.hpp"
0013 #include "Acts/Geometry/ITrackingVolumeBuilder.hpp"
0014 #include "Acts/Geometry/ITrackingVolumeHelper.hpp"
0015 #include "Acts/Utilities/Logger.hpp"
0016
0017 #include <algorithm>
0018 #include <array>
0019 #include <limits>
0020 #include <memory>
0021 #include <ostream>
0022 #include <stdexcept>
0023 #include <string>
0024 #include <utility>
0025
0026 namespace Acts {
0027
0028 class IVolumeMaterial;
0029 class ISurfaceMaterial;
0030 class ILayerBuilder;
0031 class IConfinedTrackingVolumeBuilder;
0032
0033
0034 enum WrappingCondition {
0035 Undefined = 0,
0036 Attaching = 1,
0037 Inserting = 2,
0038 Wrapping = 3,
0039 CentralInserting = 4,
0040 CentralWrapping = 5,
0041 NoWrapping = 6
0042 };
0043
0044
0045 struct VolumeConfig {
0046 bool present{false};
0047 bool wrapping{false};
0048 double rMin;
0049 double rMax;
0050 double zMin;
0051 double zMax;
0052 LayerVector layers;
0053 MutableTrackingVolumeVector volumes;
0054
0055
0056 VolumeConfig()
0057 : rMin(std::numeric_limits<double>::max()),
0058 rMax(std::numeric_limits<double>::lowest()),
0059 zMin(std::numeric_limits<double>::max()),
0060 zMax(std::numeric_limits<double>::lowest()),
0061 layers() {}
0062
0063
0064
0065
0066
0067 void adaptZ(const VolumeConfig& lConfig) {
0068 if (lConfig.present) {
0069 zMin = std::min(zMin, lConfig.zMin);
0070 zMax = std::max(zMax, lConfig.zMax);
0071 }
0072 }
0073
0074
0075
0076
0077
0078 void adaptR(const VolumeConfig& lConfig) {
0079 if (lConfig.present) {
0080 rMin = std::min(rMin, lConfig.rMin);
0081 rMax = std::max(rMax, lConfig.rMax);
0082 }
0083 }
0084
0085
0086
0087
0088
0089 void adapt(const VolumeConfig& lConfig) {
0090 adaptZ(lConfig);
0091 adaptR(lConfig);
0092 }
0093
0094
0095
0096
0097
0098
0099
0100 void midPointAttachZ(VolumeConfig& lConfig) {
0101 if (lConfig.zMin >= zMax) {
0102 double zMid = 0.5 * (lConfig.zMin + zMax);
0103 lConfig.zMin = zMid;
0104 zMax = zMid;
0105 } else {
0106 double zMid = 0.5 * (zMin + lConfig.zMax);
0107 lConfig.zMax = zMid;
0108 zMin = zMid;
0109 }
0110 }
0111
0112
0113
0114
0115
0116 void attachZ(const VolumeConfig& lConfig) {
0117 if (lConfig.zMin >= zMax) {
0118 zMax = lConfig.zMin;
0119 } else {
0120 zMin = lConfig.zMax;
0121 }
0122 }
0123
0124
0125
0126
0127
0128 bool overlapsInR(const VolumeConfig& vConfig) const {
0129 if (!present) {
0130 return false;
0131 }
0132 return std::max(rMin, vConfig.rMin) <= std::min(rMax, vConfig.rMax);
0133 }
0134
0135
0136
0137
0138
0139 bool overlapsInZ(const VolumeConfig& vConfig) const {
0140 if (!present) {
0141 return false;
0142 }
0143 return std::max(zMin, vConfig.zMin) <= std::min(zMax, vConfig.zMax);
0144 }
0145
0146
0147
0148
0149
0150 bool wraps(const VolumeConfig& vConfig) const {
0151 if ((zMax <= vConfig.zMin) || (zMin >= vConfig.zMax)) {
0152 return true;
0153 }
0154 return containsInR(vConfig);
0155 }
0156
0157
0158
0159
0160 bool contains(const VolumeConfig& vConfig) const {
0161 return (containsInR(vConfig) && containsInZ(vConfig));
0162 }
0163
0164
0165
0166
0167 bool containsInR(const VolumeConfig& vConfig) const {
0168 return (rMin >= vConfig.rMax);
0169 }
0170
0171
0172
0173
0174 bool containsInZ(const VolumeConfig& vConfig) const {
0175 return (vConfig.zMin > zMin && vConfig.zMax < zMax);
0176 }
0177
0178
0179 std::string toString() const {
0180
0181 std::stringstream sl;
0182 sl << rMin << ", " << rMax << " / " << zMin << ", " << zMax;
0183 return sl.str();
0184 }
0185 };
0186
0187
0188 struct WrappingConfig {
0189 public:
0190
0191 VolumeConfig nVolumeConfig;
0192 VolumeConfig cVolumeConfig;
0193 VolumeConfig pVolumeConfig;
0194
0195
0196 VolumeConfig containerVolumeConfig;
0197
0198
0199 VolumeConfig existingVolumeConfig;
0200 VolumeConfig fGapVolumeConfig;
0201 VolumeConfig sGapVolumeConfig;
0202
0203
0204
0205 VolumeConfig externalVolumeConfig;
0206
0207
0208 WrappingCondition wCondition = Undefined;
0209 std::string wConditionScreen = "[left untouched]";
0210
0211
0212 WrappingConfig() = default;
0213
0214
0215 void configureContainerVolume() {
0216
0217 containerVolumeConfig.present = true;
0218 std::string wConditionAddon = "";
0219
0220 if ((nVolumeConfig.present && cVolumeConfig.present) ||
0221 (cVolumeConfig.present && pVolumeConfig.present) ||
0222 (nVolumeConfig.present && pVolumeConfig.present)) {
0223 wCondition = Wrapping;
0224 wConditionScreen = "grouped to ";
0225 }
0226
0227 if (nVolumeConfig.present) {
0228 containerVolumeConfig.adapt(nVolumeConfig);
0229 wConditionScreen += "[n]";
0230 }
0231 if (cVolumeConfig.present) {
0232 containerVolumeConfig.adapt(cVolumeConfig);
0233 wConditionScreen += "[c]";
0234 }
0235 if (pVolumeConfig.present) {
0236 containerVolumeConfig.adapt(pVolumeConfig);
0237 wConditionScreen += "[p]";
0238 }
0239
0240 if (externalVolumeConfig.present) {
0241 containerVolumeConfig.adapt(externalVolumeConfig);
0242 }
0243
0244 if (nVolumeConfig.present && cVolumeConfig.present) {
0245 nVolumeConfig.midPointAttachZ(cVolumeConfig);
0246 }
0247 if (cVolumeConfig.present && pVolumeConfig.present) {
0248 cVolumeConfig.midPointAttachZ(pVolumeConfig);
0249 }
0250
0251
0252
0253 if (!existingVolumeConfig.present || !cVolumeConfig.present) {
0254 nVolumeConfig.adaptR(containerVolumeConfig);
0255 cVolumeConfig.adaptR(containerVolumeConfig);
0256 pVolumeConfig.adaptR(containerVolumeConfig);
0257 }
0258 }
0259
0260
0261 void wrapInsertAttach() {
0262
0263
0264 if (existingVolumeConfig.present) {
0265
0266 if (!cVolumeConfig.present) {
0267
0268 if (nVolumeConfig.present &&
0269 nVolumeConfig.zMax < existingVolumeConfig.zMin) {
0270 nVolumeConfig.attachZ(existingVolumeConfig);
0271
0272 wCondition = Attaching;
0273 wConditionScreen = "[n attached]";
0274 }
0275 if (pVolumeConfig.present &&
0276 pVolumeConfig.zMin > existingVolumeConfig.zMax) {
0277 pVolumeConfig.attachZ(existingVolumeConfig);
0278
0279 wCondition = Attaching;
0280 wConditionScreen = "[p attached]";
0281 }
0282
0283 if (containerVolumeConfig.rMin > existingVolumeConfig.rMin) {
0284 nVolumeConfig.rMin = existingVolumeConfig.rMin;
0285 pVolumeConfig.rMin = existingVolumeConfig.rMin;
0286 } else {
0287 fGapVolumeConfig.present = true;
0288
0289 fGapVolumeConfig.adaptZ(existingVolumeConfig);
0290 fGapVolumeConfig.rMin = containerVolumeConfig.rMin;
0291 fGapVolumeConfig.rMax = existingVolumeConfig.rMin;
0292 }
0293
0294 if (containerVolumeConfig.rMax < existingVolumeConfig.rMax) {
0295 nVolumeConfig.rMax = existingVolumeConfig.rMax;
0296 pVolumeConfig.rMax = existingVolumeConfig.rMax;
0297 } else {
0298 sGapVolumeConfig.present = true;
0299
0300 sGapVolumeConfig.adaptZ(existingVolumeConfig);
0301 sGapVolumeConfig.rMin = existingVolumeConfig.rMax;
0302 sGapVolumeConfig.rMax = containerVolumeConfig.rMax;
0303 }
0304 } else {
0305
0306 if (existingVolumeConfig.rMax < containerVolumeConfig.rMin) {
0307
0308
0309 nVolumeConfig.rMin = existingVolumeConfig.rMax;
0310 cVolumeConfig.rMin = existingVolumeConfig.rMax;
0311 pVolumeConfig.rMin = existingVolumeConfig.rMax;
0312
0313 nVolumeConfig.rMax = containerVolumeConfig.rMax;
0314 cVolumeConfig.rMax = containerVolumeConfig.rMax;
0315 pVolumeConfig.rMax = containerVolumeConfig.rMax;
0316
0317 wCondition = Wrapping;
0318 wConditionScreen = "[fully wrapped]";
0319 } else if (existingVolumeConfig.rMin > containerVolumeConfig.rMax) {
0320
0321
0322 nVolumeConfig.rMax = existingVolumeConfig.rMin;
0323 cVolumeConfig.rMax = existingVolumeConfig.rMin;
0324 pVolumeConfig.rMax = existingVolumeConfig.rMin;
0325
0326 nVolumeConfig.rMin = containerVolumeConfig.rMin;
0327 cVolumeConfig.rMin = containerVolumeConfig.rMin;
0328 pVolumeConfig.rMin = containerVolumeConfig.rMin;
0329
0330 wCondition = Inserting;
0331 wConditionScreen = "[fully inserted]";
0332 } else if (cVolumeConfig.wraps(existingVolumeConfig)) {
0333
0334
0335 nVolumeConfig.rMax = containerVolumeConfig.rMax;
0336 cVolumeConfig.rMax = containerVolumeConfig.rMax;
0337 pVolumeConfig.rMax = containerVolumeConfig.rMax;
0338
0339 nVolumeConfig.rMin = existingVolumeConfig.rMin;
0340 cVolumeConfig.rMin = existingVolumeConfig.rMax;
0341 pVolumeConfig.rMin = existingVolumeConfig.rMin;
0342
0343 wCondition = CentralWrapping;
0344 wConditionScreen = "[centrally wrapped]";
0345 } else if (existingVolumeConfig.wraps(cVolumeConfig)) {
0346
0347
0348 nVolumeConfig.rMax = containerVolumeConfig.rMax;
0349 cVolumeConfig.rMax = existingVolumeConfig.rMin;
0350 pVolumeConfig.rMax = containerVolumeConfig.rMax;
0351
0352 nVolumeConfig.rMin = containerVolumeConfig.rMin;
0353 cVolumeConfig.rMin = containerVolumeConfig.rMin;
0354 pVolumeConfig.rMin = containerVolumeConfig.rMin;
0355
0356 wCondition = CentralWrapping;
0357 wConditionScreen = "[centrally inserted]";
0358 } else if ((existingVolumeConfig.rMax > containerVolumeConfig.rMin &&
0359 existingVolumeConfig.rMin < containerVolumeConfig.rMin) ||
0360 (existingVolumeConfig.rMax > containerVolumeConfig.rMax &&
0361 existingVolumeConfig.rMin < containerVolumeConfig.rMax)) {
0362
0363
0364 throw std::invalid_argument(
0365 "Volumes are overlapping, this shouldn't be happening. Please "
0366 "check your geometry building.");
0367 }
0368
0369
0370
0371
0372
0373
0374 VolumeConfig referenceVolume =
0375 (wCondition == Wrapping || wCondition == Inserting)
0376 ? containerVolumeConfig
0377 : cVolumeConfig;
0378
0379 if (existingVolumeConfig.zMin > referenceVolume.zMin) {
0380 fGapVolumeConfig.present = true;
0381 fGapVolumeConfig.adaptR(existingVolumeConfig);
0382 fGapVolumeConfig.zMin = referenceVolume.zMin;
0383 fGapVolumeConfig.zMax = existingVolumeConfig.zMin;
0384 } else {
0385
0386 if (nVolumeConfig.present) {
0387 nVolumeConfig.zMin = existingVolumeConfig.zMin;
0388 } else if (cVolumeConfig.present) {
0389 cVolumeConfig.zMin = existingVolumeConfig.zMin;
0390 }
0391 }
0392
0393 if (existingVolumeConfig.zMax < referenceVolume.zMax) {
0394 sGapVolumeConfig.present = true;
0395 sGapVolumeConfig.adaptR(existingVolumeConfig);
0396 sGapVolumeConfig.zMin = existingVolumeConfig.zMax;
0397 sGapVolumeConfig.zMax = referenceVolume.zMax;
0398 } else {
0399
0400 if (pVolumeConfig.present) {
0401 pVolumeConfig.zMax = existingVolumeConfig.zMax;
0402 } else if (cVolumeConfig.present) {
0403 cVolumeConfig.zMax = existingVolumeConfig.zMax;
0404 }
0405 }
0406 }
0407 }
0408 return;
0409 }
0410
0411
0412 std::string toString() const {
0413
0414 std::stringstream sl;
0415 if (containerVolumeConfig.present) {
0416 sl << "New container built with configuration: "
0417 << containerVolumeConfig.toString() << '\n';
0418 }
0419
0420 if (nVolumeConfig.present) {
0421 sl << " - n: Negative Endcap, current configuration: "
0422 << nVolumeConfig.toString() << '\n';
0423 }
0424 if (cVolumeConfig.present) {
0425 sl << " - c: Barrel, current configuration: "
0426 << cVolumeConfig.toString() << '\n';
0427 }
0428 if (pVolumeConfig.present) {
0429 sl << " - p: Negative Endcap, current configuration: "
0430 << pVolumeConfig.toString() << '\n';
0431 }
0432 if (existingVolumeConfig.present) {
0433 sl << "Existing volume with configuration: "
0434 << existingVolumeConfig.toString() << '\n';
0435 if (fGapVolumeConfig.present) {
0436 sl << " - g1: First gap volume, configuration : "
0437 << fGapVolumeConfig.toString() << '\n';
0438 }
0439 if (sGapVolumeConfig.present) {
0440 sl << " - g2: Second gap volume, configuration : "
0441 << sGapVolumeConfig.toString() << '\n';
0442 }
0443 if (wCondition != Undefined) {
0444 sl << "WrappingCondition = " << wCondition << '\n';
0445 }
0446 }
0447 return sl.str();
0448 }
0449 };
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470 class CylinderVolumeBuilder : public ITrackingVolumeBuilder {
0471 public:
0472
0473
0474 struct Config {
0475
0476 std::shared_ptr<const ITrackingVolumeHelper> trackingVolumeHelper = nullptr;
0477
0478 std::string volumeName = "";
0479
0480 std::shared_ptr<const IVolumeMaterial> volumeMaterial = nullptr;
0481
0482 bool buildToRadiusZero = false;
0483
0484 bool checkRingLayout = false;
0485
0486 double ringTolerance = 0 * UnitConstants::mm;
0487
0488 std::shared_ptr<const ILayerBuilder> layerBuilder = nullptr;
0489
0490 std::shared_ptr<const IConfinedTrackingVolumeBuilder> ctVolumeBuilder =
0491 nullptr;
0492
0493 std::pair<double, double> layerEnvelopeR = {1. * UnitConstants::mm,
0494 1. * UnitConstants::mm};
0495
0496 double layerEnvelopeZ = 1. * UnitConstants::mm;
0497
0498
0499
0500
0501
0502 std::array<std::shared_ptr<const ISurfaceMaterial>, 6> boundaryMaterial{
0503 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
0504 };
0505
0506
0507
0508
0509
0510 explicit CylinderVolumeBuilder(const Config& cvbConfig,
0511 std::unique_ptr<const Logger> logger =
0512 getDefaultLogger("CylinderVolumeBuilder",
0513 Logging::INFO));
0514
0515
0516 ~CylinderVolumeBuilder() override;
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527 MutableTrackingVolumePtr trackingVolume(
0528 const GeometryContext& gctx, TrackingVolumePtr existingVolume = nullptr,
0529 std::shared_ptr<const VolumeBounds> externalBounds =
0530 nullptr) const override;
0531
0532
0533
0534
0535 void setConfiguration(const Config& cvbConfig);
0536
0537
0538
0539
0540 Config getConfiguration() const;
0541
0542
0543
0544
0545 void setLogger(std::unique_ptr<const Logger> newLogger);
0546
0547
0548
0549
0550
0551
0552
0553
0554 VolumeConfig analyzeContent(
0555 const GeometryContext& gctx, const LayerVector& lVector,
0556 const MutableTrackingVolumeVector& mtvVector) const;
0557
0558 private:
0559
0560 Config m_cfg;
0561
0562
0563
0564
0565 const Logger& logger() const { return *m_logger; }
0566
0567
0568 std::unique_ptr<const Logger> m_logger;
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582 bool checkLayerContainment(const GeometryContext& gctx,
0583 VolumeConfig& layerConfig,
0584 const VolumeConfig& insideConfig,
0585 const VolumeConfig& volumeConfig, int sign) const;
0586 };
0587
0588
0589 inline CylinderVolumeBuilder::Config CylinderVolumeBuilder::getConfiguration()
0590 const {
0591 return m_cfg;
0592 }
0593
0594 }