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