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