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