File indexing completed on 2025-01-18 09:11:20
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Geometry/CuboidVolumeBuilder.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Units.hpp"
0013 #include "Acts/Geometry/BoundarySurfaceFace.hpp"
0014 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0015 #include "Acts/Geometry/Extent.hpp"
0016 #include "Acts/Geometry/LayerArrayCreator.hpp"
0017 #include "Acts/Geometry/LayerCreator.hpp"
0018 #include "Acts/Geometry/ProtoLayer.hpp"
0019 #include "Acts/Geometry/SurfaceArrayCreator.hpp"
0020 #include "Acts/Geometry/TrackingGeometry.hpp"
0021 #include "Acts/Geometry/TrackingVolume.hpp"
0022 #include "Acts/Geometry/Volume.hpp"
0023 #include "Acts/Surfaces/PlaneSurface.hpp"
0024 #include "Acts/Surfaces/RectangleBounds.hpp"
0025 #include "Acts/Surfaces/Surface.hpp"
0026 #include "Acts/Utilities/BinUtility.hpp"
0027 #include "Acts/Utilities/BinnedArrayXD.hpp"
0028 #include "Acts/Utilities/BinningData.hpp"
0029 #include "Acts/Utilities/Logger.hpp"
0030
0031 #include <algorithm>
0032 #include <limits>
0033 #include <stdexcept>
0034 #include <type_traits>
0035
0036 std::shared_ptr<const Acts::Surface> Acts::CuboidVolumeBuilder::buildSurface(
0037 const GeometryContext& ,
0038 const CuboidVolumeBuilder::SurfaceConfig& cfg) const {
0039 std::shared_ptr<PlaneSurface> surface;
0040
0041
0042 Transform3 trafo(Transform3::Identity() * cfg.rotation);
0043 trafo.translation() = cfg.position;
0044
0045
0046 if (cfg.detElementConstructor) {
0047 surface = Surface::makeShared<PlaneSurface>(
0048 cfg.rBounds,
0049 *(cfg.detElementConstructor(trafo, cfg.rBounds, cfg.thickness)));
0050 } else {
0051 surface = Surface::makeShared<PlaneSurface>(trafo, cfg.rBounds);
0052 }
0053 surface->assignSurfaceMaterial(cfg.surMat);
0054 return surface;
0055 }
0056
0057 std::shared_ptr<const Acts::Layer> Acts::CuboidVolumeBuilder::buildLayer(
0058 const GeometryContext& gctx,
0059 Acts::CuboidVolumeBuilder::LayerConfig& cfg) const {
0060 if (cfg.surfaces.empty() && cfg.surfaceCfg.empty()) {
0061 throw std::runtime_error{
0062 "Neither surfaces nor config to build surfaces was provided. Cannot "
0063 "proceed"};
0064 }
0065
0066
0067 if (cfg.surfaces.empty()) {
0068 for (const auto& sCfg : cfg.surfaceCfg) {
0069 cfg.surfaces.push_back(buildSurface(gctx, sCfg));
0070 }
0071 }
0072
0073 Vector3 centroid{0., 0., 0.};
0074
0075 for (const auto& surface : cfg.surfaces) {
0076 centroid += surface->transform(gctx).translation();
0077 }
0078
0079 centroid /= cfg.surfaces.size();
0080
0081
0082
0083
0084 Transform3 trafo = Transform3::Identity();
0085 trafo.translation() = centroid;
0086 if (cfg.rotation) {
0087 trafo.linear() = *cfg.rotation;
0088 } else {
0089 trafo.linear() = cfg.surfaces.front()->transform(gctx).rotation();
0090 }
0091
0092 LayerCreator::Config lCfg;
0093 lCfg.surfaceArrayCreator = std::make_shared<const SurfaceArrayCreator>();
0094 LayerCreator layerCreator(lCfg);
0095 ProtoLayer pl{gctx, cfg.surfaces};
0096 pl.envelope[AxisDirection::AxisX] = cfg.envelopeX;
0097 pl.envelope[AxisDirection::AxisY] = cfg.envelopeY;
0098 pl.envelope[AxisDirection::AxisZ] = cfg.envelopeZ;
0099 return layerCreator.planeLayer(gctx, cfg.surfaces, cfg.binsY, cfg.binsZ,
0100 cfg.binningDimension, pl, trafo);
0101 }
0102
0103 std::pair<double, double> Acts::CuboidVolumeBuilder::binningRange(
0104 const GeometryContext& gctx,
0105 const Acts::CuboidVolumeBuilder::VolumeConfig& cfg) const {
0106 using namespace UnitLiterals;
0107
0108 std::pair<double, double> minMax = std::make_pair(
0109 std::numeric_limits<double>::max(), -std::numeric_limits<double>::max());
0110
0111
0112
0113
0114
0115
0116 Vector3 minVolumeBoundaries = cfg.position - 0.5 * cfg.length;
0117 Vector3 maxVolumeBoundaries = cfg.position + 0.5 * cfg.length;
0118
0119
0120
0121 for (const auto& layercfg : cfg.layerCfg) {
0122
0123 ProtoLayer pl{gctx, layercfg.surfaces};
0124 pl.envelope[cfg.binningDimension] = layercfg.envelopeX;
0125
0126 double surfacePosMin = pl.min(cfg.binningDimension);
0127 double surfacePosMax = pl.max(cfg.binningDimension);
0128
0129
0130 if (surfacePosMin < minMax.first) {
0131 minMax.first = surfacePosMin;
0132 }
0133 if (surfacePosMax > minMax.second) {
0134 minMax.second = surfacePosMax;
0135 }
0136 }
0137
0138
0139 minMax.first = std::min(
0140 minMax.first, minVolumeBoundaries(toUnderlying(cfg.binningDimension)));
0141 minMax.second = std::max(
0142 minMax.second, maxVolumeBoundaries(toUnderlying(cfg.binningDimension)));
0143
0144 return minMax;
0145 }
0146
0147 std::shared_ptr<Acts::TrackingVolume> Acts::CuboidVolumeBuilder::buildVolume(
0148 const GeometryContext& gctx,
0149 Acts::CuboidVolumeBuilder::VolumeConfig& cfg) const {
0150
0151 Transform3 trafo(Transform3::Identity());
0152 trafo.translation() = cfg.position;
0153
0154 auto bounds = std::make_shared<CuboidVolumeBounds>(
0155 cfg.length.x() * 0.5, cfg.length.y() * 0.5, cfg.length.z() * 0.5);
0156
0157
0158 LayerVector layVec;
0159 if (cfg.layers.empty()) {
0160 cfg.layers.reserve(cfg.layerCfg.size());
0161
0162 for (auto& layerCfg : cfg.layerCfg) {
0163 cfg.layers.push_back(buildLayer(gctx, layerCfg));
0164 layVec.push_back(cfg.layers.back());
0165 }
0166 } else {
0167 for (auto& lay : cfg.layers) {
0168 layVec.push_back(lay);
0169 }
0170 }
0171
0172
0173 std::pair<double, double> minMax = binningRange(gctx, cfg);
0174 LayerArrayCreator::Config lacCnf;
0175 LayerArrayCreator layArrCreator(
0176 lacCnf, getDefaultLogger("LayerArrayCreator", Logging::INFO));
0177 std::unique_ptr<const LayerArray> layArr(
0178 layArrCreator.layerArray(gctx, layVec, minMax.first, minMax.second,
0179 BinningType::arbitrary, cfg.binningDimension));
0180
0181
0182 if (cfg.trackingVolumes.empty()) {
0183 for (VolumeConfig vc : cfg.volumeCfg) {
0184 cfg.trackingVolumes.push_back(buildVolume(gctx, vc));
0185 }
0186 }
0187
0188 std::shared_ptr<TrackingVolume> trackVolume;
0189 if (layVec.empty()) {
0190
0191 trackVolume = std::make_shared<TrackingVolume>(
0192 trafo, bounds, cfg.volumeMaterial, nullptr, nullptr,
0193 cfg.trackingVolumes, cfg.name);
0194 } else {
0195
0196 trackVolume = std::make_shared<TrackingVolume>(
0197 trafo, bounds, cfg.volumeMaterial, std::move(layArr), nullptr,
0198 cfg.trackingVolumes, cfg.name);
0199 }
0200 return trackVolume;
0201 }
0202
0203 Acts::MutableTrackingVolumePtr Acts::CuboidVolumeBuilder::trackingVolume(
0204 const GeometryContext& gctx, Acts::TrackingVolumePtr ,
0205 std::shared_ptr<const VolumeBounds> ) const {
0206
0207 std::vector<std::shared_ptr<TrackingVolume>> volumes;
0208 volumes.reserve(m_cfg.volumeCfg.size());
0209 for (VolumeConfig volCfg : m_cfg.volumeCfg) {
0210 volumes.push_back(buildVolume(gctx, volCfg));
0211 }
0212
0213
0214
0215 std::ranges::sort(volumes, {}, [](const auto& v) { return v->center().x(); });
0216
0217
0218 for (unsigned int i = 0; i < volumes.size() - 1; i++) {
0219 volumes[i + 1]->glueTrackingVolume(
0220 gctx, BoundarySurfaceFace::negativeFaceYZ, volumes[i].get(),
0221 BoundarySurfaceFace::positiveFaceYZ);
0222 volumes[i]->glueTrackingVolume(gctx, BoundarySurfaceFace::positiveFaceYZ,
0223 volumes[i + 1].get(),
0224 BoundarySurfaceFace::negativeFaceYZ);
0225 }
0226
0227
0228 Transform3 trafo(Transform3::Identity());
0229 trafo.translation() = m_cfg.position;
0230
0231
0232 auto volumeBounds = std::make_shared<CuboidVolumeBounds>(
0233 m_cfg.length.x() * 0.5, m_cfg.length.y() * 0.5, m_cfg.length.z() * 0.5);
0234
0235
0236 std::vector<std::pair<TrackingVolumePtr, Vector3>> tapVec;
0237 tapVec.reserve(m_cfg.volumeCfg.size());
0238 for (auto& tVol : volumes) {
0239 tapVec.push_back(std::make_pair(tVol, tVol->center()));
0240 }
0241
0242
0243 std::vector<float> binBoundaries;
0244 binBoundaries.push_back(volumes[0]->center().x() -
0245 m_cfg.volumeCfg[0].length.x() * 0.5);
0246 for (std::size_t i = 0; i < volumes.size(); i++) {
0247 binBoundaries.push_back(volumes[i]->center().x() +
0248 m_cfg.volumeCfg[i].length.x() * 0.5);
0249 }
0250
0251
0252 BinningData binData(BinningOption::open, AxisDirection::AxisX, binBoundaries);
0253 auto bu = std::make_unique<const BinUtility>(binData);
0254
0255
0256 std::shared_ptr<const TrackingVolumeArray> trVolArr(
0257 new BinnedArrayXD<TrackingVolumePtr>(tapVec, std::move(bu)));
0258
0259
0260 MutableTrackingVolumePtr mtvp(std::make_shared<TrackingVolume>(
0261 trafo, volumeBounds, nullptr, nullptr, trVolArr,
0262 MutableTrackingVolumeVector{}, "World"));
0263
0264 return mtvp;
0265 }