SPH
Grid.h
Go to the documentation of this file.
1 #pragma once
2 
7 
12 
14 
15 template <typename T>
16 class Grid {
17 private:
19  Indices dimensions = Indices(0);
20 
21 public:
22  Grid() = default;
23 
24  Grid(const Indices& dimensions, const T& value = T())
25  : dimensions(dimensions) {
26  data.resizeAndSet(this->voxelCount(), value);
27  }
28 
29  INLINE T& operator[](const Indices& idxs) {
30  return data[map(idxs)];
31  }
32 
33  INLINE const T& operator[](const Indices& idxs) const {
34  return data[map(idxs)];
35  }
36 
37  INLINE Indices size() const {
38  return dimensions;
39  }
40 
41  INLINE bool empty() const {
42  return data.empty();
43  }
44 
45  INLINE uint64_t voxelCount() const {
46  return dimensions[X] * dimensions[Y] * dimensions[Z];
47  }
48 
50  return data.begin();
51  }
52 
54  return data.end();
55  }
56 
57 private:
58  INLINE uint64_t map(const Indices idxs) const {
59  SPH_ASSERT(idxs[X] >= 0 && idxs[X] < dimensions[X]);
60  SPH_ASSERT(idxs[Y] >= 0 && idxs[Y] < dimensions[Y]);
61  SPH_ASSERT(idxs[Z] >= 0 && idxs[Z] < dimensions[Z]);
62  return idxs[X] * dimensions[Y] * dimensions[Z] + idxs[Y] * dimensions[Z] + idxs[Z];
63  }
64 };
65 
66 template <typename T>
67 class OctreeNode {
68 private:
70 
72 
73 public:
74  T& create(const Indices& idxs, const Size dim, const T& value) {
75  if (dim == 1) {
76  // create leaf node
77  data = value;
78  return data;
79  }
80  Size code;
81  Indices childIdxs;
82  tieToTuple(code, childIdxs) = this->getCodeAndChildIdxs(idxs, dim);
83 
84  Children& children = data;
85  if (!children[code]) {
86  children[code] = makeAuto<OctreeNode>();
87  }
88  return children[code]->create(childIdxs, dim / 2, value);
89  }
90 
91  struct Hint {
94  };
95 
96  Variant<T*, Hint> find(const Indices& idxs, const Size dim) {
97  SPH_ASSERT(idxs[X] >= 0 && idxs[X] < int(dim), idxs, dim);
98  SPH_ASSERT(idxs[Y] >= 0 && idxs[Y] < int(dim), idxs, dim);
99  SPH_ASSERT(idxs[Z] >= 0 && idxs[Z] < int(dim), idxs, dim);
100  if (this->isLeaf()) {
101  return std::addressof(data.template get<T>());
102  } else {
103  Size code;
104  Indices childIdxs;
105  tieToTuple(code, childIdxs) = this->getCodeAndChildIdxs(idxs, dim);
106 
107  Children& children = data;
108  if (children[code]) {
109  return children[code]->find(childIdxs, dim / 2);
110  } else {
111  return Hint{ this, dim };
112  }
113  }
114  }
115 
116  Variant<const T*, Hint> find(const Indices& idxs, const Size dim) const {
117  Variant<T*, Hint> value = const_cast<OctreeNode*>(this)->find(idxs, dim);
118  if (value.template has<T*>()) {
119  return static_cast<const T*>(value.template get<T*>());
120  } else {
121  return value.template get<Hint>();
122  }
123  }
124 
125  template <typename TFunctor>
126  void iterate(const Indices& from, const Indices& to, const TFunctor& functor) {
127  if (this->isLeaf()) {
128  SPH_ASSERT(all(to - from == Indices(1)));
129  functor(data.template get<T>(), from);
130  return;
131  }
132 
133  Children& children = data;
134  for (Size code = 0; code < 8; ++code) {
135  if (!children[code]) {
136  continue;
137  }
138  const Indices size((to[X] - from[X]) / 2, (to[Y] - from[Y]) / 2, (to[Z] - from[Z]) / 2);
139  Indices n1 = from, n2 = to;
140  if (code & 0x01) {
141  n1[X] += size[X];
142  } else {
143  n2[X] -= size[X];
144  }
145  if (code & 0x02) {
146  n1[Y] += size[Y];
147  } else {
148  n2[Y] -= size[Y];
149  }
150  if (code & 0x04) {
151  n1[Z] += size[Z];
152  } else {
153  n2[Z] -= size[Z];
154  }
155  children[code]->iterate(n1, n2, functor);
156  }
157  }
158 
159  bool isLeaf() const {
160  return data.template has<T>();
161  }
162 
163 private:
164  INLINE Tuple<Size, Indices> getCodeAndChildIdxs(const Indices& idxs, const Size dim) const {
165  SPH_ASSERT(dim > 1);
166  const int half = int(dim / 2);
167  Indices child = idxs;
168  Size code = 0;
169  if (idxs[X] >= half) {
170  code |= 0x01;
171  child[X] -= half;
172  }
173  if (idxs[Y] >= half) {
174  code |= 0x02;
175  child[Y] -= half;
176  }
177  if (idxs[Z] >= half) {
178  code |= 0x04;
179  child[Z] -= half;
180  }
181  SPH_ASSERT(code < 8);
182  return { code, child };
183  }
184 };
185 
186 template <typename T>
187 class SparseGrid {
188 private:
189  Size dimensions = 0;
190  T defaultValue;
191 
192  OctreeNode<T> root;
193 
194 public:
195  SparseGrid() = default;
196 
197  SparseGrid(const Size dimensions, const T& value = T())
198  : dimensions(dimensions)
199  , defaultValue(value) {
200  SPH_ASSERT(isPower2(dimensions));
201  }
202 
203  INLINE T& operator[](const Indices& idxs) {
204  Variant<T*, typename OctreeNode<T>::Hint> ptrOrHint = root.find(idxs, dimensions);
205  if (ptrOrHint.template has<T*>()) {
206  return *ptrOrHint.template get<T*>();
207  } else {
208  typename OctreeNode<T>::Hint hint = ptrOrHint;
209  return hint.node->create(idxs, hint.dim, defaultValue);
210  }
211  }
212 
213  INLINE const T& operator[](const Indices& idxs) const {
214  Variant<const T*, typename OctreeNode<T>::Hint> ptrOrHint = root.find(idxs, dimensions);
215  if (ptrOrHint.template has<const T*>()) {
216  return *ptrOrHint.template get<const T*>();
217  } else {
218  return defaultValue;
219  }
220  }
221 
222  template <typename TFunctor>
223  void iterate(const TFunctor& functor) {
224  root.iterate(Indices(0), Indices(dimensions), functor);
225  }
226 
227  INLINE Size size() const {
228  return dimensions;
229  }
230 
231  INLINE bool empty() const {
232  return dimensions == 0;
233  }
234 
235  INLINE uint64_t voxelCount() const {
236  const uint64_t d = dimensions;
237  return d * d * d;
238  }
239 };
240 
Generic dynamically allocated resizable storage.
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
Simplified implementation of std::unique_ptr, using only default deleter.
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
Vectorized computations with integral numbers.
INLINE bool all(const Indices &i)
Definition: Indices.h:144
INLINE Float root(const Float f)
constexpr INLINE bool isPower2(const Size n) noexcept
Returns true if given n is a power of 2. N must at least 1.
Definition: MathUtils.h:72
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
INLINE Tuple< TArgs &... > tieToTuple(TArgs &... args)
Creates a tuple of l-value references. Use IGNORE placeholder to omit one or more parameters.
Definition: Tuple.h:304
Object capable of storing values of different types.
@ Y
Definition: Vector.h:23
@ X
Definition: Vector.h:22
@ Z
Definition: Vector.h:24
INLINE Iterator< StorageType > end() noexcept
Definition: Array.h:462
INLINE bool empty() const noexcept
Definition: Array.h:201
void resizeAndSet(const TCounter newSize, const T &value)
Resizes the array to new size and assigns a given value to all newly created elements.
Definition: Array.h:265
INLINE Iterator< StorageType > begin() noexcept
Definition: Array.h:450
Definition: Grid.h:16
Iterator< T > end()
Definition: Grid.h:53
INLINE T & operator[](const Indices &idxs)
Definition: Grid.h:29
Iterator< T > begin()
Definition: Grid.h:49
INLINE const T & operator[](const Indices &idxs) const
Definition: Grid.h:33
INLINE bool empty() const
Definition: Grid.h:41
INLINE Indices size() const
Definition: Grid.h:37
Grid()=default
INLINE uint64_t voxelCount() const
Definition: Grid.h:45
Grid(const Indices &dimensions, const T &value=T())
Definition: Grid.h:24
Helper object for storing three (possibly four) int or bool values.
Definition: Indices.h:16
Simple (forward) iterator over continuous array of objects of type T.
Definition: Iterator.h:18
Variant< const T *, Hint > find(const Indices &idxs, const Size dim) const
Definition: Grid.h:116
void iterate(const Indices &from, const Indices &to, const TFunctor &functor)
Definition: Grid.h:126
Variant< T *, Hint > find(const Indices &idxs, const Size dim)
Definition: Grid.h:96
bool isLeaf() const
Definition: Grid.h:159
T & create(const Indices &idxs, const Size dim, const T &value)
Definition: Grid.h:74
INLINE Size size() const
Definition: Grid.h:227
SparseGrid()=default
INLINE T & operator[](const Indices &idxs)
Definition: Grid.h:203
INLINE const T & operator[](const Indices &idxs) const
Definition: Grid.h:213
INLINE uint64_t voxelCount() const
Definition: Grid.h:235
void iterate(const TFunctor &functor)
Definition: Grid.h:223
INLINE bool empty() const
Definition: Grid.h:231
SparseGrid(const Size dimensions, const T &value=T())
Definition: Grid.h:197
Array with fixed number of allocated elements.
Definition: StaticArray.h:19
Heterogeneous container capable of storing a fixed number of values.
Definition: Tuple.h:146
Variant, an implementation of type-safe union, similar to std::variant or boost::variant.
Definition: Variant.h:171
Size dim
Definition: Grid.h:93
OctreeNode * node
Definition: Grid.h:92