Gamedev Framework (gf)  0.5.0
A C++11 framework for 2D games
Array2D.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2017 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 #ifndef ARRAY2D_H
22 #define ARRAY2D_H
23 
24 #include <cassert>
25 #include <type_traits>
26 #include <utility>
27 #include <vector>
28 
29 #include "Log.h"
30 
31 #include "Math.h"
32 #include "Portability.h"
33 #include "Range.h"
34 #include "Vector.h"
35 
36 namespace gf {
37 #ifndef DOXYGEN_SHOULD_SKIP_THIS
38 inline namespace v1 {
39 #endif
40 
59  template<typename T, typename I = unsigned>
60  class Array2D {
61  public:
68  : m_size(0, 0)
69  {
70 
71  }
72 
79  : m_size(size)
80  , m_data(size.width * size.height)
81  {
82 
83  }
84 
91  Array2D(Vector<I, 2> size, const T& value)
92  : m_size(size)
93  , m_data(size.width * size.height, value)
94  {
95 
96  }
97 
101  Array2D(const Array2D&) = default;
102 
106  Array2D& operator=(const Array2D&) = default;
107 
111  Array2D(Array2D&&) = default;
112 
116  Array2D& operator=(Array2D&&) = default;
117 
123  void swap(Array2D& other) {
124  std::swap(m_data, other.m_data);
125  std::swap(m_size, other.m_size);
126  }
127 
141  const T *getDataPtr() const noexcept {
142  return m_data.data();
143  }
144 
150  std::size_t getDataSize() const noexcept {
151  return m_data.size();
152  }
153 
159  constexpr Vector<I, 2> getSize() const noexcept {
160  return m_size;
161  }
162 
168  constexpr unsigned getCols() const noexcept {
169  return m_size.col;
170  }
171 
177  constexpr unsigned getRows() const noexcept {
178  return m_size.row;
179  }
180 
189  constexpr bool isEmpty() const noexcept {
190  return m_data.empty();
191  }
192 
200  constexpr bool isValid(Vector<I, 2> pos) const noexcept {
201  return pos.col < m_size.col && pos.row < m_size.row && (std::is_unsigned<I>::value || (0 <= pos.col && 0 <= pos.row));
202  }
203 
217  return get(pos);
218  }
219 
226  T& operator()(std::size_t pos) {
227  return m_data[pos];
228  }
229 
235  const T& operator()(Vector<I, 2> pos) const {
236  return get(pos);
237  }
238 
245  const T& operator()(std::size_t pos) const {
246  return m_data[pos];
247  }
248 
255  constexpr Vector<I, 2> toPosition(std::size_t pos) const noexcept {
256  return { pos % m_size.col, pos / m_size.col };
257  }
258 
287  template<typename Func>
288  void visit4Neighbors(Vector<I, 2> pos, Func func) {
289  visitNeighborsDiamond(pos, func, 1);
290  }
291 
313  template<typename Func>
314  void visit4Neighbors(Vector<I, 2> pos, Func func) const {
315  visitNeighborsDiamond(pos, func, 1);
316  }
317 
339  template<typename Func>
340  void visit12Neighbors(Vector<I, 2> pos, Func func) {
341  visitNeighborsDiamond(pos, func, 2);
342  }
343 
365  template<typename Func>
366  void visit12Neighbors(Vector<I, 2> pos, Func func) const {
367  visitNeighborsDiamond(pos, func, 2);
368  }
369 
391  template<typename Func>
392  void visit8Neighbors(Vector<I, 2> pos, Func func) {
393  visitNeighborsSquare(pos, func, 1);
394  }
395 
419  template<typename Func>
420  void visit8Neighbors(Vector<I, 2> pos, Func func) const {
421  visitNeighborsSquare(pos, func, 1);
422  }
423 
445  template<typename Func>
446  void visit24Neighbors(Vector<I, 2> pos, Func func) {
447  visitNeighborsSquare(pos, func, 2);
448  }
449 
471  template<typename Func>
472  void visit24Neighbors(Vector<I, 2> pos, Func func) const {
473  visitNeighborsSquare(pos, func, 2);
474  }
475 
489  const T *begin() const noexcept {
490  return m_data.data();
491  }
492 
499  const T *end() const noexcept {
500  return m_data.data() + m_data.size();
501  }
502 
509  T *begin() noexcept {
510  return m_data.data();
511  }
512 
519  T *end() noexcept {
520  return m_data.data() + m_data.size();
521  }
522 
528  constexpr RangeZ getPositionRange() const noexcept {
529  return { 0, m_size.col * m_size.row };
530  }
531 
537  constexpr RangeU getRowRange() const noexcept {
538  return { 0, m_size.row };
539  }
540 
546  constexpr RangeU getColRange() const noexcept {
547  return { 0, m_size.col };
548  }
549 
552  private:
553  T& get(Vector<I, 2> pos) {
554  return m_data[pos.row * m_size.col + pos.col];
555  }
556 
557  const T& get(Vector<I, 2> pos) const {
558  return m_data[pos.row * m_size.col + pos.col];
559  }
560 
561  template<typename Func>
562  void visitNeighborsSquare(Vector<I, 2> pos, Func func, unsigned n) const {
563  assert(isValid(pos));
564 
565  unsigned colMin = pos.col - std::min(pos.col, n);
566  unsigned colMax = pos.col + std::min(m_size.col - pos.col - 1, n);
567  unsigned rowMin = pos.row - std::min(pos.row, n);
568  unsigned rowMax = pos.row + std::min(m_size.row - pos.row - 1, n);
569 
570  for (unsigned row = rowMin; row <= rowMax; ++row) {
571  for (unsigned col = colMin; col <= colMax; ++col) {
572  if (col == pos.col && row == pos.row) { // avoid to include VectorOps.h
573  continue;
574  }
575 
576  func({ col, row }, get({ col, row }));
577  }
578  }
579  }
580 
581  template<typename Func>
582  void visitNeighborsSquare(Vector<I, 2> pos, Func func, unsigned n) {
583  assert(isValid(pos));
584 
585  unsigned colMin = pos.col - std::min(pos.col, n);
586  unsigned colMax = pos.col + std::min(m_size.col - pos.col - 1, n);
587  unsigned rowMin = pos.row - std::min(pos.row, n);
588  unsigned rowMax = pos.row + std::min(m_size.row - pos.row - 1, n);
589 
590  for (unsigned row = rowMin; row <= rowMax; ++row) {
591  for (unsigned col = colMin; col <= colMax; ++col) {
592  if (col == pos.col && row == pos.row) { // avoid to include VectorOps.h
593  continue;
594  }
595 
596  func({ col, row }, get({ col, row }));
597  }
598  }
599  }
600 
601 
602  template<typename Func>
603  void visitNeighborsDiamond(Vector<I, 2> pos, Func func, unsigned n) const {
604  assert(isValid(pos));
605 
606  unsigned colMin = pos.col - std::min(pos.col, n);
607  unsigned colMax = pos.col + std::min(m_size.col - pos.col - 1, n);
608  unsigned rowMin = pos.row - std::min(pos.row, n);
609  unsigned rowMax = pos.row + std::min(m_size.row - pos.row - 1, n);
610 
611  for (unsigned row = rowMin; row <= rowMax; ++row) {
612  for (unsigned col = colMin; col <= colMax; ++col) {
613  if (col == pos.col && row == pos.row) { // avoid to include VectorOps.h
614  continue;
615  }
616 
617  if (gf::absdiff(col, pos.col) + gf::absdiff(row, pos.row) > n) {
618  continue;
619  }
620 
621  func({ col, row }, get({ col, row }));
622  }
623  }
624  }
625 
626  template<typename Func>
627  void visitNeighborsDiamond(Vector<I, 2> pos, Func func, unsigned n) {
628  assert(isValid(pos));
629 
630  unsigned colMin = pos.col - std::min(pos.col, n);
631  unsigned colMax = pos.col + std::min(m_size.col - pos.col - 1, n);
632  unsigned rowMin = pos.row - std::min(pos.row, n);
633  unsigned rowMax = pos.row + std::min(m_size.row - pos.row - 1, n);
634 
635  for (unsigned row = rowMin; row <= rowMax; ++row) {
636  for (unsigned col = colMin; col <= colMax; ++col) {
637  if (col == pos.col && row == pos.row) { // avoid to include VectorOps.h
638  continue;
639  }
640 
641  if (gf::absdiff(col, pos.col) + gf::absdiff(row, pos.row) > n) {
642  continue;
643  }
644 
645  func({ col, row }, get({ col, row }));
646  }
647  }
648  }
649 
650  private:
651  Vector<I, 2> m_size;
652  std::vector<T> m_data;
653  };
654 
655 #ifndef DOXYGEN_SHOULD_SKIP_THIS
656 }
657 #endif
658 }
659 
660 #endif // ARRAY2D_H
A two-dimensional array.
Definition: Array2D.h:60
A half-open range of values.
Definition: Range.h:42
T * end() noexcept
Get an iterator to the element following the last element of the array.
Definition: Array2D.h:519
constexpr RangeU getRowRange() const noexcept
Get the row range.
Definition: Array2D.h:537
constexpr unsigned getCols() const noexcept
Get the number of columns.
Definition: Array2D.h:168
const T * begin() const noexcept
Get an iterator to the first element of the array.
Definition: Array2D.h:489
const T * getDataPtr() const noexcept
Get the pointer to raw data.
Definition: Array2D.h:141
std::size_t getDataSize() const noexcept
Get the raw data size.
Definition: Array2D.h:150
void swap(Array2D &other)
Swap with another array.
Definition: Array2D.h:123
constexpr T absdiff(T lhs, T rhs)
Absolute difference of two values.
Definition: Math.h:313
void visit4Neighbors(Vector< I, 2 > pos, Func func) const
Visit the 4 neighbors of a given position.
Definition: Array2D.h:314
void visit12Neighbors(Vector< I, 2 > pos, Func func) const
Visit the 12 neighbors of a given position.
Definition: Array2D.h:366
constexpr RangeU getColRange() const noexcept
Get the column range.
Definition: Array2D.h:546
constexpr Vector< I, 2 > toPosition(std::size_t pos) const noexcept
Transform a 1D position into a 2D position.
Definition: Array2D.h:255
void visit24Neighbors(Vector< I, 2 > pos, Func func) const
Visit the 24 neighbors of a given position.
Definition: Array2D.h:472
void visit8Neighbors(Vector< I, 2 > pos, Func func) const
Visit the 8 neighbors of a given position.
Definition: Array2D.h:420
The namespace for gf classes.
Definition: Action.h:34
Array2D()
Default constructor.
Definition: Array2D.h:67
Array2D(Vector< I, 2 > size)
Constructor with a size.
Definition: Array2D.h:78
constexpr bool isValid(Vector< I, 2 > pos) const noexcept
Check if a position is valid.
Definition: Array2D.h:200
void visit24Neighbors(Vector< I, 2 > pos, Func func)
Visit the 24 neighbors of a given position.
Definition: Array2D.h:446
T & operator()(Vector< I, 2 > pos)
Get the element at a given 2D position.
Definition: Array2D.h:216
constexpr bool isEmpty() const noexcept
Check if the array is empty.
Definition: Array2D.h:189
constexpr RangeZ getPositionRange() const noexcept
Get the 1D position range of the array.
Definition: Array2D.h:528
constexpr Vector< I, 2 > getSize() const noexcept
Get the size of the array.
Definition: Array2D.h:159
T & operator()(std::size_t pos)
Get the element at a given 1D position.
Definition: Array2D.h:226
T * begin() noexcept
Get an iterator to the first element of the array.
Definition: Array2D.h:509
Array2D(Vector< I, 2 > size, const T &value)
Constructor with a size and a value.
Definition: Array2D.h:91
const T & operator()(std::size_t pos) const
Get the element at a given 1D position.
Definition: Array2D.h:245
const T & operator()(Vector< I, 2 > pos) const
Get the element at a given 2D position.
Definition: Array2D.h:235
constexpr unsigned getRows() const noexcept
Get the number of rows.
Definition: Array2D.h:177
void visit12Neighbors(Vector< I, 2 > pos, Func func)
Visit the 12 neighbors of a given position.
Definition: Array2D.h:340
void visit8Neighbors(Vector< I, 2 > pos, Func func)
Visit the 8 neighbors of a given position.
Definition: Array2D.h:392
void visit4Neighbors(Vector< I, 2 > pos, Func func)
Visit the 4 neighbors of a given position.
Definition: Array2D.h:288
const T * end() const noexcept
Get an iterator to the element following the last element of the array.
Definition: Array2D.h:499