File indexing completed on 2026-05-29 07:33:12
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Geometry/TrackingGeometry.hpp"
0010
0011 #include "Acts/Definitions/Tolerance.hpp"
0012 #include "Acts/Geometry/GeometryContext.hpp"
0013 #include "Acts/Geometry/GeometryIdentifier.hpp"
0014 #include "Acts/Geometry/GeometryObject.hpp"
0015 #include "Acts/Geometry/TrackingGeometryVisitor.hpp"
0016 #include "Acts/Geometry/TrackingVolume.hpp"
0017 #include "Acts/Material/ProtoVolumeMaterial.hpp"
0018 #include "Acts/Surfaces/Surface.hpp"
0019
0020 #include <cstddef>
0021
0022 namespace Acts {
0023
0024 class Gen1GeometryClosureVisitor : public TrackingGeometryMutableVisitor {
0025 public:
0026 Gen1GeometryClosureVisitor(const Logger& logger,
0027 const IMaterialDecorator* materialDecorator,
0028 const GeometryIdentifierHook& hook)
0029 : m_logger(&logger),
0030 m_materialDecorator(materialDecorator),
0031 m_hook(&hook) {
0032 ACTS_VERBOSE("Creating Gen1GeometryClosureVisitor");
0033 }
0034
0035 const Logger& logger() const { return *m_logger; }
0036
0037 void visitVolume(TrackingVolume& volume) override {
0038 ACTS_DEBUG("Volume: " << volume.volumeName());
0039
0040
0041 m_volumeID = GeometryIdentifier().withVolume(m_volumeID.volume() + 1);
0042
0043 m_iboundary = 0;
0044
0045 m_ilayer = 0;
0046
0047
0048 ACTS_VERBOSE("~> volumeID: " << m_volumeID);
0049 volume.assignGeometryId(m_volumeID);
0050
0051
0052 if (m_materialDecorator != nullptr) {
0053 ACTS_VERBOSE("Decorating volume " << volume.volumeName()
0054 << " with material");
0055 m_materialDecorator->decorate(volume);
0056 }
0057 if (!volume.hasMaterial() && volume.motherVolume() != nullptr &&
0058 volume.motherVolume()->hasMaterial()) {
0059 auto protoMaterial = dynamic_cast<const ProtoVolumeMaterial*>(
0060 volume.motherVolume()->volumeMaterial());
0061 if (protoMaterial == nullptr) {
0062 volume.assignVolumeMaterial(volume.motherVolume()->volumeMaterialPtr());
0063 }
0064 }
0065 }
0066
0067 void visitBoundarySurface(
0068 BoundarySurfaceT<TrackingVolume>& boundary) override {
0069 ACTS_DEBUG("BoundarySurface: " << boundary.surfaceRepresentation().name());
0070
0071 auto& bSurface = boundary.surfaceRepresentation();
0072
0073 m_iboundary += 1;
0074 auto boundaryID = GeometryIdentifier(m_volumeID).withBoundary(m_iboundary);
0075 ACTS_VERBOSE("~> boundaryID: " << boundaryID);
0076
0077 auto& mutableBSurface = *(const_cast<RegularSurface*>(&bSurface));
0078
0079
0080 ACTS_VERBOSE("~> assigning boundaryID: " << boundaryID);
0081 mutableBSurface.assignGeometryId(boundaryID);
0082
0083
0084 if (m_materialDecorator != nullptr) {
0085 ACTS_VERBOSE("Decorating boundary surface " << bSurface.name()
0086 << " with material");
0087 m_materialDecorator->decorate(mutableBSurface);
0088 }
0089 }
0090
0091 void visitLayer(Layer& layer) override {
0092 ACTS_DEBUG("Close Layer");
0093
0094 m_ilayer += 1;
0095 auto layerID = GeometryIdentifier(m_volumeID).withLayer(m_ilayer);
0096 ACTS_VERBOSE("~> layerID: " << layerID);
0097
0098
0099 layer.closeGeometry(m_materialDecorator, layerID, *m_hook, *m_logger);
0100 }
0101
0102 const Logger* m_logger;
0103 GeometryIdentifier m_volumeID;
0104 GeometryIdentifier::Value m_iboundary = 0;
0105 GeometryIdentifier::Value m_ilayer = 0;
0106 const IMaterialDecorator* m_materialDecorator = nullptr;
0107 const GeometryIdentifierHook* m_hook = nullptr;
0108
0109 std::unordered_map<GeometryIdentifier, const TrackingVolume*> m_volumesById{};
0110 std::unordered_map<GeometryIdentifier, const Surface*> m_surfacesById{};
0111 };
0112
0113 namespace {
0114 class GeometryIdMapVisitor : public TrackingGeometryVisitor {
0115 private:
0116 void checkIdentifier(const GeometryObject& obj, std::string_view type) {
0117 if (obj.geometryId() == GeometryIdentifier{}) {
0118 std::stringstream ss;
0119 ss << "Encountered " << type << " with no geometry ID";
0120 throw std::invalid_argument(ss.str());
0121 }
0122
0123 ACTS_VERBOSE("Checking identifier for " << type << ": "
0124 << obj.geometryId());
0125
0126 auto [it, inserted] = m_objectsById.emplace(obj.geometryId(), &obj);
0127
0128 if (!inserted && it->second != &obj) {
0129 std::stringstream ss;
0130 ss << "Duplicate " << type << " ID: " << obj.geometryId() << ": & "
0131 << it->second << " != " << &obj;
0132 if (const auto* other = dynamic_cast<const TrackingVolume*>(it->second);
0133 other != nullptr) {
0134 ss << " (" << other->volumeName() << ")";
0135 }
0136 ACTS_ERROR(ss.str());
0137 throw std::invalid_argument(ss.str());
0138 } else {
0139 ACTS_VERBOSE("Inserted " << type << " ID: " << obj.geometryId()
0140 << " pointing at " << &obj);
0141 }
0142 }
0143
0144 const Logger& logger() const { return m_logger; }
0145 const Logger& m_logger;
0146
0147 public:
0148 explicit GeometryIdMapVisitor(const Logger& logger) : m_logger(logger) {}
0149
0150 void visitVolume(const TrackingVolume& volume) override {
0151 std::string label = "volume(" + volume.volumeName() + ")";
0152 checkIdentifier(volume, label);
0153
0154 m_volumesById.emplace(volume.geometryId(), &volume);
0155 }
0156
0157 void visitSurface(const Surface& surface) override {
0158 if (surface.geometryId() == GeometryIdentifier{}) {
0159 std::cout << "Surface has no geometry ID: "
0160 << surface.toStream(
0161 GeometryContext::dangerouslyDefaultConstruct())
0162 << std::endl;
0163 throw std::invalid_argument("Surface has no geometry ID");
0164 }
0165
0166 checkIdentifier(surface, "surface");
0167
0168 m_surfacesById.emplace(surface.geometryId(), &surface);
0169 }
0170
0171 void visitLayer(const Layer& layer) override {
0172
0173
0174
0175 if (layer.geometryId() != layer.surfaceRepresentation().geometryId()) {
0176 ACTS_ERROR("Layer ID mismatch: "
0177 << layer.geometryId()
0178 << " != " << layer.surfaceRepresentation().geometryId());
0179 throw std::invalid_argument("Layer ID mismatch");
0180 }
0181 }
0182
0183 void visitBoundarySurface(
0184 const BoundarySurfaceT<TrackingVolume>& boundary) override {
0185 const auto& surface = boundary.surfaceRepresentation();
0186 checkIdentifier(surface, "boundary surface");
0187 m_surfacesById.emplace(surface.geometryId(), &surface);
0188 }
0189
0190 void visitPortal(const Portal& portal) override {
0191 const auto& surface = portal.surface();
0192 checkIdentifier(surface, "portal");
0193 m_surfacesById.emplace(surface.geometryId(), &surface);
0194 }
0195
0196 std::unordered_map<GeometryIdentifier, const TrackingVolume*> m_volumesById{};
0197 std::unordered_map<GeometryIdentifier, const Surface*> m_surfacesById{};
0198
0199 std::unordered_map<GeometryIdentifier, const GeometryObject*> m_objectsById{};
0200 };
0201
0202 }
0203 TrackingGeometry::TrackingGeometry(
0204 const MutableTrackingVolumePtr& highestVolume,
0205 const IMaterialDecorator* materialDecorator,
0206 const GeometryIdentifierHook& hook, const Logger& logger, bool close)
0207 : m_world(highestVolume) {
0208 if (close) {
0209 ACTS_DEBUG("Closing tracking geometry with Gen1 assignment");
0210 Gen1GeometryClosureVisitor visitor{logger, materialDecorator, hook};
0211 apply(visitor);
0212 }
0213
0214 GeometryIdMapVisitor mapVisitor{logger};
0215 apply(mapVisitor);
0216 m_volumesById = std::move(mapVisitor.m_volumesById);
0217 m_surfacesById = std::move(mapVisitor.m_surfacesById);
0218
0219 ACTS_DEBUG("TrackingGeometry created with "
0220 << m_volumesById.size() << " volumes and " << m_surfacesById.size()
0221 << " surfaces");
0222
0223 m_volumesById.rehash(0);
0224 m_surfacesById.rehash(0);
0225 }
0226
0227 TrackingGeometry::~TrackingGeometry() = default;
0228
0229 const TrackingVolume* TrackingGeometry::lowestTrackingVolume(
0230 const GeometryContext& gctx, const Vector3& gp) const {
0231 return m_world->lowestTrackingVolume(gctx, gp, s_onSurfaceTolerance);
0232 }
0233
0234 const TrackingVolume* TrackingGeometry::highestTrackingVolume() const {
0235 return m_world.get();
0236 }
0237
0238 TrackingVolume* TrackingGeometry::highestTrackingVolume() {
0239 return m_world.get();
0240 }
0241
0242 std::shared_ptr<const TrackingVolume>
0243 TrackingGeometry::highestTrackingVolumePtr() const {
0244 return m_world;
0245 }
0246
0247 const Layer* TrackingGeometry::associatedLayer(const GeometryContext& gctx,
0248 const Vector3& gp) const {
0249 const TrackingVolume* lowestVol = lowestTrackingVolume(gctx, gp);
0250 if (lowestVol == nullptr) {
0251 return nullptr;
0252 }
0253 return lowestVol->associatedLayer(gctx, gp);
0254 }
0255
0256 const TrackingVolume* TrackingGeometry::findVolume(
0257 GeometryIdentifier id) const {
0258 auto vol = m_volumesById.find(id);
0259 if (vol == m_volumesById.end()) {
0260 return nullptr;
0261 }
0262 return vol->second;
0263 }
0264
0265 const Surface* TrackingGeometry::findSurface(GeometryIdentifier id) const {
0266 auto srf = m_surfacesById.find(id);
0267 if (srf == m_surfacesById.end()) {
0268 return nullptr;
0269 }
0270 return srf->second;
0271 }
0272
0273 const std::unordered_map<GeometryIdentifier, const Surface*>&
0274 TrackingGeometry::geoIdSurfaceMap() const {
0275 return m_surfacesById;
0276 }
0277
0278 void TrackingGeometry::visualize(IVisualization3D& helper,
0279 const GeometryContext& gctx,
0280 const ViewConfig& viewConfig,
0281 const ViewConfig& portalViewConfig,
0282 const ViewConfig& sensitiveViewConfig) const {
0283 highestTrackingVolume()->visualize(helper, gctx, viewConfig, portalViewConfig,
0284 sensitiveViewConfig);
0285 }
0286
0287 void TrackingGeometry::apply(TrackingGeometryVisitor& visitor) const {
0288 highestTrackingVolume()->apply(visitor);
0289 }
0290
0291 void TrackingGeometry::apply(TrackingGeometryMutableVisitor& visitor) {
0292 highestTrackingVolume()->apply(visitor);
0293 }
0294
0295 TrackingGeometry::GeometryVersion TrackingGeometry::geometryVersion() const {
0296 if (highestTrackingVolume()->portals().empty()) {
0297 return GeometryVersion::Gen1;
0298 } else {
0299 return GeometryVersion::Gen3;
0300 }
0301 }
0302
0303 }