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