Warning, file /acts/Core/src/Geometry/SurfaceArrayCreator.cpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Geometry/SurfaceArrayCreator.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Surfaces/CylinderSurface.hpp"
0013 #include "Acts/Surfaces/DiscSurface.hpp"
0014 #include "Acts/Surfaces/PlanarBounds.hpp"
0015 #include "Acts/Surfaces/PlaneSurface.hpp"
0016 #include "Acts/Surfaces/RectangleBounds.hpp"
0017 #include "Acts/Surfaces/Surface.hpp"
0018 #include "Acts/Surfaces/SurfaceArray.hpp"
0019 #include "Acts/Utilities/AxisDefinitions.hpp"
0020 #include "Acts/Utilities/BinningType.hpp"
0021 #include "Acts/Utilities/Helpers.hpp"
0022
0023 #include <algorithm>
0024 #include <numbers>
0025 #include <stdexcept>
0026
0027 namespace Acts {
0028
0029 using VectorHelpers::perp;
0030 using VectorHelpers::phi;
0031
0032 SurfaceArray SurfaceArrayCreator::surfaceArrayOnCylinder(
0033 const GeometryContext& gctx,
0034 std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsPhi,
0035 std::size_t binsZ, std::optional<ProtoLayer> protoLayerOpt,
0036 const Transform3& transform, std::uint8_t maxNeighborDistance) const {
0037 using enum AxisDirection;
0038
0039 const std::vector<const Surface*> surfacesRaw = unpackSmartPointers(surfaces);
0040
0041 const ProtoLayer protoLayer =
0042 protoLayerOpt ? *protoLayerOpt : ProtoLayer(gctx, surfacesRaw);
0043
0044 ACTS_VERBOSE("Creating a SurfaceArray on a cylinder");
0045 ACTS_VERBOSE(" -- with " << surfaces.size() << " surfaces.");
0046 ACTS_VERBOSE(" -- with phi x z = " << binsPhi << " x " << binsZ << " = "
0047 << binsPhi * binsZ << " bins.");
0048
0049 Transform3 fullTransform = transform;
0050 const auto pAxisPhi =
0051 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Closed,
0052 AxisPhi, protoLayer, fullTransform, binsPhi);
0053 const auto pAxisZ =
0054 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Bound, AxisZ,
0055 protoLayer, fullTransform, binsZ);
0056
0057 const double R = protoLayer.medium(AxisR, true);
0058 const double halfZ = protoLayer.range(AxisZ, true) * 0.5;
0059 const double layerTolerance = protoLayer.range(AxisR) * 0.5;
0060
0061 auto surface = Surface::makeShared<CylinderSurface>(fullTransform, R, halfZ);
0062 ACTS_VERBOSE("- projection surface is: " << surface->toString(gctx));
0063
0064 return SurfaceArray(gctx, std::move(surfaces), std::move(surface),
0065 layerTolerance, {*pAxisPhi, *pAxisZ},
0066 maxNeighborDistance);
0067 }
0068
0069 SurfaceArray SurfaceArrayCreator::surfaceArrayOnCylinder(
0070 const GeometryContext& gctx,
0071 std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypePhi,
0072 BinningType bTypeZ, std::optional<ProtoLayer> protoLayerOpt,
0073 const Transform3& transform, std::uint8_t maxNeighborDistance) const {
0074 using enum AxisDirection;
0075
0076 const std::vector<const Surface*> surfacesRaw = unpackSmartPointers(surfaces);
0077
0078 const ProtoLayer protoLayer =
0079 protoLayerOpt ? *protoLayerOpt : ProtoLayer(gctx, surfacesRaw);
0080
0081 const double R = protoLayer.medium(AxisR, true);
0082 const double halfZ = protoLayer.range(AxisZ, true) * 0.5;
0083 const double layerTolerance = protoLayer.range(AxisR) * 0.5;
0084
0085 std::unique_ptr<const IAxis> pAxisPhi;
0086 std::unique_ptr<const IAxis> pAxisZ;
0087
0088 Transform3 fullTransform = transform;
0089
0090 if (bTypePhi == equidistant) {
0091 pAxisPhi =
0092 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Closed,
0093 AxisPhi, protoLayer, fullTransform, 0);
0094 } else {
0095 pAxisPhi = createVariableAxis(gctx, surfacesRaw, AxisBoundaryType::Closed,
0096 AxisPhi, protoLayer, fullTransform);
0097 }
0098
0099 if (bTypeZ == equidistant) {
0100 pAxisZ = createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Bound,
0101 AxisZ, protoLayer, fullTransform);
0102 } else {
0103 pAxisZ = createVariableAxis(gctx, surfacesRaw, AxisBoundaryType::Bound,
0104 AxisZ, protoLayer, fullTransform);
0105 }
0106
0107 auto surface = Surface::makeShared<CylinderSurface>(fullTransform, R, halfZ);
0108
0109 const std::size_t bins0 = pAxisPhi->getNBins();
0110 const std::size_t bins1 = pAxisZ->getNBins();
0111 ACTS_VERBOSE("Creating a SurfaceArray on a cylinder");
0112 ACTS_VERBOSE(" -- with " << surfaces.size() << " surfaces.");
0113 ACTS_VERBOSE(" -- with phi x z = " << bins0 << " x " << bins1 << " = "
0114 << bins0 * bins1 << " bins.");
0115
0116 return SurfaceArray(gctx, std::move(surfaces), std::move(surface),
0117 layerTolerance, {*pAxisPhi, *pAxisZ},
0118 maxNeighborDistance);
0119 }
0120
0121 SurfaceArray SurfaceArrayCreator::surfaceArrayOnDisc(
0122 const GeometryContext& gctx,
0123 std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsR,
0124 std::size_t binsPhi, std::optional<ProtoLayer> protoLayerOpt,
0125 const Transform3& transform, std::uint8_t maxNeighborDistance) const {
0126 using enum AxisDirection;
0127
0128 const std::vector<const Surface*> surfacesRaw = unpackSmartPointers(surfaces);
0129
0130 const ProtoLayer protoLayer =
0131 protoLayerOpt ? *protoLayerOpt : ProtoLayer(gctx, surfacesRaw);
0132
0133 ACTS_VERBOSE("Creating a SurfaceArray on a disc");
0134
0135 Transform3 fullTransform = transform;
0136 const auto pAxisR =
0137 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Bound, AxisR,
0138 protoLayer, fullTransform, binsR);
0139 const auto pAxisPhi =
0140 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Closed,
0141 AxisPhi, protoLayer, fullTransform, binsPhi);
0142
0143 const double Z = protoLayer.medium(AxisZ, true);
0144 const double Rmin = protoLayer.min(AxisR, true);
0145 const double Rmax = protoLayer.max(AxisR, true);
0146 const double layerThickness = protoLayer.range(AxisZ) * 0.5;
0147 ACTS_VERBOSE("- z-position of disc estimated as " << Z);
0148 ACTS_VERBOSE("- full transform is \n" << fullTransform.matrix());
0149
0150 if (fullTransform.translation().norm() < s_transformEquivalentTolerance) {
0151 ACTS_VERBOSE(
0152 "input transform does not have translation: putting projection surface "
0153 "at center of gravity in z");
0154 fullTransform.translate(Vector3::UnitZ() * Z);
0155 }
0156
0157 auto surface = Surface::makeShared<DiscSurface>(fullTransform, Rmin, Rmax);
0158 ACTS_VERBOSE("- projection surface is: " << surface->toString(gctx));
0159
0160 const std::size_t bins0 = pAxisR->getNBins();
0161 const std::size_t bins1 = pAxisPhi->getNBins();
0162 ACTS_VERBOSE(" -- with " << surfaces.size() << " surfaces.");
0163 ACTS_VERBOSE(" -- with r x phi = " << bins0 << " x " << bins1 << " = "
0164 << bins0 * bins1 << " bins.");
0165
0166 return SurfaceArray(gctx, std::move(surfaces), std::move(surface),
0167 layerThickness, {*pAxisR, *pAxisPhi},
0168 maxNeighborDistance);
0169 }
0170
0171 SurfaceArray SurfaceArrayCreator::surfaceArrayOnDisc(
0172 const GeometryContext& gctx,
0173 std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypeR,
0174 BinningType bTypePhi, std::optional<ProtoLayer> protoLayerOpt,
0175 const Transform3& transform, std::uint8_t maxNeighborDistance) const {
0176 using enum AxisDirection;
0177
0178 const std::vector<const Surface*> surfacesRaw = unpackSmartPointers(surfaces);
0179
0180 const ProtoLayer protoLayer =
0181 protoLayerOpt ? *protoLayerOpt : ProtoLayer(gctx, surfacesRaw);
0182
0183 ACTS_VERBOSE("Creating a SurfaceArray on a disc");
0184
0185 std::unique_ptr<const IAxis> pAxisPhi;
0186 std::unique_ptr<const IAxis> pAxisR;
0187
0188 Transform3 fullTransform = transform;
0189 Transform3 inverseTransform = transform.inverse();
0190
0191 if (bTypeR == equidistant) {
0192 pAxisR = createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Bound,
0193 AxisR, protoLayer, fullTransform);
0194 } else {
0195 pAxisR = createVariableAxis(gctx, surfacesRaw, AxisBoundaryType::Bound,
0196 AxisR, protoLayer, fullTransform);
0197 }
0198
0199
0200
0201 if (pAxisR->getNBins() > 1) {
0202
0203
0204 std::vector<std::vector<const Surface*>> phiModules(pAxisR->getNBins());
0205 for (const auto& srf : surfacesRaw) {
0206 const Vector3 bpos =
0207 inverseTransform * srf->referencePosition(gctx, AxisR);
0208 const std::size_t bin =
0209 pAxisR->getBin(perp(bpos)) - 1;
0210 phiModules.at(bin).push_back(srf);
0211 }
0212
0213 std::vector<std::size_t> nPhiModules;
0214 const auto& matcher = m_cfg.surfaceMatcher;
0215 const auto equal = [&gctx, &matcher](const Surface* a, const Surface* b) {
0216 return matcher(gctx, AxisPhi, a, b);
0217 };
0218
0219 std::transform(
0220 phiModules.begin(), phiModules.end(), std::back_inserter(nPhiModules),
0221 [&equal,
0222 this](const std::vector<const Surface*>& surfaces_) -> std::size_t {
0223 return this->findKeySurfaces(surfaces_, equal).size();
0224 });
0225
0226
0227
0228
0229
0230
0231
0232 const std::size_t nBinsPhi =
0233 *std::min_element(nPhiModules.begin(), nPhiModules.end());
0234 pAxisPhi =
0235 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Closed,
0236 AxisPhi, protoLayer, fullTransform, nBinsPhi);
0237
0238 } else {
0239
0240 if (bTypePhi == equidistant) {
0241 pAxisPhi =
0242 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Closed,
0243 AxisPhi, protoLayer, fullTransform, 0);
0244 } else {
0245 pAxisPhi = createVariableAxis(gctx, surfacesRaw, AxisBoundaryType::Closed,
0246 AxisPhi, protoLayer, fullTransform);
0247 }
0248 }
0249
0250 const double Z = protoLayer.medium(AxisZ, true);
0251 const double Rmin = protoLayer.min(AxisR, true);
0252 const double Rmax = protoLayer.max(AxisR, true);
0253 const double layerThickness = protoLayer.range(AxisZ) * 0.5;
0254 ACTS_VERBOSE("- z-position of disc estimated as " << Z);
0255
0256 if (fullTransform.translation().norm() < s_transformEquivalentTolerance) {
0257 ACTS_VERBOSE(
0258 "input transform does not have translation: putting projection surface "
0259 "at center of gravity in z");
0260 fullTransform.translate(Vector3::UnitZ() * Z);
0261 }
0262
0263 auto surface = Surface::makeShared<DiscSurface>(fullTransform, Rmin, Rmax);
0264
0265
0266 const std::size_t bins0 = pAxisR->getNBins();
0267 const std::size_t bins1 = pAxisPhi->getNBins();
0268 ACTS_VERBOSE(" -- with " << surfaces.size() << " surfaces.");
0269 ACTS_VERBOSE(" -- with r x phi = " << bins0 << " x " << bins1 << " = "
0270 << bins0 * bins1 << " bins.");
0271
0272 return SurfaceArray(gctx, std::move(surfaces), std::move(surface),
0273 layerThickness, {*pAxisR, *pAxisPhi},
0274 maxNeighborDistance);
0275 }
0276
0277
0278 SurfaceArray SurfaceArrayCreator::surfaceArrayOnPlane(
0279 const GeometryContext& gctx,
0280 std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t bins1,
0281 std::size_t bins2, AxisDirection aDir,
0282 std::optional<ProtoLayer> protoLayerOpt, const Transform3& transform,
0283 std::uint8_t maxNeighborDistance) const {
0284 using enum AxisDirection;
0285
0286 const std::vector<const Surface*> surfacesRaw = unpackSmartPointers(surfaces);
0287
0288 const ProtoLayer protoLayer =
0289 protoLayerOpt ? *protoLayerOpt : ProtoLayer(gctx, surfacesRaw);
0290
0291 ACTS_VERBOSE("Creating a SurfaceArray on a plance");
0292 ACTS_VERBOSE(" -- with " << surfaces.size() << " surfaces.");
0293 ACTS_VERBOSE(" -- with " << bins1 << " x " << bins2 << " = " << bins1 * bins2
0294 << " bins.");
0295 Transform3 fullTransform = transform;
0296
0297 const double layerTolerance = protoLayer.range(aDir) * 0.5;
0298
0299
0300 switch (aDir) {
0301 case AxisX: {
0302 const auto pAxis1 =
0303 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Bound,
0304 AxisY, protoLayer, fullTransform, bins1);
0305 const auto pAxis2 =
0306 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Bound,
0307 AxisZ, protoLayer, fullTransform, bins2);
0308 auto surface = Surface::makeShared<PlaneSurface>(
0309 fullTransform,
0310 std::make_shared<RectangleBounds>(
0311 Vector2(protoLayer.min(AxisY), protoLayer.min(AxisZ)),
0312 Vector2(protoLayer.max(AxisY), protoLayer.max(AxisZ))));
0313 return SurfaceArray(gctx, std::move(surfaces), std::move(surface),
0314 layerTolerance, {*pAxis1, *pAxis2},
0315 maxNeighborDistance);
0316 }
0317 case AxisY: {
0318 const auto pAxis1 =
0319 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Bound,
0320 AxisX, protoLayer, fullTransform, bins1);
0321 const auto pAxis2 =
0322 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Bound,
0323 AxisZ, protoLayer, fullTransform, bins2);
0324 auto surface = Surface::makeShared<PlaneSurface>(
0325 fullTransform,
0326 std::make_shared<RectangleBounds>(
0327 Vector2(protoLayer.min(AxisX), protoLayer.min(AxisY)),
0328 Vector2(protoLayer.max(AxisX), protoLayer.max(AxisY))));
0329 return SurfaceArray(gctx, std::move(surfaces), std::move(surface),
0330 layerTolerance, {*pAxis1, *pAxis2},
0331 maxNeighborDistance);
0332 }
0333 case AxisZ: {
0334 const auto pAxis1 =
0335 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Bound,
0336 AxisX, protoLayer, fullTransform, bins1);
0337 const auto pAxis2 =
0338 createEquidistantAxis(gctx, surfacesRaw, AxisBoundaryType::Bound,
0339 AxisY, protoLayer, fullTransform, bins2);
0340 auto surface = Surface::makeShared<PlaneSurface>(
0341 fullTransform,
0342 std::make_shared<RectangleBounds>(
0343 Vector2(protoLayer.min(AxisX), protoLayer.min(AxisY)),
0344 Vector2(protoLayer.max(AxisX), protoLayer.max(AxisY))));
0345 return SurfaceArray(gctx, std::move(surfaces), std::move(surface),
0346 layerTolerance, {*pAxis1, *pAxis2},
0347 maxNeighborDistance);
0348 }
0349 default:
0350 break;
0351 }
0352
0353 throw std::invalid_argument(
0354 "SurfaceArrayCreator::surfaceArrayOnPlane: Invalid binning direction");
0355 }
0356
0357 std::vector<const Surface*> SurfaceArrayCreator::findKeySurfaces(
0358 const std::vector<const Surface*>& surfaces,
0359 const std::function<bool(const Surface*, const Surface*)>& equal) const {
0360 std::vector<const Surface*> keys;
0361 for (const auto& srfA : surfaces) {
0362 bool exists = false;
0363 for (const auto& srfB : keys) {
0364 if (equal(srfA, srfB)) {
0365 exists = true;
0366 break;
0367 }
0368 }
0369 if (!exists) {
0370 keys.push_back(srfA);
0371 }
0372 }
0373
0374 return keys;
0375 }
0376
0377 std::size_t SurfaceArrayCreator::determineBinCount(
0378 const GeometryContext& gctx, const std::vector<const Surface*>& surfaces,
0379 AxisDirection aDir) const {
0380 const auto& matcher = m_cfg.surfaceMatcher;
0381 const auto equal = [&gctx, &aDir, &matcher](const Surface* a,
0382 const Surface* b) {
0383 return matcher(gctx, aDir, a, b);
0384 };
0385 const std::vector<const Surface*> keys = findKeySurfaces(surfaces, equal);
0386
0387 return keys.size();
0388 }
0389
0390 std::unique_ptr<const IAxis> SurfaceArrayCreator::createVariableAxis(
0391 const GeometryContext& gctx, const std::vector<const Surface*>& surfaces,
0392 AxisBoundaryType aBoundaryType, AxisDirection aDir,
0393 const ProtoLayer& protoLayer, Transform3& transform) const {
0394 using enum AxisDirection;
0395
0396 if (surfaces.empty()) {
0397 throw std::logic_error(
0398 "No surfaces handed over for creating arbitrary bin utility!");
0399 }
0400
0401
0402
0403
0404 const auto& matcher = m_cfg.surfaceMatcher;
0405
0406 const auto equal = [&gctx, &aDir, &matcher](const Surface* a,
0407 const Surface* b) {
0408 return matcher(gctx, aDir, a, b);
0409 };
0410 std::vector<const Surface*> keys = findKeySurfaces(surfaces, equal);
0411
0412 std::vector<double> binEdges;
0413 if (aDir == AxisPhi) {
0414 std::stable_sort(keys.begin(), keys.end(),
0415 [&gctx](const Surface* a, const Surface* b) {
0416 return (phi(a->referencePosition(gctx, AxisPhi)) <
0417 phi(b->referencePosition(gctx, AxisPhi)));
0418 });
0419
0420 const double maxPhi =
0421 0.5 * (phi(keys.at(0)->referencePosition(gctx, AxisPhi)) +
0422 phi(keys.at(1)->referencePosition(gctx, AxisPhi)));
0423
0424
0425 const double angle = -(std::numbers::pi + maxPhi);
0426 transform = transform * AngleAxis3(angle, Vector3::UnitZ());
0427
0428
0429
0430
0431 double previous = phi(keys.at(0)->referencePosition(gctx, AxisPhi));
0432
0433 for (std::size_t i = 1; i < keys.size(); i++) {
0434 const Surface* surface = keys.at(i);
0435
0436
0437
0438 const double edge =
0439 0.5 * (previous + phi(surface->referencePosition(gctx, AxisPhi))) +
0440 angle;
0441 binEdges.push_back(edge);
0442 previous = phi(surface->referencePosition(gctx, AxisPhi));
0443 }
0444
0445
0446 constexpr unsigned int segments = 72;
0447
0448
0449 const Surface* backSurface = keys.back();
0450 const PlanarBounds* backBounds =
0451 dynamic_cast<const PlanarBounds*>(&(backSurface->bounds()));
0452 if (backBounds == nullptr) {
0453 ACTS_ERROR(
0454 "Given SurfaceBounds are not planar - not implemented for "
0455 "other bounds yet! ");
0456 }
0457
0458 const std::vector<Vector3> backVertices =
0459 makeGlobalVertices(gctx, *backSurface, backBounds->vertices(segments));
0460 const double maxBValue = phi(*std::ranges::max_element(
0461 backVertices, {}, [](const Vector3& v) { return phi(v); }));
0462
0463 binEdges.push_back(maxBValue);
0464
0465 binEdges.push_back(std::numbers::pi);
0466
0467 } else if (aDir == AxisZ) {
0468 std::ranges::stable_sort(keys, {}, [&gctx](const Surface* s) {
0469 return s->referencePosition(gctx, AxisZ).z();
0470 });
0471
0472 binEdges.push_back(protoLayer.min(AxisZ));
0473 binEdges.push_back(protoLayer.max(AxisZ));
0474
0475
0476 double previous = keys.front()->referencePosition(gctx, AxisZ).z();
0477
0478 for (auto surface = keys.begin() + 1; surface != keys.end(); surface++) {
0479
0480
0481
0482 binEdges.push_back(
0483 0.5 * (previous + (*surface)->referencePosition(gctx, AxisZ).z()));
0484 previous = (*surface)->referencePosition(gctx, AxisZ).z();
0485 }
0486 } else {
0487 std::ranges::stable_sort(keys, {}, [&gctx](const Surface* s) {
0488 return perp(s->referencePosition(gctx, AxisR));
0489 });
0490
0491 binEdges.push_back(protoLayer.min(AxisR));
0492 binEdges.push_back(protoLayer.max(AxisR));
0493
0494
0495 double previous = perp(keys.front()->referencePosition(gctx, AxisR));
0496
0497
0498 for (auto surface = keys.begin() + 1; surface != keys.end(); surface++) {
0499
0500
0501
0502 binEdges.push_back(
0503 0.5 * (previous + perp((*surface)->referencePosition(gctx, AxisR))));
0504 previous = perp((*surface)->referencePosition(gctx, AxisR));
0505 }
0506 }
0507 std::ranges::sort(binEdges);
0508 ACTS_VERBOSE("Create variable binning Axis for binned SurfaceArray");
0509 ACTS_VERBOSE(" AxisDirection: " << aDir);
0510 ACTS_VERBOSE(" Number of bins: " << (binEdges.size() - 1));
0511 ACTS_VERBOSE(" (Min/Max) = (" << binEdges.front() << "/"
0512 << binEdges.back() << ")");
0513
0514 return IAxis::createVariable(aBoundaryType, binEdges, aDir);
0515 }
0516
0517 std::unique_ptr<const IAxis> SurfaceArrayCreator::createEquidistantAxis(
0518 const GeometryContext& gctx, const std::vector<const Surface*>& surfaces,
0519 AxisBoundaryType aBoundaryType, AxisDirection aDir,
0520 const ProtoLayer& protoLayer, Transform3& transform,
0521 std::size_t nBins) const {
0522 using enum AxisDirection;
0523
0524 if (surfaces.empty()) {
0525 throw std::logic_error(
0526 "No surfaces handed over for creating equidistant axis!");
0527 }
0528
0529
0530 double minimum = protoLayer.min(aDir, false);
0531 double maximum = protoLayer.max(aDir, false);
0532
0533 std::size_t binNumber = 0;
0534 if (nBins == 0) {
0535
0536 binNumber = determineBinCount(gctx, surfaces, aDir);
0537 } else {
0538
0539 binNumber = nBins;
0540 }
0541
0542
0543 auto matcher = m_cfg.surfaceMatcher;
0544
0545
0546 if (aDir == AxisPhi) {
0547 minimum = protoLayer.min(AxisPhi, true);
0548 maximum = protoLayer.max(AxisPhi, true);
0549
0550 if (m_cfg.doPhiBinningOptimization) {
0551 minimum = -std::numbers::pi;
0552 maximum = std::numbers::pi;
0553
0554
0555
0556
0557 const Surface* maxElem =
0558 *std::ranges::max_element(surfaces, {}, [&gctx](const Surface* s) {
0559 return phi(s->referencePosition(gctx, AxisR));
0560 });
0561
0562
0563
0564
0565 const double surfaceMax = phi(maxElem->referencePosition(gctx, AxisR));
0566 const double gridStep =
0567 2 * std::numbers::pi / static_cast<double>(binNumber);
0568 const double gridMax = std::numbers::pi - 0.5 * gridStep;
0569 const double angle = gridMax - surfaceMax;
0570
0571
0572 transform = transform * AngleAxis3(angle, Vector3::UnitZ());
0573 }
0574 }
0575
0576
0577 ACTS_VERBOSE("Create equidistant binning Axis for binned SurfaceArray");
0578 ACTS_VERBOSE(" AxisDirection: " << aDir);
0579 ACTS_VERBOSE(" Number of bins: " << binNumber);
0580 ACTS_VERBOSE(" (Min/Max) = (" << minimum << "/" << maximum << ")");
0581
0582 return IAxis::createEquidistant(aBoundaryType, minimum, maximum, binNumber,
0583 aDir);
0584 }
0585
0586 std::vector<Vector3> SurfaceArrayCreator::makeGlobalVertices(
0587 const GeometryContext& gctx, const Surface& surface,
0588 const std::vector<Vector2>& locVertices) const {
0589 std::vector<Vector3> globVertices;
0590 for (auto& vertex : locVertices) {
0591 Vector3 globVertex = surface.localToGlobal(gctx, vertex, Vector3());
0592 globVertices.push_back(globVertex);
0593 }
0594 return globVertices;
0595 }
0596
0597 }