File indexing completed on 2025-01-18 09:11:24
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/PlanarBounds.hpp"
0013 #include "Acts/Surfaces/Surface.hpp"
0014 #include "Acts/Surfaces/SurfaceArray.hpp"
0015 #include "Acts/Surfaces/SurfaceBounds.hpp"
0016 #include "Acts/Utilities/BinningType.hpp"
0017 #include "Acts/Utilities/Grid.hpp"
0018 #include "Acts/Utilities/Helpers.hpp"
0019 #include "Acts/Utilities/IAxis.hpp"
0020 #include "Acts/Utilities/detail/grid_helper.hpp"
0021
0022 #include <algorithm>
0023 #include <cmath>
0024 #include <numbers>
0025 #include <stdexcept>
0026
0027 using Acts::VectorHelpers::perp;
0028 using Acts::VectorHelpers::phi;
0029
0030 std::unique_ptr<Acts::SurfaceArray>
0031 Acts::SurfaceArrayCreator::surfaceArrayOnCylinder(
0032 const GeometryContext& gctx,
0033 std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsPhi,
0034 std::size_t binsZ, std::optional<ProtoLayer> protoLayerOpt,
0035 const Transform3& transform) const {
0036 std::vector<const Surface*> surfacesRaw = unpack_shared_vector(surfaces);
0037
0038 ProtoLayer protoLayer =
0039 protoLayerOpt ? *protoLayerOpt : ProtoLayer(gctx, surfacesRaw);
0040
0041 ACTS_VERBOSE("Creating a SurfaceArray on a cylinder");
0042 ACTS_VERBOSE(" -- with " << surfaces.size() << " surfaces.");
0043 ACTS_VERBOSE(" -- with phi x z = " << binsPhi << " x " << binsZ << " = "
0044 << binsPhi * binsZ << " bins.");
0045
0046 Transform3 ftransform = transform;
0047 ProtoAxis pAxisPhi =
0048 createEquidistantAxis(gctx, surfacesRaw, AxisDirection::AxisPhi,
0049 protoLayer, ftransform, binsPhi);
0050 ProtoAxis pAxisZ = createEquidistantAxis(
0051 gctx, surfacesRaw, AxisDirection::AxisZ, protoLayer, ftransform, binsZ);
0052
0053 double R = protoLayer.medium(AxisDirection::AxisR, true);
0054
0055 Transform3 itransform = ftransform.inverse();
0056
0057 auto globalToLocal = [ftransform](const Vector3& pos) {
0058 Vector3 loc = ftransform * pos;
0059 return Vector2(phi(loc), loc.z());
0060 };
0061 auto localToGlobal = [itransform, R](const Vector2& loc) {
0062 return itransform *
0063 Vector3(R * std::cos(loc[0]), R * std::sin(loc[0]), loc[1]);
0064 };
0065
0066 std::unique_ptr<SurfaceArray::ISurfaceGridLookup> sl =
0067 makeSurfaceGridLookup2D<AxisBoundaryType::Closed,
0068 AxisBoundaryType::Bound>(
0069 globalToLocal, localToGlobal, pAxisPhi, pAxisZ);
0070
0071 sl->fill(gctx, surfacesRaw);
0072 completeBinning(gctx, *sl, surfacesRaw);
0073
0074 return std::make_unique<SurfaceArray>(std::move(sl), std::move(surfaces),
0075 ftransform);
0076 }
0077
0078 std::unique_ptr<Acts::SurfaceArray>
0079 Acts::SurfaceArrayCreator::surfaceArrayOnCylinder(
0080 const GeometryContext& gctx,
0081 std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypePhi,
0082 BinningType bTypeZ, std::optional<ProtoLayer> protoLayerOpt,
0083 const Transform3& transform) const {
0084 std::vector<const Surface*> surfacesRaw = unpack_shared_vector(surfaces);
0085
0086 ProtoLayer protoLayer =
0087 protoLayerOpt ? *protoLayerOpt : ProtoLayer(gctx, surfacesRaw);
0088
0089 double R = protoLayer.medium(AxisDirection::AxisR, true);
0090
0091 ProtoAxis pAxisPhi;
0092 ProtoAxis pAxisZ;
0093
0094 Transform3 ftransform = transform;
0095
0096 if (bTypePhi == equidistant) {
0097 pAxisPhi = createEquidistantAxis(gctx, surfacesRaw, AxisDirection::AxisPhi,
0098 protoLayer, ftransform, 0);
0099 } else {
0100 pAxisPhi = createVariableAxis(gctx, surfacesRaw, AxisDirection::AxisPhi,
0101 protoLayer, ftransform);
0102 }
0103
0104 if (bTypeZ == equidistant) {
0105 pAxisZ = createEquidistantAxis(gctx, surfacesRaw, AxisDirection::AxisZ,
0106 protoLayer, ftransform);
0107 } else {
0108 pAxisZ = createVariableAxis(gctx, surfacesRaw, AxisDirection::AxisZ,
0109 protoLayer, ftransform);
0110 }
0111
0112 Transform3 itransform = ftransform.inverse();
0113 auto globalToLocal = [ftransform](const Vector3& pos) {
0114 Vector3 loc = ftransform * pos;
0115 return Vector2(phi(loc), loc.z());
0116 };
0117 auto localToGlobal = [itransform, R](const Vector2& loc) {
0118 return itransform *
0119 Vector3(R * std::cos(loc[0]), R * std::sin(loc[0]), loc[1]);
0120 };
0121
0122 std::unique_ptr<SurfaceArray::ISurfaceGridLookup> sl =
0123 makeSurfaceGridLookup2D<AxisBoundaryType::Closed,
0124 AxisBoundaryType::Bound>(
0125 globalToLocal, localToGlobal, pAxisPhi, pAxisZ);
0126
0127 sl->fill(gctx, surfacesRaw);
0128 completeBinning(gctx, *sl, surfacesRaw);
0129
0130
0131 auto axes = sl->getAxes();
0132 std::size_t bins0 = axes.at(0)->getNBins();
0133 std::size_t bins1 = axes.at(1)->getNBins();
0134
0135 ACTS_VERBOSE("Creating a SurfaceArray on a cylinder");
0136 ACTS_VERBOSE(" -- with " << surfaces.size() << " surfaces.");
0137 ACTS_VERBOSE(" -- with phi x z = " << bins0 << " x " << bins1 << " = "
0138 << bins0 * bins1 << " bins.");
0139
0140 return std::make_unique<SurfaceArray>(std::move(sl), std::move(surfaces),
0141 ftransform);
0142 }
0143
0144 std::unique_ptr<Acts::SurfaceArray>
0145 Acts::SurfaceArrayCreator::surfaceArrayOnDisc(
0146 const GeometryContext& gctx,
0147 std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t binsR,
0148 std::size_t binsPhi, std::optional<ProtoLayer> protoLayerOpt,
0149 const Transform3& transform) const {
0150 std::vector<const Surface*> surfacesRaw = unpack_shared_vector(surfaces);
0151
0152 ProtoLayer protoLayer =
0153 protoLayerOpt ? *protoLayerOpt : ProtoLayer(gctx, surfacesRaw);
0154
0155 ACTS_VERBOSE("Creating a SurfaceArray on a disc");
0156
0157 Transform3 ftransform = transform;
0158 ProtoAxis pAxisR = createEquidistantAxis(
0159 gctx, surfacesRaw, AxisDirection::AxisR, protoLayer, ftransform, binsR);
0160 ProtoAxis pAxisPhi =
0161 createEquidistantAxis(gctx, surfacesRaw, AxisDirection::AxisPhi,
0162 protoLayer, ftransform, binsPhi);
0163
0164 double Z = protoLayer.medium(AxisDirection::AxisZ, true);
0165 ACTS_VERBOSE("- z-position of disk estimated as " << Z);
0166
0167 Transform3 itransform = transform.inverse();
0168
0169 auto globalToLocal = [ftransform](const Vector3& pos) {
0170 Vector3 loc = ftransform * pos;
0171 return Vector2(perp(loc), phi(loc));
0172 };
0173 auto localToGlobal = [itransform, Z](const Vector2& loc) {
0174 return itransform *
0175 Vector3(loc[0] * std::cos(loc[1]), loc[0] * std::sin(loc[1]), Z);
0176 };
0177
0178 std::unique_ptr<SurfaceArray::ISurfaceGridLookup> sl =
0179 makeSurfaceGridLookup2D<AxisBoundaryType::Bound,
0180 AxisBoundaryType::Closed>(
0181 globalToLocal, localToGlobal, pAxisR, pAxisPhi);
0182
0183
0184 auto axes = sl->getAxes();
0185 std::size_t bins0 = axes.at(0)->getNBins();
0186 std::size_t bins1 = axes.at(1)->getNBins();
0187
0188 ACTS_VERBOSE(" -- with " << surfaces.size() << " surfaces.");
0189 ACTS_VERBOSE(" -- with r x phi = " << bins0 << " x " << bins1 << " = "
0190 << bins0 * bins1 << " bins.");
0191 sl->fill(gctx, surfacesRaw);
0192 completeBinning(gctx, *sl, surfacesRaw);
0193
0194 return std::make_unique<SurfaceArray>(std::move(sl), std::move(surfaces),
0195 ftransform);
0196 }
0197
0198 std::unique_ptr<Acts::SurfaceArray>
0199 Acts::SurfaceArrayCreator::surfaceArrayOnDisc(
0200 const GeometryContext& gctx,
0201 std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypeR,
0202 BinningType bTypePhi, std::optional<ProtoLayer> protoLayerOpt,
0203 const Transform3& transform) const {
0204 std::vector<const Surface*> surfacesRaw = unpack_shared_vector(surfaces);
0205
0206 ProtoLayer protoLayer =
0207 protoLayerOpt ? *protoLayerOpt : ProtoLayer(gctx, surfacesRaw);
0208
0209 ACTS_VERBOSE("Creating a SurfaceArray on a disc");
0210
0211 ProtoAxis pAxisPhi;
0212 ProtoAxis pAxisR;
0213
0214 Transform3 ftransform = transform;
0215
0216 if (bTypeR == equidistant) {
0217 pAxisR = createEquidistantAxis(gctx, surfacesRaw, AxisDirection::AxisR,
0218 protoLayer, ftransform);
0219 } else {
0220 pAxisR = createVariableAxis(gctx, surfacesRaw, AxisDirection::AxisR,
0221 protoLayer, ftransform);
0222 }
0223
0224
0225
0226 if (pAxisR.nBins > 1) {
0227
0228
0229 std::vector<std::vector<const Surface*>> phiModules(pAxisR.nBins);
0230 for (const auto& srf : surfacesRaw) {
0231 Vector3 bpos = srf->referencePosition(gctx, AxisDirection::AxisR);
0232 std::size_t bin = pAxisR.getBin(perp(bpos));
0233 phiModules.at(bin).push_back(srf);
0234 }
0235
0236 std::vector<std::size_t> nPhiModules;
0237 auto matcher = m_cfg.surfaceMatcher;
0238 auto equal = [&gctx, &matcher](const Surface* a, const Surface* b) {
0239 return matcher(gctx, AxisDirection::AxisPhi, a, b);
0240 };
0241
0242 std::transform(
0243 phiModules.begin(), phiModules.end(), std::back_inserter(nPhiModules),
0244 [&equal,
0245 this](const std::vector<const Surface*>& surfaces_) -> std::size_t {
0246 return this->findKeySurfaces(surfaces_, equal).size();
0247 });
0248
0249
0250
0251
0252
0253
0254
0255 std::size_t nBinsPhi =
0256 (*std::min_element(nPhiModules.begin(), nPhiModules.end()));
0257 pAxisPhi = createEquidistantAxis(gctx, surfacesRaw, AxisDirection::AxisPhi,
0258 protoLayer, ftransform, nBinsPhi);
0259
0260 } else {
0261
0262 if (bTypePhi == equidistant) {
0263 pAxisPhi = createEquidistantAxis(
0264 gctx, surfacesRaw, AxisDirection::AxisPhi, protoLayer, ftransform, 0);
0265 } else {
0266 pAxisPhi = createVariableAxis(gctx, surfacesRaw, AxisDirection::AxisPhi,
0267 protoLayer, ftransform);
0268 }
0269 }
0270
0271 double Z = protoLayer.medium(AxisDirection::AxisZ, true);
0272 ACTS_VERBOSE("- z-position of disk estimated as " << Z);
0273
0274 Transform3 itransform = ftransform.inverse();
0275
0276 auto globalToLocal = [ftransform](const Vector3& pos) {
0277 Vector3 loc = ftransform * pos;
0278 return Vector2(perp(loc), phi(loc));
0279 };
0280 auto localToGlobal = [itransform, Z](const Vector2& loc) {
0281 return itransform *
0282 Vector3(loc[0] * std::cos(loc[1]), loc[0] * std::sin(loc[1]), Z);
0283 };
0284
0285 std::unique_ptr<SurfaceArray::ISurfaceGridLookup> sl =
0286 makeSurfaceGridLookup2D<AxisBoundaryType::Bound,
0287 AxisBoundaryType::Closed>(
0288 globalToLocal, localToGlobal, pAxisR, pAxisPhi);
0289
0290
0291 auto axes = sl->getAxes();
0292 std::size_t bins0 = axes.at(0)->getNBins();
0293 std::size_t bins1 = axes.at(1)->getNBins();
0294
0295 ACTS_VERBOSE(" -- with " << surfaces.size() << " surfaces.");
0296 ACTS_VERBOSE(" -- with r x phi = " << bins0 << " x " << bins1 << " = "
0297 << bins0 * bins1 << " bins.");
0298
0299 sl->fill(gctx, surfacesRaw);
0300 completeBinning(gctx, *sl, surfacesRaw);
0301
0302 return std::make_unique<SurfaceArray>(std::move(sl), std::move(surfaces),
0303 ftransform);
0304 }
0305
0306
0307 std::unique_ptr<Acts::SurfaceArray>
0308 Acts::SurfaceArrayCreator::surfaceArrayOnPlane(
0309 const GeometryContext& gctx,
0310 std::vector<std::shared_ptr<const Surface>> surfaces, std::size_t bins1,
0311 std::size_t bins2, AxisDirection aDir,
0312 std::optional<ProtoLayer> protoLayerOpt,
0313 const Transform3& transform) const {
0314 std::vector<const Surface*> surfacesRaw = unpack_shared_vector(surfaces);
0315
0316 ProtoLayer protoLayer =
0317 protoLayerOpt ? *protoLayerOpt : ProtoLayer(gctx, surfacesRaw);
0318
0319 ACTS_VERBOSE("Creating a SurfaceArray on a plance");
0320 ACTS_VERBOSE(" -- with " << surfaces.size() << " surfaces.");
0321 ACTS_VERBOSE(" -- with " << bins1 << " x " << bins2 << " = " << bins1 * bins2
0322 << " bins.");
0323 Transform3 ftransform = transform;
0324 Transform3 itransform = transform.inverse();
0325
0326 auto globalToLocal = [ftransform](const Vector3& pos) {
0327 Vector3 loc = ftransform * pos;
0328 return Vector2(loc.x(), loc.y());
0329 };
0330 auto localToGlobal = [itransform](const Vector2& loc) {
0331 return itransform * Vector3(loc.x(), loc.y(), 0.);
0332 };
0333
0334 std::unique_ptr<SurfaceArray::ISurfaceGridLookup> sl;
0335
0336
0337 switch (aDir) {
0338 case AxisDirection::AxisX: {
0339 ProtoAxis pAxis1 =
0340 createEquidistantAxis(gctx, surfacesRaw, AxisDirection::AxisY,
0341 protoLayer, ftransform, bins1);
0342 ProtoAxis pAxis2 =
0343 createEquidistantAxis(gctx, surfacesRaw, AxisDirection::AxisZ,
0344 protoLayer, ftransform, bins2);
0345 sl = makeSurfaceGridLookup2D<AxisBoundaryType::Bound,
0346 AxisBoundaryType::Bound>(
0347 globalToLocal, localToGlobal, pAxis1, pAxis2);
0348 break;
0349 }
0350 case AxisDirection::AxisY: {
0351 ProtoAxis pAxis1 =
0352 createEquidistantAxis(gctx, surfacesRaw, AxisDirection::AxisX,
0353 protoLayer, ftransform, bins1);
0354 ProtoAxis pAxis2 =
0355 createEquidistantAxis(gctx, surfacesRaw, AxisDirection::AxisZ,
0356 protoLayer, ftransform, bins2);
0357 sl = makeSurfaceGridLookup2D<AxisBoundaryType::Bound,
0358 AxisBoundaryType::Bound>(
0359 globalToLocal, localToGlobal, pAxis1, pAxis2);
0360 break;
0361 }
0362 case AxisDirection::AxisZ: {
0363 ProtoAxis pAxis1 =
0364 createEquidistantAxis(gctx, surfacesRaw, AxisDirection::AxisX,
0365 protoLayer, ftransform, bins1);
0366 ProtoAxis pAxis2 =
0367 createEquidistantAxis(gctx, surfacesRaw, AxisDirection::AxisY,
0368 protoLayer, ftransform, bins2);
0369 sl = makeSurfaceGridLookup2D<AxisBoundaryType::Bound,
0370 AxisBoundaryType::Bound>(
0371 globalToLocal, localToGlobal, pAxis1, pAxis2);
0372 break;
0373 }
0374 default: {
0375 throw std::invalid_argument(
0376 "Acts::SurfaceArrayCreator::"
0377 "surfaceArrayOnPlane: Invalid binning "
0378 "direction");
0379 }
0380 }
0381
0382 sl->fill(gctx, surfacesRaw);
0383 completeBinning(gctx, *sl, surfacesRaw);
0384
0385 return std::make_unique<SurfaceArray>(std::move(sl), std::move(surfaces),
0386 ftransform);
0387
0388 }
0389
0390 std::vector<const Acts::Surface*> Acts::SurfaceArrayCreator::findKeySurfaces(
0391 const std::vector<const Surface*>& surfaces,
0392 const std::function<bool(const Surface*, const Surface*)>& equal) const {
0393 std::vector<const Surface*> keys;
0394 for (const auto& srfA : surfaces) {
0395 bool exists = false;
0396 for (const auto& srfB : keys) {
0397 if (equal(srfA, srfB)) {
0398 exists = true;
0399 break;
0400 }
0401 }
0402 if (!exists) {
0403 keys.push_back(srfA);
0404 }
0405 }
0406
0407 return keys;
0408 }
0409
0410 std::size_t Acts::SurfaceArrayCreator::determineBinCount(
0411 const GeometryContext& gctx, const std::vector<const Surface*>& surfaces,
0412 AxisDirection aDir) const {
0413 auto matcher = m_cfg.surfaceMatcher;
0414 auto equal = [&gctx, &aDir, &matcher](const Surface* a, const Surface* b) {
0415 return matcher(gctx, aDir, a, b);
0416 };
0417 std::vector<const Surface*> keys = findKeySurfaces(surfaces, equal);
0418
0419 return keys.size();
0420 }
0421
0422 Acts::SurfaceArrayCreator::ProtoAxis
0423 Acts::SurfaceArrayCreator::createVariableAxis(
0424 const GeometryContext& gctx, const std::vector<const Surface*>& surfaces,
0425 AxisDirection aDir, const ProtoLayer& protoLayer,
0426 Transform3& transform) const {
0427 if (surfaces.empty()) {
0428 throw std::logic_error(
0429 "No surfaces handed over for creating arbitrary bin utility!");
0430 }
0431
0432
0433
0434
0435 auto matcher = m_cfg.surfaceMatcher;
0436
0437 auto equal = [&gctx, &aDir, &matcher](const Surface* a, const Surface* b) {
0438 return matcher(gctx, aDir, a, b);
0439 };
0440 std::vector<const Acts::Surface*> keys = findKeySurfaces(surfaces, equal);
0441
0442 std::vector<AxisScalar> aDirs;
0443 if (aDir == Acts::AxisDirection::AxisPhi) {
0444 std::stable_sort(
0445 keys.begin(), keys.end(),
0446 [&gctx](const Acts::Surface* a, const Acts::Surface* b) {
0447 return (phi(a->referencePosition(gctx, AxisDirection::AxisPhi)) <
0448 phi(b->referencePosition(gctx, AxisDirection::AxisPhi)));
0449 });
0450
0451 AxisScalar maxPhi =
0452 0.5 *
0453 (phi(keys.at(0)->referencePosition(gctx, AxisDirection::AxisPhi)) +
0454 phi(keys.at(1)->referencePosition(gctx, AxisDirection::AxisPhi)));
0455
0456
0457 AxisScalar angle = -(std::numbers::pi + maxPhi);
0458 transform = (transform)*AngleAxis3(angle, Vector3::UnitZ());
0459
0460
0461
0462
0463 AxisScalar previous =
0464 phi(keys.at(0)->referencePosition(gctx, AxisDirection::AxisPhi));
0465
0466 for (std::size_t i = 1; i < keys.size(); i++) {
0467 const Surface* surface = keys.at(i);
0468
0469
0470
0471 AxisScalar edge = 0.5 * (previous + phi(surface->referencePosition(
0472 gctx, AxisDirection::AxisPhi))) +
0473 angle;
0474 aDirs.push_back(edge);
0475 previous = phi(surface->referencePosition(gctx, AxisDirection::AxisPhi));
0476 }
0477
0478
0479 unsigned int segments = 72;
0480
0481
0482 const Acts::Surface* backSurface = keys.back();
0483 const Acts::PlanarBounds* backBounds =
0484 dynamic_cast<const Acts::PlanarBounds*>(&(backSurface->bounds()));
0485 if (backBounds == nullptr) {
0486 ACTS_ERROR(
0487 "Given SurfaceBounds are not planar - not implemented for "
0488 "other bounds yet! ");
0489 }
0490
0491 std::vector<Acts::Vector3> backVertices =
0492 makeGlobalVertices(gctx, *backSurface, backBounds->vertices(segments));
0493 AxisScalar maxBValue = phi(
0494 *std::max_element(backVertices.begin(), backVertices.end(),
0495 [](const Acts::Vector3& a, const Acts::Vector3& b) {
0496 return phi(a) < phi(b);
0497 }));
0498
0499 aDirs.push_back(maxBValue);
0500
0501 aDirs.push_back(std::numbers::pi_v<AxisScalar>);
0502
0503 } else if (aDir == Acts::AxisDirection::AxisZ) {
0504 std::stable_sort(
0505 keys.begin(), keys.end(),
0506 [&gctx](const Acts::Surface* a, const Acts::Surface* b) {
0507 return (a->referencePosition(gctx, AxisDirection::AxisZ).z() <
0508 b->referencePosition(gctx, AxisDirection::AxisZ).z());
0509 });
0510
0511 aDirs.push_back(protoLayer.min(AxisDirection::AxisZ));
0512 aDirs.push_back(protoLayer.max(AxisDirection::AxisZ));
0513
0514
0515 AxisScalar previous =
0516 keys.front()->referencePosition(gctx, AxisDirection::AxisZ).z();
0517
0518 for (auto surface = keys.begin() + 1; surface != keys.end(); surface++) {
0519
0520
0521
0522 aDirs.push_back(
0523 0.5 *
0524 (previous +
0525 (*surface)->referencePosition(gctx, AxisDirection::AxisZ).z()));
0526 previous = (*surface)->referencePosition(gctx, AxisDirection::AxisZ).z();
0527 }
0528 } else {
0529 std::stable_sort(
0530 keys.begin(), keys.end(),
0531 [&gctx](const Acts::Surface* a, const Acts::Surface* b) {
0532 return (perp(a->referencePosition(gctx, AxisDirection::AxisR)) <
0533 perp(b->referencePosition(gctx, AxisDirection::AxisR)));
0534 });
0535
0536 aDirs.push_back(protoLayer.min(AxisDirection::AxisR));
0537 aDirs.push_back(protoLayer.max(AxisDirection::AxisR));
0538
0539
0540 AxisScalar previous =
0541 perp(keys.front()->referencePosition(gctx, AxisDirection::AxisR));
0542
0543
0544 for (auto surface = keys.begin() + 1; surface != keys.end(); surface++) {
0545
0546
0547
0548 aDirs.push_back(0.5 * (previous + perp((*surface)->referencePosition(
0549 gctx, AxisDirection::AxisR))));
0550 previous =
0551 perp((*surface)->referencePosition(gctx, AxisDirection::AxisR));
0552 }
0553 }
0554 std::ranges::sort(aDirs);
0555 ACTS_VERBOSE("Create variable binning Axis for binned SurfaceArray");
0556 ACTS_VERBOSE(" AxisDirection: " << aDir);
0557 ACTS_VERBOSE(" Number of bins: " << (aDirs.size() - 1));
0558 ACTS_VERBOSE(" (Min/Max) = (" << aDirs.front() << "/" << aDirs.back()
0559 << ")");
0560
0561 ProtoAxis pAxis;
0562 pAxis.bType = arbitrary;
0563 pAxis.axisDir = aDir;
0564 pAxis.binEdges = aDirs;
0565 pAxis.nBins = aDirs.size() - 1;
0566
0567 return pAxis;
0568 }
0569
0570 Acts::SurfaceArrayCreator::ProtoAxis
0571 Acts::SurfaceArrayCreator::createEquidistantAxis(
0572 const GeometryContext& gctx, const std::vector<const Surface*>& surfaces,
0573 AxisDirection aDir, const ProtoLayer& protoLayer, Transform3& transform,
0574 std::size_t nBins) const {
0575 if (surfaces.empty()) {
0576 throw std::logic_error(
0577 "No surfaces handed over for creating equidistant axis!");
0578 }
0579
0580
0581 double minimum = 0.;
0582 double maximum = 0.;
0583
0584
0585
0586
0587
0588
0589 std::vector<const Acts::Surface*> keys;
0590
0591 std::size_t binNumber = 0;
0592 if (nBins == 0) {
0593
0594 binNumber = determineBinCount(gctx, surfaces, aDir);
0595 } else {
0596
0597 binNumber = nBins;
0598 }
0599
0600
0601 auto matcher = m_cfg.surfaceMatcher;
0602
0603
0604 if (aDir == AxisDirection::AxisPhi) {
0605 if (m_cfg.doPhiBinningOptimization) {
0606
0607
0608
0609 const Acts::Surface* maxElem = *std::max_element(
0610 surfaces.begin(), surfaces.end(),
0611 [&gctx](const Acts::Surface* a, const Acts::Surface* b) {
0612 return phi(a->referencePosition(gctx, AxisDirection::AxisR)) <
0613 phi(b->referencePosition(gctx, AxisDirection::AxisR));
0614 });
0615
0616
0617 auto equal = [&gctx, &aDir, &matcher](const Surface* a,
0618 const Surface* b) {
0619 return matcher(gctx, aDir, a, b);
0620 };
0621 keys = findKeySurfaces(surfaces, equal);
0622
0623
0624 if (keys.size() > 1) {
0625
0626
0627 minimum = -std::numbers::pi;
0628 maximum = std::numbers::pi;
0629
0630
0631 double step = 2 * std::numbers::pi / binNumber;
0632
0633
0634
0635 double max =
0636 phi(maxElem->referencePosition(gctx, AxisDirection::AxisR));
0637 double angle = std::numbers::pi - (max + 0.5 * step);
0638
0639
0640 transform = (transform)*AngleAxis3(angle, Vector3::UnitZ());
0641
0642 } else {
0643 minimum = protoLayer.min(AxisDirection::AxisPhi, true);
0644 maximum = protoLayer.max(AxisDirection::AxisPhi, true);
0645
0646 }
0647 } else {
0648 minimum = -std::numbers::pi;
0649 maximum = std::numbers::pi;
0650 }
0651 } else {
0652 maximum = protoLayer.max(aDir, false);
0653 minimum = protoLayer.min(aDir, false);
0654 }
0655
0656
0657 ACTS_VERBOSE("Create equidistant binning Axis for binned SurfaceArray");
0658 ACTS_VERBOSE(" AxisDirection: " << aDir);
0659 ACTS_VERBOSE(" Number of bins: " << binNumber);
0660 ACTS_VERBOSE(" (Min/Max) = (" << minimum << "/" << maximum << ")");
0661
0662 ProtoAxis pAxis;
0663 pAxis.max = maximum;
0664 pAxis.min = minimum;
0665 pAxis.bType = equidistant;
0666 pAxis.axisDir = aDir;
0667 pAxis.nBins = binNumber;
0668
0669 return pAxis;
0670 }
0671
0672 std::vector<Acts::Vector3> Acts::SurfaceArrayCreator::makeGlobalVertices(
0673 const GeometryContext& gctx, const Acts::Surface& surface,
0674 const std::vector<Acts::Vector2>& locVertices) const {
0675 std::vector<Acts::Vector3> globVertices;
0676 for (auto& vertex : locVertices) {
0677 Acts::Vector3 globVertex =
0678 surface.localToGlobal(gctx, vertex, Acts::Vector3());
0679 globVertices.push_back(globVertex);
0680 }
0681 return globVertices;
0682 }