Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-29 07:33:12

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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     // Increment the volume ID for this volume
0041     m_volumeID = GeometryIdentifier().withVolume(m_volumeID.volume() + 1);
0042     // Reset boundary id for this volume
0043     m_iboundary = 0;
0044     // Reset layer id for this volume
0045     m_ilayer = 0;
0046 
0047     // assign the Volume ID to the volume itself
0048     ACTS_VERBOSE("~> volumeID: " << m_volumeID);
0049     volume.assignGeometryId(m_volumeID);
0050 
0051     // assign the material if you have a decorator
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     // get the intersection solution
0071     auto& bSurface = boundary.surfaceRepresentation();
0072     // create the boundary surface id
0073     m_iboundary += 1;
0074     auto boundaryID = GeometryIdentifier(m_volumeID).withBoundary(m_iboundary);
0075     ACTS_VERBOSE("~> boundaryID: " << boundaryID);
0076     // now assign to the boundary surface
0077     auto& mutableBSurface = *(const_cast<RegularSurface*>(&bSurface));
0078 
0079     // assign the boundary ID to the surface
0080     ACTS_VERBOSE("~> assigning boundaryID: " << boundaryID);
0081     mutableBSurface.assignGeometryId(boundaryID);
0082 
0083     // Assign material if you have a decorator
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     // create the layer identification
0094     m_ilayer += 1;
0095     auto layerID = GeometryIdentifier(m_volumeID).withLayer(m_ilayer);
0096     ACTS_VERBOSE("~> layerID: " << layerID);
0097 
0098     // now close the geometry
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     // Layers ARE also GeometryObjects and have IDs.
0173     // Let's check that the layer has the same ID as it's surface
0174     // representation. Uniqueness of the surface IDs is checked in the surface
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 }  // namespace
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 }  // namespace Acts