File indexing completed on 2025-09-16 08:13:42
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Geometry/GeometryIdentifier.hpp"
0012 #include "Acts/Utilities/PointerTraits.hpp"
0013 #include "ActsExamples/Utilities/GroupBy.hpp"
0014 #include "ActsExamples/Utilities/Range.hpp"
0015
0016 #include <algorithm>
0017 #include <cassert>
0018 #include <utility>
0019
0020 #include <boost/bimap.hpp>
0021 #include <boost/container/flat_map.hpp>
0022 #include <boost/container/flat_set.hpp>
0023
0024 namespace ActsExamples {
0025 namespace detail {
0026
0027 template <typename ObjType>
0028 concept GeometryIdObj = requires(const ObjType& obj) {
0029 { obj.geometryId() } -> std::same_as<Acts::GeometryIdentifier>;
0030 };
0031
0032 template <typename ObjType>
0033 concept GeometryIdPtrObj =
0034 Acts::PointerConcept<ObjType> &&
0035 GeometryIdObj<typename Acts::RemovePointer<ObjType>::type>;
0036
0037
0038 template <typename ObjType>
0039 concept TimedObj = requires(const ObjType& obj) {
0040 { obj.time() };
0041 };
0042
0043 template <typename ObjType>
0044 concept TimedObjPtr = Acts::PointerConcept<ObjType> &&
0045 TimedObj<typename Acts::RemovePointer<ObjType>::type>;
0046
0047
0048 struct GeometryIdGetter {
0049
0050 constexpr Acts::GeometryIdentifier operator()(
0051 Acts::GeometryIdentifier geometryId) const {
0052 return geometryId;
0053 }
0054
0055 constexpr Acts::GeometryIdentifier operator()(
0056 Acts::GeometryIdentifier::Value encoded) const {
0057 return Acts::GeometryIdentifier(encoded);
0058 }
0059
0060 template <typename T>
0061 constexpr Acts::GeometryIdentifier operator()(
0062 const std::pair<Acts::GeometryIdentifier, T>& mapItem) const {
0063 return mapItem.first;
0064 }
0065
0066 template <GeometryIdPtrObj T>
0067 constexpr Acts::GeometryIdentifier operator()(const T& thing) const {
0068 return thing->geometryId();
0069 }
0070
0071 template <GeometryIdObj T>
0072 inline auto operator()(const T& thing) const {
0073 return thing.geometryId();
0074 }
0075
0076 template <GeometryIdObj T>
0077 inline auto operator()(std::reference_wrapper<T> thing) const
0078 -> decltype(thing.get().geometryId(), Acts::GeometryIdentifier()) {
0079 return thing.get().geometryId();
0080 }
0081 };
0082
0083 struct CompareGeometryId {
0084
0085 using is_transparent = void;
0086
0087
0088 template <TimedObj Left, TimedObj Right>
0089 constexpr bool operator()(const Left& lhs, const Right& rhs) const {
0090 const auto lId = GeometryIdGetter{}(lhs);
0091 const auto rId = GeometryIdGetter{}(rhs);
0092 if (lId == rId) {
0093 return lhs.time() < rhs.time();
0094 }
0095 return lId < rId;
0096 }
0097 template <TimedObjPtr Left, TimedObjPtr Right>
0098 constexpr bool operator()(const Left& lhs, const Right& rhs) const {
0099 return (*this)(*lhs, *rhs);
0100 }
0101
0102 template <typename Left, typename Right>
0103 constexpr bool operator()(Left&& lhs, Right&& rhs) const {
0104 return GeometryIdGetter()(lhs) < GeometryIdGetter()(rhs);
0105 }
0106 };
0107
0108 }
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 template <typename T>
0121 using GeometryIdMultiset =
0122 boost::container::flat_multiset<T, detail::CompareGeometryId>;
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 template <typename T>
0137 using GeometryIdMultimap =
0138 GeometryIdMultiset<std::pair<Acts::GeometryIdentifier, T>>;
0139
0140
0141 template <typename T>
0142 inline Range<typename GeometryIdMultiset<T>::const_iterator> selectVolume(
0143 const GeometryIdMultiset<T>& container,
0144 Acts::GeometryIdentifier::Value volume) {
0145 auto cmp = Acts::GeometryIdentifier().withVolume(volume);
0146 auto beg = std::lower_bound(container.begin(), container.end(), cmp,
0147 detail::CompareGeometryId{});
0148
0149 cmp = Acts::GeometryIdentifier().withVolume(volume + 1u);
0150
0151
0152
0153 auto end =
0154 std::lower_bound(beg, container.end(), cmp, detail::CompareGeometryId{});
0155 return makeRange(beg, end);
0156 }
0157
0158
0159 template <typename T>
0160 inline auto selectVolume(const GeometryIdMultiset<T>& container,
0161 Acts::GeometryIdentifier id) {
0162 return selectVolume(container, id.volume());
0163 }
0164
0165
0166 template <typename T>
0167 inline Range<typename GeometryIdMultiset<T>::const_iterator> selectLayer(
0168 const GeometryIdMultiset<T>& container,
0169 Acts::GeometryIdentifier::Value volume,
0170 Acts::GeometryIdentifier::Value layer) {
0171 auto cmp = Acts::GeometryIdentifier().withVolume(volume).withLayer(layer);
0172 auto beg = std::lower_bound(container.begin(), container.end(), cmp,
0173 detail::CompareGeometryId{});
0174
0175 cmp = Acts::GeometryIdentifier().withVolume(volume).withLayer(layer + 1u);
0176
0177
0178
0179 auto end =
0180 std::lower_bound(beg, container.end(), cmp, detail::CompareGeometryId{});
0181 return makeRange(beg, end);
0182 }
0183
0184
0185 template <typename T>
0186 inline auto selectLayer(const GeometryIdMultiset<T>& container,
0187 Acts::GeometryIdentifier id) {
0188 return selectLayer(container, id.volume(), id.layer());
0189 }
0190
0191
0192 template <typename T>
0193 inline Range<typename GeometryIdMultiset<T>::const_iterator> selectModule(
0194 const GeometryIdMultiset<T>& container, Acts::GeometryIdentifier geoId) {
0195
0196 return makeRange(container.equal_range(geoId));
0197 }
0198
0199
0200 template <typename T>
0201 inline auto selectModule(const GeometryIdMultiset<T>& container,
0202 Acts::GeometryIdentifier::Value volume,
0203 Acts::GeometryIdentifier::Value layer,
0204 Acts::GeometryIdentifier::Value sensitive) {
0205 return selectModule(container, Acts::GeometryIdentifier()
0206 .withVolume(volume)
0207 .withLayer(layer)
0208 .withSensitive(sensitive));
0209 }
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 template <typename T>
0228 inline Range<typename GeometryIdMultiset<T>::const_iterator>
0229 selectLowestNonZeroGeometryObject(const GeometryIdMultiset<T>& container,
0230 Acts::GeometryIdentifier geoId) {
0231 assert((geoId.boundary() == 0u) && "Boundary component must be zero");
0232 assert((geoId.approach() == 0u) && "Approach component must be zero");
0233
0234 if (geoId.sensitive() != 0u) {
0235 return selectModule(container, geoId);
0236 } else if (geoId.layer() != 0u) {
0237 return selectLayer(container, geoId);
0238 } else if (geoId.volume() != 0u) {
0239 return selectVolume(container, geoId);
0240 } else {
0241 return makeRange(container.begin(), container.end());
0242 }
0243 }
0244
0245
0246 template <typename T>
0247 inline GroupBy<typename GeometryIdMultiset<T>::const_iterator,
0248 detail::GeometryIdGetter>
0249 groupByModule(const GeometryIdMultiset<T>& container) {
0250 return makeGroupBy(container, detail::GeometryIdGetter());
0251 }
0252
0253
0254
0255
0256
0257 template <typename T>
0258 struct GeometryIdMultisetAccessor {
0259 using Container = GeometryIdMultiset<T>;
0260 using Key = Acts::GeometryIdentifier;
0261 using Value = typename GeometryIdMultiset<T>::value_type;
0262 using Iterator = typename GeometryIdMultiset<T>::const_iterator;
0263
0264
0265 const Container* container = nullptr;
0266 };
0267
0268
0269
0270 using GeometryIdMapActsAthena =
0271 boost::bimap<std::uint64_t, Acts::GeometryIdentifier>;
0272
0273 }