File indexing completed on 2026-09-25 08:21:01
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Material/detail/MaterialSurfaceRegistry.hpp"
0010
0011 #include "Acts/Material/MergedMaterialMarker.hpp"
0012 #include "Acts/Material/ProtoSurfaceMaterial.hpp"
0013 #include "Acts/Surfaces/Surface.hpp"
0014
0015 #include <functional>
0016 #include <sstream>
0017 #include <stdexcept>
0018 #include <unordered_set>
0019
0020 namespace Acts::detail {
0021
0022 const std::optional<std::string>& materialKey(
0023 const ISurfaceMaterial* material) {
0024 if (auto* proto = dynamic_cast<const ProtoSurfaceMaterial*>(material)) {
0025 return proto->materialKey();
0026 }
0027 if (auto* proto = dynamic_cast<const ProtoGridSurfaceMaterial*>(material)) {
0028 return proto->materialKey();
0029 }
0030 static const std::optional<std::string> empty;
0031 return empty;
0032 }
0033
0034 MaterialSurfaceRegistry::MaterialSurfaceRegistry(
0035 std::span<const Surface* const> surfaces) {
0036 std::map<std::string, const Surface*, std::less<>> keys;
0037 std::unordered_set<const Surface*> visited;
0038 for (const Surface* surface : surfaces) {
0039 if (surface == nullptr) {
0040 throw std::invalid_argument("Null material surface");
0041 }
0042 if (!visited.insert(surface).second) {
0043 continue;
0044 }
0045 if (auto* marker = dynamic_cast<const MergedMaterialMarker*>(
0046 surface->surfaceMaterial())) {
0047 std::ostringstream message;
0048 message << "Cannot map or load material on surface "
0049 << surface->geometryId() << ": " << *marker;
0050 throw std::invalid_argument(message.str());
0051 }
0052 const auto id = surface->geometryId();
0053 if (!m_surfaces.emplace(id, surface).second) {
0054 std::ostringstream message;
0055 message << "Duplicate material surface geometry ID " << id;
0056 throw std::invalid_argument(message.str());
0057 }
0058 m_keys.try_emplace(id, detail::materialKey(surface->surfaceMaterial()));
0059 if (detail::materialKey(surface->surfaceMaterial())) {
0060 const auto& key = *detail::materialKey(surface->surfaceMaterial());
0061 if (id == GeometryIdentifier{}) {
0062 throw std::invalid_argument("Material key '" + key +
0063 "' has no geometry ID");
0064 }
0065 if (!keys.try_emplace(key, surface).second) {
0066 throw std::invalid_argument("Duplicate material key '" + key + "'");
0067 }
0068 }
0069 }
0070 }
0071
0072 TrackingGeometryMaterial MaterialSurfaceRegistry::materialMaps(
0073 SurfaceMaterialMaps materials) const {
0074 TrackingGeometryMaterial result;
0075 for (const auto& [id, key] : m_keys) {
0076 if (key && !materials.contains(id)) {
0077 throw std::invalid_argument("Missing mapping output for material key '" +
0078 *key + "'");
0079 }
0080 }
0081 for (auto& [id, material] : materials) {
0082 const auto found = m_surfaces.find(id);
0083 if (found == m_surfaces.end()) {
0084 throw std::invalid_argument(
0085 "Material output has an unregistered geometry ID");
0086 }
0087 const Surface& surface = *found->second;
0088 if (surface.geometryId() != id ||
0089 detail::materialKey(surface.surfaceMaterial()) != m_keys.at(id)) {
0090 throw std::invalid_argument(
0091 "Material surface identity changed during mapping");
0092 }
0093 if (!material) {
0094 throw std::invalid_argument("Null material in mapping output");
0095 }
0096 if (detail::materialKey(surface.surfaceMaterial())) {
0097 if (!result.keyedSurfaces
0098 .try_emplace(*detail::materialKey(surface.surfaceMaterial()),
0099 KeyedSurfaceMaterial{id, std::move(material)})
0100 .second) {
0101 throw std::invalid_argument(
0102 "Duplicate material key during finalization");
0103 }
0104 } else {
0105 result.surfaceMaterials.try_emplace(id, std::move(material));
0106 }
0107 }
0108 return result;
0109 }
0110
0111 }