File indexing completed on 2025-01-18 10:13:52
0001 #pragma once
0002
0003 #include <unordered_map>
0004 #include <vector>
0005 #include "VecGeom/base/Vector3D.h"
0006 #include "VecGeom/management/ABBoxManager.h"
0007 #include "VecGeom/base/SOA3D.h"
0008 #include "VecGeom/base/robin_hood.h" // for fast hash map
0009 #include <type_traits>
0010
0011 namespace vecgeom {
0012 inline namespace VECGEOM_IMPL_NAMESPACE {
0013
0014
0015
0016
0017
0018 template <typename P, bool ScalarProperties = false>
0019 class FlatVoxelHashMap {
0020 public:
0021 FlatVoxelHashMap(Vector3D<float> const &lower, Vector3D<float> const &Length, int Nx, int Ny, int Nz)
0022 : fNx{Nx}, fNy{Ny}, fNz{Nz}
0023 {
0024 fLowerX = lower.x();
0025 fLowerY = lower.y();
0026 fLowerZ = lower.z();
0027 fDeltaX = Length.x() / Nx;
0028 fDeltaY = Length.y() / Ny;
0029 fDeltaZ = Length.z() / Nz;
0030 fInvDeltaX = 1. / fDeltaX;
0031 fInvDeltaY = 1. / fDeltaY;
0032 fInvDeltaZ = 1. / fDeltaZ;
0033 }
0034
0035
0036
0037 void addProperty(Vector3D<float> const &point, P const &property)
0038 {
0039 const auto key = getVoxelKey(point);
0040 addPropertyForKey(key, property);
0041 }
0042
0043
0044 float getVoxelDiagonal() const { return std::sqrt(fDeltaX * fDeltaX + fDeltaY * fDeltaY + fDeltaZ * fDeltaZ); }
0045
0046 float getVoxelVolume() const { return fDeltaX * fDeltaY * fDeltaZ; }
0047
0048 void addPropertyForKey(long key, P const &property)
0049 {
0050 auto iter = fVoxelMap.find(key);
0051 if (key == fLastKey) {
0052
0053
0054 if (iter == fVoxelMap.end()) {
0055 std::cerr << "THERE SHOULD BE AN ENTRY ALREADY\n";
0056 }
0057 append<P>(iter, property);
0058 } else {
0059
0060
0061
0062 if (iter != fVoxelMap.end()) {
0063 std::cerr << "FATAL ERROR IN INSERTION\n";
0064 }
0065
0066 assign<P>(key, property);
0067 fLastKey = key;
0068 }
0069 }
0070
0071
0072
0073 void markFromBoundingBoxes(LogicalVolume const &lvol)
0074 {
0075
0076
0077
0078
0079
0080
0081
0082 std::vector<std::pair<long, P>> keyToProp;
0083
0084 int nDaughters{0};
0085 auto abboxes = ABBoxManager::Instance().GetABBoxes(&lvol, nDaughters);
0086 for (int d = 0; d < nDaughters; ++d) {
0087 const auto &lower = abboxes[2 * d];
0088 const auto &upper = abboxes[2 * d + 1];
0089
0090 int kxlow{-1}, kylow{-1}, kzlow{-1};
0091 int kxup{-1}, kyup{-1}, kzup{-1};
0092 getVoxelCoordinates(lower.x(), lower.y(), lower.z(), kxlow, kylow, kzlow);
0093 getVoxelCoordinates(upper.x(), upper.y(), upper.z(), kxup, kyup, kzup);
0094
0095 kxlow = std::max(kxlow, 0);
0096 kylow = std::max(kylow, 0);
0097 kzlow = std::max(kzlow, 0);
0098
0099 kxup = std::min(kxup, fNx - 1);
0100 kyup = std::min(kyup, fNy - 1);
0101 kzup = std::min(kzup, fNz - 1);
0102
0103
0104 for (int kx = kxlow; kx <= kxup; ++kx) {
0105 for (int ky = kylow; ky <= kyup; ++ky) {
0106 for (int kz = kzlow; kz <= kzup; ++kz) {
0107 keyToProp.push_back(std::pair<long, P>(getKeyFromCells(kx, ky, kz), d));
0108 }
0109 }
0110 }
0111 }
0112
0113
0114 std::sort(keyToProp.begin(), keyToProp.end(),
0115 [](std::pair<long, P> const &a, std::pair<long, P> const &b) { return a.first < b.first; });
0116
0117
0118 for (auto &e : keyToProp) {
0119 addPropertyForKey(e.first, e.second);
0120 }
0121 }
0122
0123
0124 bool isOccupied(Vector3D<float> const &point) const { return fVoxelMap.find(getVoxelKey(point)) != fVoxelMap.end(); }
0125
0126 bool isOccupied(long key) const { return fVoxelMap.find(key) != fVoxelMap.end(); }
0127
0128
0129
0130 std::vector<long> getKeys(SOA3D<float> const &points)
0131 {
0132 std::vector<long> keys;
0133 for (size_t i = 0; i < points.size(); ++i) {
0134 keys.push_back(getKey(points.x(i), points.y(i), points.z(i)));
0135 }
0136 return keys;
0137 }
0138
0139
0140
0141 template <typename T>
0142 void getKeys(SOA3D<T> const &points, std::vector<long> &keys)
0143 {
0144 for (size_t i = 0; i < points.size(); ++i) {
0145 keys.push_back(getKey(points.x(i), points.y(i), points.z(i)));
0146 }
0147 }
0148
0149
0150 void getVoxelCoordinates(float x, float y, float z, int &kx, int &ky, int &kz) const
0151 {
0152 kx = (int)((x - fLowerX) * fInvDeltaX);
0153 ky = (int)((y - fLowerY) * fInvDeltaY);
0154 kz = (int)((z - fLowerZ) * fInvDeltaZ);
0155 }
0156
0157 long getKeyFromCells(int kx, int ky, int kz) const { return kx + fNx * (ky + kz * fNy); }
0158
0159 long getKey(float x, float y, float z) const
0160 {
0161 const auto kx = (int)((x - fLowerX) * fInvDeltaX);
0162 const auto ky = (int)((y - fLowerY) * fInvDeltaY);
0163 const auto kz = (int)((z - fLowerZ) * fInvDeltaZ);
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 return getKeyFromCells(kx, ky, kz);
0174 }
0175
0176 long getVoxelKey(Vector3D<float> const &point) const { return getKey(point.x(), point.y(), point.z()); }
0177
0178 const P *getProperties(Vector3D<float> const &point, int &length) const
0179 {
0180 return getPropertiesGivenKey(getVoxelKey(point), length);
0181 }
0182
0183
0184
0185
0186
0187 const P *getPropertiesGivenKey(long key, int &length) const { return getPropertiesImpl<P>(key, length); }
0188
0189 Vector3D<int> keyToCell(long key) const
0190 {
0191 const auto kz = key / (fNx * fNy);
0192 const auto ky = (key - (kz * fNx * fNy)) / fNx;
0193 const auto kx = key - (kz * fNx * fNy) - ky * fNx;
0194 return Vector3D<int>(kx, ky, kz);
0195 }
0196
0197
0198 Vector3D<float> keyToPos(long key) const
0199 {
0200 const auto kz = key / (fNx * fNy);
0201 const auto ky = (key - (kz * fNx * fNy)) / fNx;
0202 const auto kx = key - (kz * fNx * fNy) - ky * fNx;
0203 return Vector3D<float>(fLowerX + kx * fDeltaX * 1.5, fLowerY + ky * fDeltaY * 1.5, fLowerZ + kz * fDeltaZ * 1.5);
0204 }
0205
0206
0207 void Extent(long key, Vector3D<float> &lower, Vector3D<float> &upper) const
0208 {
0209 const auto kz = key / (fNx * fNy);
0210 const auto ky = (key - (kz * fNx * fNy)) / fNx;
0211 const auto kx = key - (kz * fNx * fNy) - ky * fNx;
0212 lower = Vector3D<float>(fLowerX + kx * fDeltaX, fLowerY + ky * fDeltaY, fLowerZ + kz * fDeltaZ);
0213 upper = lower + Vector3D<float>(fDeltaX, fDeltaY, fDeltaZ);
0214 }
0215
0216
0217 void print() const
0218 {
0219 int count{0};
0220 int pcount{0};
0221 for (auto &k : fVoxelMap) {
0222 auto key = k.first;
0223 int number{0};
0224 auto props = getPropertiesGivenKey(key, number);
0225 pcount += number;
0226 count++;
0227 std::cout << " voxel at key " << key << " : " << keyToCell(key) << " pos " << keyToPos(key) << " filled with "
0228 << number << " properties \n";
0229 std::cout << "{ ";
0230 for (int i = 0; i < number; ++i) {
0231 std::cout << props[i] << " , ";
0232 }
0233 std::cout << " }\n";
0234 }
0235 std::cout << "NUM VOXELS OCCUPIED " << count << " SUM PROPERTIES " << pcount << "\n";
0236 }
0237
0238
0239 void clear()
0240 {
0241 fVoxelMap.clear();
0242 fProperties.clear();
0243 }
0244
0245
0246 size_t size() const { return fVoxelMap.size(); }
0247
0248 private:
0249
0250 int fNx = 0;
0251 int fNy = 0;
0252 int fNz = 0;
0253
0254
0255 float fLowerX = 0.;
0256 float fLowerY = 0.;
0257 float fLowerZ = 0.;
0258 float fDeltaX = 1.;
0259 float fDeltaY = 1.;
0260 float fDeltaZ = 1.;
0261 float fInvDeltaX = 1.;
0262 float fInvDeltaY = 1.;
0263 float fInvDeltaZ = 1.;
0264
0265 long fLastKey = -1;
0266
0267
0268
0269
0270
0271
0272 template <typename T>
0273 void assign(long key, typename std::enable_if<ScalarProperties, T>::type prop)
0274 {
0275 fVoxelMap[key] = prop;
0276 }
0277
0278
0279 template <typename T>
0280 void assign(long key, typename std::enable_if<!ScalarProperties, T>::type prop)
0281 {
0282 fVoxelMap[key] = std::pair<int, int>(fProperties.size(), 1);
0283 fProperties.push_back(prop);
0284 }
0285
0286
0287 template <typename T, typename Iter>
0288 void append(Iter iter, typename std::enable_if<ScalarProperties, T>::type prop)
0289 {
0290
0291
0292 std::cerr << "INVALID APPEND TO SCALAR PORPERTIES\n";
0293 }
0294
0295
0296 template <typename T, typename Iter>
0297 void append(Iter iter, typename std::enable_if<!ScalarProperties, T>::type prop)
0298 {
0299 fProperties.push_back(prop);
0300 iter->second.second++;
0301 }
0302
0303
0304 template <typename T>
0305 T const *getPropertiesImpl(long key, int &length,
0306 typename std::enable_if<!ScalarProperties, T>::type * = nullptr) const
0307 {
0308 length = 0;
0309 auto iter = fVoxelMap.find(key);
0310 if (iter != fVoxelMap.end()) {
0311 length = iter->second.second;
0312 return &fProperties[iter->second.first];
0313 }
0314 return nullptr;
0315 }
0316
0317
0318 template <typename T>
0319 T const *getPropertiesImpl(long key, int &length,
0320 typename std::enable_if<ScalarProperties, T>::type * = nullptr) const
0321 {
0322 length = 0;
0323 auto iter = fVoxelMap.find(key);
0324 if (iter != fVoxelMap.end()) {
0325 length = 1;
0326 return &(iter->second);
0327 }
0328 return nullptr;
0329 }
0330
0331 using MapValueType = typename std::conditional<ScalarProperties, P, std::pair<int, int>>::type;
0332 robin_hood::unordered_map<long, MapValueType> fVoxelMap;
0333
0334 std::vector<P> fProperties;
0335 };
0336
0337 }
0338 }