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