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