File indexing completed on 2026-09-25 08:21:01
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Material/TrackingGeometryMaterial.hpp"
0010
0011 #include "Acts/Geometry/TrackingGeometry.hpp"
0012 #include "Acts/Geometry/TrackingVolume.hpp"
0013 #include "Acts/Material/MergedMaterialMarker.hpp"
0014 #include "Acts/Material/ProtoSurfaceMaterial.hpp"
0015 #include "Acts/Material/detail/MaterialSurfaceRegistry.hpp"
0016 #include "Acts/Utilities/Helpers.hpp"
0017
0018 #include <set>
0019 #include <sstream>
0020 #include <stdexcept>
0021 #include <vector>
0022
0023 namespace Acts {
0024
0025 namespace {
0026 std::shared_ptr<const ISurfaceMaterial> resolve(
0027 const TrackingGeometryMaterial& maps, const Surface& surface) {
0028 if (const auto* marker = dynamic_cast<const MergedMaterialMarker*>(
0029 surface.surfaceMaterial())) {
0030 std::ostringstream message;
0031 message << "Cannot decorate surface " << surface.geometryId() << ": "
0032 << *marker;
0033 throw std::invalid_argument(message.str());
0034 }
0035 if (detail::materialKey(surface.surfaceMaterial())) {
0036 const auto& key = *detail::materialKey(surface.surfaceMaterial());
0037 const auto found = maps.keyedSurfaces.find(key);
0038 if (found == maps.keyedSurfaces.end() || !found->second.material) {
0039 throw std::invalid_argument("Missing material for key '" + key + "'");
0040 }
0041 auto checkProtoKey = [&](const auto* proto) {
0042 if (proto != nullptr && proto->materialKey() &&
0043 *proto->materialKey() != key) {
0044 throw std::invalid_argument(
0045 "Proto material disagrees with assignment key '" + key + "'");
0046 }
0047 };
0048 checkProtoKey(dynamic_cast<const ProtoSurfaceMaterial*>(
0049 found->second.material.get()));
0050 checkProtoKey(dynamic_cast<const ProtoGridSurfaceMaterial*>(
0051 found->second.material.get()));
0052 if (dynamic_cast<const MergedMaterialMarker*>(
0053 found->second.material.get()) != nullptr) {
0054 throw std::invalid_argument("Merged material marker cannot supply key '" +
0055 key + "'");
0056 }
0057 return found->second.material;
0058 }
0059 const auto found = maps.surfaceMaterials.find(surface.geometryId());
0060 return found == maps.surfaceMaterials.end() ? nullptr : found->second;
0061 }
0062
0063 }
0064
0065 void TrackingGeometryMaterial::apply(Surface& surface) const {
0066 if (auto material = resolve(*this, surface)) {
0067 surface.assignSurfaceMaterial(std::move(material));
0068 }
0069 }
0070
0071 void TrackingGeometryMaterial::apply(std::span<Surface* const> surfaces) const {
0072 std::vector<const Surface*> participating;
0073 for (const Surface* surface : surfaces) {
0074 if (surface == nullptr) {
0075 throw std::invalid_argument("Null surface during material decoration");
0076 }
0077 if (surface->hasMaterial() ||
0078 detail::materialKey(surface->surfaceMaterial()) ||
0079 surfaceMaterials.contains(surface->geometryId())) {
0080 participating.push_back(surface);
0081 }
0082 }
0083 detail::MaterialSurfaceRegistry registry(participating);
0084 std::vector<std::pair<Surface*, std::shared_ptr<const ISurfaceMaterial>>>
0085 assignments;
0086 std::set<Surface*> visited;
0087 for (Surface* surface : surfaces) {
0088 if (visited.insert(surface).second) {
0089 if (auto material = resolve(*this, *surface)) {
0090 assignments.emplace_back(surface, std::move(material));
0091 }
0092 }
0093 }
0094 for (auto& [surface, material] : assignments) {
0095 surface->assignSurfaceMaterial(std::move(material));
0096 }
0097 }
0098
0099 void TrackingGeometryMaterial::apply(TrackingGeometry& geometry) const {
0100 if (!keyedSurfaces.empty() &&
0101 geometry.geometryVersion() == TrackingGeometry::GeometryVersion::Gen1) {
0102 throw std::invalid_argument(
0103 "Cannot apply a keyed material map to Gen1 geometry: stable material "
0104 "keys require Gen3 material designators. Use a Gen1 map indexed by "
0105 "geometry ID or apply this map to the matching Gen3 geometry.");
0106 }
0107 std::vector<Surface*> surfaces;
0108 std::vector<TrackingVolume*> volumes;
0109 geometry.apply(
0110 overloaded{[&](Surface& surface) { surfaces.push_back(&surface); },
0111 [&](Portal& portal) { surfaces.push_back(&portal.surface()); },
0112 [&](BoundarySurfaceT<TrackingVolume>& boundary) {
0113 surfaces.push_back(&boundary.surfaceRepresentation());
0114 },
0115 [&](TrackingVolume& volume) { volumes.push_back(&volume); }});
0116 apply(surfaces);
0117 for (auto* volume : volumes) {
0118 apply(*volume);
0119 }
0120 }
0121
0122 void TrackingGeometryMaterial::apply(TrackingVolume& volume) const {
0123 if (const auto found = volumeMaterials.find(volume.geometryId());
0124 found != volumeMaterials.end()) {
0125 volume.assignVolumeMaterial(found->second);
0126 }
0127 }
0128
0129 }