Radium Engine  1.5.0
Grid.hpp
1 #pragma once
2 
3 #include <vector>
4 
5 #include <Core/RaCore.hpp>
6 #include <Eigen/Core>
7 
8 namespace Ra {
9 namespace Core {
16 template <typename T, uint D>
17 class Grid
18 {
19 
20  public:
21  // public types and constants.
22  static const uint Dimension = D;
23  using IdxVector =
24  Eigen::Matrix<uint, D, 1>;
25  using OffsetVector = Eigen::Matrix<int, D, 1>;
26 
29  class Iterator
30  {
31  public:
32  //
33  // Construction
34  //
35 
37  explicit Iterator( const IdxVector& size, uint startIdx = 0 );
38 
40  Iterator( const IdxVector& size, const IdxVector& startIdx );
41 
43  explicit Iterator( const Grid<T, D>& grid, uint startIdx = 0 );
44 
46  Iterator( const Grid<T, D>& grid, const IdxVector& startIdx );
47 
49  Iterator( const Iterator& other ) = default;
50  Iterator& operator=( const Iterator& other ) = default;
51 
53  template <typename T2>
54  typename Grid<T2, D>::Iterator cast() const;
55 
56  //
57  // Basic getters and setters
58  //
59 
61  inline void setFromLinear( uint idx );
62 
64  inline void setFromVector( const IdxVector& idx );
65 
67  inline uint getLinear() const;
68 
70  inline IdxVector getVector() const;
71 
73  inline const IdxVector& getGridSize() const;
74 
76  inline bool isOut() const;
77 
79  inline bool isIn() const;
80 
81  //
82  // Increment and decrement operators
83  //
84 
86  inline Iterator& operator++();
87  inline Iterator operator++( int );
88 
90  inline Iterator& operator--();
91  inline Iterator operator--( int );
92 
93  //
94  // Add and substract operators with linear offset
95  //
96 
98  inline Iterator& operator+=( uint i );
99 
101  inline Iterator& operator-=( uint i );
102 
103  //
104  // Add and substract operators with vector offset
105  //
106 
107  // Note : these convenience functions do not do any kind
108  // of check. If you get out of bounds on one dimension, the iterator
109  // might still be valid but not pointing to the element you think
110  // it should.
111 
112  inline Iterator& operator+=( const IdxVector& idx );
113  inline Iterator& operator-=( const IdxVector& idx );
114  inline Iterator& operator+=( const OffsetVector& idx );
115 
118  bool isValidOffset( const OffsetVector& idx );
119 
120  //
121  // Comparison operators
122  //
123 
124  // Note : comparing iterators of different grid sizes will assert.
125 
126  inline bool operator==( const Iterator& other ) const;
127  inline bool operator<( const Iterator& other ) const;
128 
129  //
130  // Extra operators
131  //
132 
133  // Declare binary operators directly (see C++ faq 35.16)
134  friend Iterator operator+( const Iterator& it, uint i ) {
135  Iterator copy( it );
136  return copy += i;
137  }
138  friend Iterator operator-( const Iterator& it, uint i ) {
139  Iterator copy( it );
140  return copy -= i;
141  }
142  friend Iterator operator+( const Iterator& it, const IdxVector& idx ) {
143  Iterator copy( it );
144  return copy += idx;
145  }
146  friend Iterator operator-( const Iterator& it, const IdxVector& idx ) {
147  Iterator copy( it );
148  return copy -= idx;
149  }
150  friend Iterator operator+( const Iterator& it, const OffsetVector& idx ) {
151  Iterator copy( it );
152  return copy += idx;
153  }
154 
155  // Extraneous comparison operators default implementation.
156  inline bool operator!=( const Iterator& rhs ) const { return !( *this == rhs ); }
157  inline bool operator>( const Iterator& rhs ) const { return rhs < *this; }
158  inline bool operator<=( const Iterator& rhs ) const { return !( *this > rhs ); }
159  inline bool operator>=( const Iterator& rhs ) const { return !( *this < rhs ); }
160 
161  private:
162  const IdxVector& m_sizes;
163  uint m_index;
164  };
165 
166  public:
167  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
168 
169  //
170  // Constructors
171  //
172 
174  Grid( const IdxVector& size = IdxVector::Zero(), const T& val = T() );
176  Grid( const IdxVector& size, const T* values );
177 
179  Grid( const Grid<T, D>& other ) = default;
180  Grid& operator=( const Grid<T, D>& other ) = default;
181 
182  //
183  // Basic getters
184  //
185 
187  inline uint size() const;
189  inline const IdxVector& sizeVector() const;
191  inline bool empty() const;
193  inline void clear();
194 
195  //
196  // Element access
197  //
198 
200  // Note that since initializer lists are implicitly convertible to
201  // Eigen vectors, you can call grid.at({x,y,z})
202  inline const T& at( const IdxVector& idx ) const;
203  inline T& at( const IdxVector& idx );
204 
206  inline const T& at( uint idx ) const;
207  inline T& at( uint idx );
208 
210  inline const T& at( const Iterator& it ) const;
211  inline T& at( const Iterator& it );
212 
214  inline const T* data() const;
215 
217  inline T* data();
218 
219  //
220  // std::iterators-like interface
221  //
222 
224  inline Iterator begin();
225  inline Iterator begin() const;
226 
228  inline Iterator end();
229  inline Iterator end() const;
230 
231  protected:
235  std::vector<T> m_data;
236 };
237 
238 // Anonymous helper functions to convert to/from multi-dimensional indices
239 // If we want to make the grid row-major we just need to overload these functions
240 // by reversing the loops.
241 namespace {
242 
243 template <typename T, uint D>
244 inline typename Grid<T, D>::IdxVector
245 linearToIdxVector( uint linIdx, const typename Grid<T, D>::IdxVector& size ) {
247 
248  for ( uint i = 0; i < D; ++i ) {
249  result[i] = linIdx % size[i];
250  linIdx = linIdx / size[i];
251  }
252  return result;
253 }
254 
255 template <typename T, uint D>
256 inline uint idxVectorToLinear( const typename Grid<T, D>::IdxVector& vecIdx,
257  const typename Grid<T, D>::IdxVector& size ) {
258  uint result = 0;
259  uint dimProd = 1;
260  for ( uint i = 0; i < D; ++i ) {
261  result += vecIdx[i] * dimProd;
262  dimProd *= size[i];
263  }
264  return result;
265 }
266 } // namespace
267 
268 //
269 // Constructors
270 //
271 
272 template <typename T, uint D>
273 Grid<T, D>::Grid( const typename Grid<T, D>::IdxVector& size, const T& val ) :
274  m_size( size ), m_data( size.prod(), val ) {}
275 
276 template <typename T, uint D>
277 Grid<T, D>::Grid( const typename Grid<T, D>::IdxVector& size, const T* values ) :
278  m_size( size ), m_data( size.prod(), values ) {}
279 //
280 // Vector size and data management.
281 //
282 
283 template <typename T, uint D>
284 inline uint Grid<T, D>::size() const {
285  CORE_ASSERT( m_data.size() == m_size.prod(), "Inconsistent grid size" );
286  return m_data.size();
287 }
288 
289 template <typename T, uint D>
290 inline const typename Grid<T, D>::IdxVector& Grid<T, D>::sizeVector() const {
291  CORE_ASSERT( m_data.size() == m_size.prod(), "Inconsistent grid size" );
292  return m_size;
293 }
294 
295 template <typename T, uint D>
296 inline bool Grid<T, D>::empty() const {
297  CORE_ASSERT( m_data.size() == m_size.prod(), "Inconsistent grid size" );
298  return m_data.empty();
299 }
300 
301 template <typename T, uint D>
302 inline void Grid<T, D>::clear() {
303  m_data.clear();
304  m_size = IdxVector::Zero();
305  CORE_ASSERT( empty(), "Inconsistent grid" );
306 }
307 
308 template <typename T, uint D>
309 inline const T* Grid<T, D>::data() const {
310  return m_data.data();
311 }
312 
313 template <typename T, uint D>
314 inline T* Grid<T, D>::data() {
315  return m_data.data();
316 }
317 
318 //
319 // Individual element access.
320 //
321 
322 template <typename T, uint D>
323 inline const T& Grid<T, D>::at( const typename Grid<T, D>::IdxVector& idx ) const {
324  const uint linIdx = idxVectorToLinear<T, D>( idx, sizeVector() );
325  CORE_ASSERT( linIdx < m_data.size(), "Invalid vector index" );
326  return m_data[linIdx];
327 }
328 
329 template <typename T, uint D>
330 inline T& Grid<T, D>::at( const typename Grid<T, D>::IdxVector& idx ) {
331  const uint linIdx = idxVectorToLinear<T, D>( idx, sizeVector() );
332  CORE_ASSERT( linIdx < m_data.size(), "Invalid vector index" );
333  return m_data[linIdx];
334 }
335 
336 template <typename T, uint D>
337 inline const T& Grid<T, D>::at( uint idx ) const {
338  CORE_ASSERT( idx < m_data.size(), "Invalid vector index" );
339  return m_data[idx];
340 }
341 
342 template <typename T, uint D>
343 inline T& Grid<T, D>::at( uint idx ) {
344  CORE_ASSERT( idx < m_data.size(), "Invalid vector index" );
345  return m_data[idx];
346 }
347 
348 template <typename T, uint D>
349 const T& Grid<T, D>::at( const typename Grid<T, D>::Iterator& it ) const {
350  CORE_ASSERT( it.getGridSize() == m_size, "Incompatible iterator" );
351  return at( it.getLinear() );
352 }
353 
354 template <typename T, uint D>
355 T& Grid<T, D>::at( const typename Grid<T, D>::Iterator& it ) {
356  CORE_ASSERT( it.getGridSize() == m_size, "Incompatible iterator" );
357  return at( it.getLinear() );
358 }
359 
360 //
361 // Iterators begin / end functions.
362 //
363 
364 template <typename T, uint D>
366  return Iterator( *this );
367 }
368 
369 template <typename T, uint D>
370 inline typename Grid<T, D>::Iterator Grid<T, D>::begin() const {
371  return Iterator( *this );
372 }
373 
374 template <typename T, uint D>
376  return Iterator( *this, size() );
377 }
378 
379 template <typename T, uint D>
380 inline typename Grid<T, D>::Iterator Grid<T, D>::end() const {
381  return Iterator( *this, size() );
382 }
383 
384 //
385 // Iterators construction
386 //
387 
388 template <typename T, uint D>
389 inline Grid<T, D>::Iterator::Iterator( const typename Grid<T, D>::IdxVector& size, uint startIdx ) :
390  m_sizes( size ) {
391  setFromLinear( startIdx );
392 }
393 
394 template <typename T, uint D>
395 inline Grid<T, D>::Iterator::Iterator( const typename Grid<T, D>::IdxVector& size,
396  const typename Grid<T, D>::IdxVector& startIdx ) :
397  m_sizes( size ) {
398  setFromVector( startIdx );
399 }
400 
401 template <typename T, uint D>
402 inline Grid<T, D>::Iterator::Iterator( const Grid<T, D>& grid, uint startIdx ) :
403  m_sizes( grid.sizeVector() ) {
404  setFromLinear( startIdx );
405 }
406 
407 template <typename T, uint D>
408 inline Grid<T, D>::Iterator::Iterator( const Grid<T, D>& grid,
409  const typename Grid<T, D>::IdxVector& startIdx ) :
410  m_sizes( grid.sizeVector() ) {
411  setFromVector( startIdx );
412 }
413 
414 //
415 // Basic Iterator get/set
416 //
417 
418 template <typename T, uint D>
419 inline void Grid<T, D>::Iterator::setFromLinear( uint i ) {
420  m_index = i;
421 }
422 
423 template <typename T, uint D>
424 inline void Grid<T, D>::Iterator::setFromVector( const typename Grid<T, D>::IdxVector& idx ) {
425  m_index = idxVectorToLinear<T, D>( idx, m_sizes );
426 }
427 
428 template <typename T, uint D>
429 inline uint Grid<T, D>::Iterator::getLinear() const {
430  return m_index;
431 }
432 
433 template <typename T, uint D>
435  return linearToIdxVector<T, D>( m_index, m_sizes );
436 }
437 
438 template <typename T, uint D>
439 inline bool Grid<T, D>::Iterator::isOut() const {
440  return !isIn();
441 }
442 
443 template <typename T, uint D>
444 inline bool Grid<T, D>::Iterator::isIn() const {
445  return m_index < m_sizes.prod();
446 }
447 
448 //
449 // Iterator increment and decrement
450 //
451 
452 template <typename T, uint D>
454  m_index++;
455  return *this;
456 }
457 
458 template <typename T, uint D>
460  m_index--;
461  return *this;
462 }
463 
464 template <typename T, uint D>
466  Iterator copy( *this );
467  ++( *this );
468  return copy;
469 }
470 
471 template <typename T, uint D>
473  Iterator copy( *this );
474  --( *this );
475  return copy;
476 }
477 
478 template <typename T, uint D>
480  m_index += i;
481  return *this;
482 }
483 
484 template <typename T, uint D>
486  m_index -= i;
487  return *this;
488 }
489 
490 template <typename T, uint D>
491 typename Grid<T, D>::Iterator&
493  CORE_ASSERT( isValidOffset( idx.template cast<int>() ), "Invalid offset vector." );
494  setFromVector( getVector() + idx );
495  return *this;
496 }
497 
498 template <typename T, uint D>
499 typename Grid<T, D>::Iterator&
501  CORE_ASSERT( isValidOffset( -( idx.template cast<int>() ) ), "Invalid offset vector." );
502  setFromVector( getVector() - idx );
503  return *this;
504 }
505 
506 template <typename T, uint D>
507 typename Grid<T, D>::Iterator&
509  CORE_ASSERT( isValidOffset( idx ), "Invalid offset vector" );
510  setFromVector( ( getVector().template cast<int>() + idx ).template cast<uint>() );
511  return *this;
512 }
513 
514 template <typename T, uint D>
515 bool Grid<T, D>::Iterator::operator==( const typename Grid<T, D>::Iterator& other ) const {
516  CORE_ASSERT( m_sizes == other.m_sizes, "Comparing unrelated grid iterators" );
517  return m_index == other.m_index;
518 }
519 
520 template <typename T, uint D>
521 bool Grid<T, D>::Iterator::operator<( const typename Grid<T, D>::Iterator& other ) const {
522  CORE_ASSERT( m_sizes == other.m_sizes, "Comparing unrelated grid iterators" );
523  return m_index < other.m_index;
524 }
525 
526 template <typename T, uint D>
528  return m_sizes;
529 }
530 
531 template <typename T, uint D>
532 template <typename T2>
534  return typename Grid<T2, D>::Iterator( m_sizes, m_index );
535 }
536 
537 template <typename T, uint D>
539  OffsetVector pos = getVector().template cast<int>() + idx;
540  return !( ( pos.array() < 0 ).any() ||
541  ( pos.array() >= m_sizes.template cast<int>().array() ).any() );
542 }
543 
544 } // namespace Core
545 } // namespace Ra
A vector of signed offsets.
Definition: Grid.hpp:30
IdxVector getVector() const
Get the current vector index.
Definition: Grid.hpp:434
Iterator & operator++()
Advance the iterator to the next-element.
Definition: Grid.hpp:453
void setFromLinear(uint idx)
Set an existing iterator to a linear index value.
Definition: Grid.hpp:419
bool isOut() const
Returns true if the current index is out of the grid.
Definition: Grid.hpp:439
void setFromVector(const IdxVector &idx)
Set an existing iterator to a vector index value.
Definition: Grid.hpp:424
const IdxVector & getGridSize() const
Get the associated grid size.
Definition: Grid.hpp:527
bool isValidOffset(const OffsetVector &idx)
Definition: Grid.hpp:538
Iterator(const Iterator &other)=default
Default copy constructor and assignment operator.
Grid< T2, D >::Iterator cast() const
Cast to the an iterator in a different type grid.
Definition: Grid.hpp:533
Iterator & operator-=(uint i)
Rewind the iterator with an offset of i elements.
Definition: Grid.hpp:485
Iterator & operator+=(uint i)
Advance the iterator with an offset of i elements.
Definition: Grid.hpp:479
Iterator(const IdxVector &size, const IdxVector &startIdx)
Constructor from size and vector index.
Iterator(const IdxVector &size, uint startIdx=0)
Constructor from size and linear index.
bool isIn() const
Returns true if the current index is inside the grid.
Definition: Grid.hpp:444
Iterator & operator--()
Move the iterator back to the previous element.
Definition: Grid.hpp:459
Iterator(const Grid< T, D > &grid, const IdxVector &startIdx)
Constructor from grid and vector index.
uint getLinear() const
Get the current linear index.
Definition: Grid.hpp:429
Iterator begin()
Get an iterator on this grid at the first element.
Definition: Grid.hpp:365
IdxVector m_size
Indicate the extends of the grid along each dimension.
Definition: Grid.hpp:233
const T & at(uint idx) const
Access an element with a linear index.
Definition: Grid.hpp:337
Grid(const Grid< T, D > &other)=default
Copy constructor and assignment operator.
Grid(const IdxVector &size, const T *values)
Construct a grid of a given size with values in ()-major format.
T * data()
Read-write access to the underlying data.
Definition: Grid.hpp:314
void clear()
Erases all data and makes the grid empty.
Definition: Grid.hpp:302
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Grid(const IdxVector &size=IdxVector::Zero(), const T &val=T())
Construct a grid of a given size and fill it with the given value.
const IdxVector & sizeVector() const
Returns the size vector (a D-dimensional vector with the size along each dimension).
Definition: Grid.hpp:290
const T * data() const
Read only access to the underlying data.
Definition: Grid.hpp:309
Eigen::Matrix< int, D, 1 > OffsetVector
A vector of the size of the grid along each dimension.
Definition: Grid.hpp:25
bool empty() const
Returns true if the grid is empty (i.e. if size() ==0).
Definition: Grid.hpp:296
Eigen::Matrix< uint, D, 1 > IdxVector
Dimension of our grid.
Definition: Grid.hpp:24
const T & at(const IdxVector &idx) const
Access an element with a D-dimensional index.
std::vector< T > m_data
Storage for the grid data.
Definition: Grid.hpp:235
uint size() const
Returns the number of elements stored.
Definition: Grid.hpp:284
const T & at(const Iterator &it) const
Access an element with an iterator.
Iterator end()
Get an iterator on this grid past the last element.
Definition: Grid.hpp:375
Definition: Cage.cpp:3