File indexing completed on 2026-09-15 08:18:17
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Geometry/GeometryIdentifier.hpp"
0012
0013 #include <algorithm>
0014 #include <cassert>
0015 #include <cstddef>
0016 #include <initializer_list>
0017 #include <iterator>
0018 #include <stdexcept>
0019 #include <utility>
0020 #include <vector>
0021
0022 namespace Acts {
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 template <typename value_t>
0063 class GeometryHierarchyMap {
0064 public:
0065
0066 using InputElement = typename std::pair<GeometryIdentifier, value_t>;
0067
0068 using Iterator = typename std::vector<value_t>::const_iterator;
0069
0070 using Value = value_t;
0071
0072
0073
0074
0075 explicit GeometryHierarchyMap(std::vector<InputElement> elements);
0076
0077
0078
0079
0080 GeometryHierarchyMap(std::initializer_list<InputElement> elements);
0081
0082
0083 GeometryHierarchyMap() = default;
0084
0085 GeometryHierarchyMap(const GeometryHierarchyMap&) = default;
0086
0087 GeometryHierarchyMap(GeometryHierarchyMap&&) noexcept = default;
0088 ~GeometryHierarchyMap() = default;
0089
0090
0091 GeometryHierarchyMap& operator=(const GeometryHierarchyMap&) = default;
0092
0093
0094 GeometryHierarchyMap& operator=(GeometryHierarchyMap&&) noexcept = default;
0095
0096
0097
0098 Iterator begin() const { return m_values.begin(); }
0099
0100
0101
0102 Iterator end() const { return m_values.end(); }
0103
0104
0105
0106 bool empty() const { return m_values.empty(); }
0107
0108
0109
0110 std::size_t size() const { return m_values.size(); }
0111
0112
0113
0114
0115
0116
0117 GeometryIdentifier idAt(std::size_t index) const {
0118 return GeometryIdentifier(m_ids.at(index));
0119 }
0120
0121
0122
0123
0124
0125
0126 const Value& valueAt(std::size_t index) const { return m_values.at(index); }
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137 Iterator find(const GeometryIdentifier& id) const;
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148 bool contains(const GeometryIdentifier& id) const;
0149
0150 private:
0151
0152
0153
0154 static_assert(GeometryIdentifier().withVolume(1).value() <
0155 GeometryIdentifier().withVolume(1).withBoundary(1).value(),
0156 "Incompatible GeometryIdentifier hierarchy");
0157 static_assert(GeometryIdentifier().withBoundary(1).value() <
0158 GeometryIdentifier().withBoundary(1).withLayer(1).value(),
0159 "Incompatible GeometryIdentifier hierarchy");
0160 static_assert(GeometryIdentifier().withLayer(1).value() <
0161 GeometryIdentifier().withLayer(1).withApproach(1).value(),
0162 "Incompatible GeometryIdentifier hierarchy");
0163 static_assert(
0164 GeometryIdentifier().withApproach(1).value() <
0165 GeometryIdentifier().withApproach(1).withSensitive(1).value(),
0166 "Incompatible GeometryIdentifier hierarchy");
0167
0168 using Identifier = GeometryIdentifier::Value;
0169
0170
0171 std::vector<Identifier> m_ids;
0172
0173 std::vector<Identifier> m_masks;
0174 std::vector<Value> m_values;
0175
0176
0177 static constexpr Identifier makeLeadingLevelsMask(GeometryIdentifier id) {
0178
0179 const auto allSet = GeometryIdentifier(~GeometryIdentifier::Value{0u});
0180
0181 if (id.sensitive() != 0u) {
0182
0183 return allSet.withExtra(0u).value();
0184 }
0185 if (id.approach() != 0u) {
0186 return allSet.withExtra(0u).withSensitive(0u).value();
0187 }
0188 if (id.layer() != 0u) {
0189 return allSet.withExtra(0u).withSensitive(0u).withApproach(0u).value();
0190 }
0191 if (id.boundary() != 0u) {
0192 return allSet.withExtra(0u)
0193 .withSensitive(0u)
0194 .withApproach(0u)
0195 .withLayer(0u)
0196 .value();
0197 }
0198 if (id.volume() != 0u) {
0199 return allSet.withExtra(0u)
0200 .withSensitive(0u)
0201 .withApproach(0u)
0202 .withLayer(0u)
0203 .withBoundary(0u)
0204 .value();
0205 }
0206
0207 return Identifier{0u};
0208 }
0209
0210
0211 static constexpr Identifier makeHighestLevelMask() {
0212 return makeLeadingLevelsMask(GeometryIdentifier(0u).withVolume(1u));
0213 }
0214
0215
0216 static constexpr bool equalWithinMask(Identifier lhs, Identifier rhs,
0217 Identifier mask) {
0218 return (lhs & mask) == (rhs & mask);
0219 }
0220
0221
0222 static void sortAndCheckDuplicates(std::vector<InputElement>& elements);
0223
0224
0225
0226
0227
0228 void fill(const std::vector<InputElement>& elements);
0229 };
0230
0231
0232
0233 template <typename value_t>
0234 inline GeometryHierarchyMap<value_t>::GeometryHierarchyMap(
0235 std::vector<InputElement> elements) {
0236 sortAndCheckDuplicates(elements);
0237 fill(elements);
0238 }
0239
0240 template <typename value_t>
0241 inline GeometryHierarchyMap<value_t>::GeometryHierarchyMap(
0242 std::initializer_list<InputElement> elements)
0243 : GeometryHierarchyMap(
0244 std::vector<InputElement>(elements.begin(), elements.end())) {}
0245
0246 template <typename value_t>
0247 inline void GeometryHierarchyMap<value_t>::sortAndCheckDuplicates(
0248 std::vector<InputElement>& elements) {
0249
0250 std::ranges::sort(elements, [=](const auto& lhs, const auto& rhs) {
0251 return lhs.first < rhs.first;
0252 });
0253
0254
0255 auto dup = std::ranges::adjacent_find(
0256 elements,
0257 [](const auto& lhs, const auto& rhs) { return lhs.first == rhs.first; });
0258
0259 if (dup != elements.end()) {
0260 throw std::invalid_argument("Input elements contain duplicates");
0261 }
0262 }
0263
0264 template <typename value_t>
0265 inline void GeometryHierarchyMap<value_t>::fill(
0266 const std::vector<InputElement>& elements) {
0267 m_ids.clear();
0268 m_masks.clear();
0269 m_values.clear();
0270
0271 m_ids.reserve(elements.size());
0272 m_masks.reserve(elements.size());
0273 m_values.reserve(elements.size());
0274
0275 for (const auto& element : elements) {
0276 m_ids.push_back(element.first.value());
0277 m_masks.push_back(
0278 makeLeadingLevelsMask(GeometryIdentifier(element.first.value())));
0279 m_values.push_back(std::move(element.second));
0280 }
0281 }
0282
0283 template <typename value_t>
0284 inline auto GeometryHierarchyMap<value_t>::find(
0285 const GeometryIdentifier& id) const -> Iterator {
0286 assert((m_ids.size() == m_values.size()) &&
0287 "Inconsistent container state: #ids != # values");
0288 assert((m_masks.size() == m_values.size()) &&
0289 "Inconsistent container state: #masks != #values");
0290
0291
0292
0293
0294
0295 const auto it = std::ranges::upper_bound(m_ids, id.value());
0296 auto i = static_cast<std::size_t>(std::ranges::distance(m_ids.begin(), it));
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308 while (0 < i) {
0309
0310 --i;
0311
0312
0313
0314
0315
0316
0317 if (!equalWithinMask(id.value(), m_ids[i], makeHighestLevelMask())) {
0318
0319 if (m_ids.front() == Identifier{0u}) {
0320 return begin();
0321 } else {
0322 return end();
0323 }
0324 }
0325
0326
0327
0328
0329 if (equalWithinMask(id.value(), m_ids[i], m_masks[i])) {
0330 return std::next(begin(), static_cast<std::ptrdiff_t>(i));
0331 }
0332 }
0333
0334
0335 return end();
0336 }
0337
0338 template <typename value_t>
0339 inline auto GeometryHierarchyMap<value_t>::contains(
0340 const GeometryIdentifier& id) const -> bool {
0341 return this->find(id) != this->end();
0342 }
0343
0344 }