File indexing completed on 2025-07-01 07:53:40
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Plugins/GeoModel/GeoModelDetectorObjectFactory.hpp"
0010
0011 #include "Acts/Detector/GeometryIdGenerator.hpp"
0012 #include "Acts/Detector/PortalGenerators.hpp"
0013 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0014 #include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp"
0015 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0016 #include "Acts/Geometry/GeometryIdentifier.hpp"
0017 #include "Acts/Geometry/TrapezoidVolumeBounds.hpp"
0018 #include "Acts/Navigation/InternalNavigation.hpp"
0019 #include "Acts/Plugins/GeoModel/GeoModelConverters.hpp"
0020 #include "Acts/Plugins/GeoModel/IGeoShapeConverter.hpp"
0021
0022 #include <algorithm>
0023 #include <iostream>
0024 #include <typeinfo>
0025
0026 #include <GeoModelHelpers/GeoShapeUtils.h>
0027 #include <GeoModelKernel/GeoBox.h>
0028 #include <GeoModelKernel/GeoPcon.h>
0029 #include <GeoModelKernel/GeoShapeShift.h>
0030 #include <GeoModelKernel/GeoShapeSubtraction.h>
0031 #include <GeoModelKernel/GeoShapeUnion.h>
0032 #include <GeoModelKernel/GeoSimplePolygonBrep.h>
0033 #include <GeoModelKernel/GeoTrd.h>
0034 #include <GeoModelKernel/GeoTube.h>
0035 #include <GeoModelKernel/GeoTubs.h>
0036
0037 namespace Acts {
0038
0039 GeoModelDetectorObjectFactory::GeoModelDetectorObjectFactory(
0040 const Config &cfg, std::unique_ptr<const Logger> mlogger)
0041 : m_logger(std::move(mlogger)), m_cfg(cfg) {}
0042
0043 void GeoModelDetectorObjectFactory::construct(Cache &cache,
0044 const GeometryContext &gctx,
0045 const GeoModelTree &geoModelTree,
0046 const Options &options) {
0047 if (geoModelTree.geoReader == nullptr) {
0048 throw std::invalid_argument("GeoModelTree has no GeoModelReader");
0049 }
0050 for (const auto &q : options.queries) {
0051 ACTS_VERBOSE("Constructing detector elements for query " << q);
0052
0053 auto qFPV = geoModelTree.geoReader
0054 ->getPublishedNodes<std::string, GeoFullPhysVol *>(q);
0055
0056
0057 for (const auto &[name, fpv] : qFPV) {
0058 FPVConstLink physVol{fpv};
0059 ACTS_INFO("Convert volume " << name);
0060 convertFpv(name, physVol, cache, gctx);
0061 }
0062 }
0063 }
0064
0065 void GeoModelDetectorObjectFactory::convertSensitive(
0066 const PVConstLink &geoPV, const Transform3 &transform,
0067 SurfaceBoundFactory &boundFactory,
0068 std::vector<GeoModelSensitiveSurface> &sensitives) {
0069 const GeoLogVol *logVol = geoPV->getLogVol();
0070 const GeoShape *shape = logVol->getShape();
0071 int shapeId = shape->typeID();
0072 const std::string &name = logVol->getName();
0073 std::shared_ptr<const IGeoShapeConverter> converter =
0074 geoShapesConverters(shapeId);
0075 if (converter == nullptr) {
0076 throw std::runtime_error("The converter for " + printGeoShape(shape) +
0077 " is a nullptr");
0078 }
0079
0080 auto converted =
0081 converter->toSensitiveSurface(geoPV, transform, boundFactory);
0082 if (converted.ok()) {
0083 const auto &[el, sf] = converted.value();
0084
0085 if (!el || !sf) {
0086 throw std::runtime_error(
0087 "The Detector Element or the Surface is a nullptr");
0088 }
0089 sensitives.push_back(converted.value());
0090 ACTS_VERBOSE("(successfully converted: "
0091 << name << " / " << printGeoShape(shape) << " / "
0092 << logVol->getMaterial()->getName() << ")");
0093 return;
0094 }
0095 ACTS_ERROR(name << " / " << printGeoShape(shape)
0096 << " could not be converted by any converter");
0097 }
0098
0099 std::vector<GeoChildNodeWithTrf>
0100 GeoModelDetectorObjectFactory::findAllSubVolumes(const PVConstLink &vol) const {
0101
0102 std::vector<GeoChildNodeWithTrf> subvolumes = getChildrenWithRef(vol, false);
0103 std::vector<GeoChildNodeWithTrf> sensitives;
0104 sensitives.reserve(subvolumes.size());
0105 for (auto &subvolume : subvolumes) {
0106
0107 if (matches(subvolume.nodeName, subvolume.volume)) {
0108 sensitives.push_back(subvolume);
0109 }
0110
0111 if (subvolume.volume->getNChildVols() == 0) {
0112 continue;
0113 }
0114
0115
0116 std::vector<GeoChildNodeWithTrf> senssubsubvolumes =
0117 findAllSubVolumes(subvolume.volume);
0118
0119
0120
0121
0122 std::transform(std::make_move_iterator(senssubsubvolumes.begin()),
0123 std::make_move_iterator(senssubsubvolumes.end()),
0124 std::back_inserter(sensitives),
0125 [&subvolume](GeoChildNodeWithTrf &&volume) {
0126 volume.transform = subvolume.transform * volume.transform;
0127 return volume;
0128 });
0129 }
0130 return sensitives;
0131 }
0132
0133 bool GeoModelDetectorObjectFactory::convertBox(const std::string &name) const {
0134 auto convB = std::ranges::any_of(m_cfg.convertBox, [&](const auto &n) {
0135 return name.find(n) != std::string::npos;
0136 });
0137 return convB;
0138 }
0139
0140 void GeoModelDetectorObjectFactory::convertFpv(const std::string &name,
0141 const FPVConstLink &fpv,
0142 Cache &cache,
0143 const GeometryContext &gctx) {
0144 const std::size_t prevSize = cache.sensitiveSurfaces.size();
0145 {
0146
0147 std::vector<GeoChildNodeWithTrf> subVolToTrf = findAllSubVolumes(fpv);
0148
0149 std::vector<GeoModelSensitiveSurface> sensitives;
0150 sensitives.reserve(subVolToTrf.size());
0151
0152 for (const auto &trfMe : subVolToTrf) {
0153
0154 const Transform3 transform =
0155 fpv->getAbsoluteTransform() * trfMe.transform;
0156 convertSensitive(trfMe.volume, transform, *cache.surfBoundFactory,
0157 sensitives);
0158 }
0159
0160 if (sensitives.empty() && matches(name, fpv)) {
0161 convertSensitive(fpv, fpv->getAbsoluteTransform(),
0162 *cache.surfBoundFactory, cache.sensitiveSurfaces);
0163 }
0164 cache.sensitiveSurfaces.insert(cache.sensitiveSurfaces.end(),
0165 std::make_move_iterator(sensitives.begin()),
0166 std::make_move_iterator(sensitives.end()));
0167
0168 for (auto i = prevSize; i < cache.sensitiveSurfaces.size(); ++i) {
0169 const auto &detEl = std::get<0>(cache.sensitiveSurfaces[i]);
0170 detEl->setDatabaseEntryName(name);
0171 ACTS_VERBOSE("Set database name of the DetectorElement to "
0172 << detEl->databaseEntryName());
0173 }
0174 }
0175
0176 if (convertBox(name)) {
0177 auto volume = GeoModel::convertVolume(fpv->getAbsoluteTransform(),
0178 fpv->getLogVol()->getShape(),
0179 *cache.volumeBoundFactory);
0180
0181 std::vector<std::shared_ptr<Surface>> surfacesToPut{};
0182 std::transform(cache.sensitiveSurfaces.begin() + prevSize,
0183 cache.sensitiveSurfaces.end(),
0184 std::back_inserter(surfacesToPut),
0185 [](const GeoModelSensitiveSurface &sensitive) {
0186 return std::get<1>(sensitive);
0187 });
0188
0189 auto volumeGen2 =
0190 GeoModel::convertDetectorVolume(gctx, *volume, name, surfacesToPut);
0191 cache.volumeBoxFPVs.emplace_back(std::make_tuple(volume, volumeGen2, fpv));
0192 }
0193 }
0194
0195 bool GeoModelDetectorObjectFactory::matches(const std::string &name,
0196 const PVConstLink &physvol) const {
0197 if (m_cfg.nameList.empty() && m_cfg.materialList.empty()) {
0198 return true;
0199 }
0200
0201 auto matchName = std::ranges::any_of(m_cfg.nameList, [&](const auto &n) {
0202 return name.find(n) != std::string::npos;
0203 });
0204
0205 std::string matStr = physvol->getLogVol()->getMaterial()->getName();
0206
0207 auto matchMaterial = std::ranges::any_of(
0208 m_cfg.materialList,
0209 [&](const auto &m) { return matStr.find(m) != std::string::npos; });
0210
0211 bool match = matchMaterial && matchName;
0212
0213
0214 if (m_cfg.nameList.empty()) {
0215 return matchMaterial;
0216 }
0217
0218
0219 if (m_cfg.materialList.empty() ||
0220 dynamic_pointer_cast<const GeoVFullPhysVol>(physvol)) {
0221 return matchName;
0222 }
0223 return match;
0224 }
0225 }