Gamedev Framework (gf)  0.7.0
A C++14 framework for 2D games
Array2D.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2018 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 
62  template<typename T, typename I = unsigned>
63  class Array2D {
64  public:
71  : m_size(0, 0)
72  {
73 
74  }
75 
82  : m_size(size)
83  , m_data(size.width * size.height)
84  {
85 
86  }
87 
94  Array2D(Vector<I, 2> size, const T& value)
95  : m_size(size)
96  , m_data(size.width * size.height, value)
97  {
98 
99  }
100 
104  Array2D(const Array2D&) = default;
105 
109  Array2D& operator=(const Array2D&) = default;
110 
114  Array2D(Array2D&&) = default;
115 
119  Array2D& operator=(Array2D&&) = default;
120 
126  void swap(Array2D& other) {
127  std::swap(m_data, other.m_data);
128  std::swap(m_size, other.m_size);
129  }
130 
144  const T *getDataPtr() const noexcept {
145  return m_data.data();
146  }
147 
153  std::size_t getDataSize() const noexcept {
154  return m_data.size();
155  }
156 
162  constexpr Vector<I, 2> getSize() const noexcept {
163  return m_size;
164  }
165 
171  constexpr I getCols() const noexcept {
172  return m_size.col;
173  }
174 
180  constexpr I getRows() const noexcept {
181  return m_size.row;
182  }
183 
192  constexpr bool isEmpty() const noexcept {
193  return m_data.empty();
194  }
195 
203  constexpr bool isValid(Vector<I, 2> pos) const noexcept {
204  return pos.col < m_size.col && pos.row < m_size.row && (std::is_unsigned<I>::value || (0 <= pos.col && 0 <= pos.row));
205  }
206 
220  return get(pos);
221  }
222 
229  T& operator()(std::size_t index) {
230  return m_data[index];
231  }
232 
238  const T& operator()(Vector<I, 2> pos) const {
239  return get(pos);
240  }
241 
248  const T& operator()(std::size_t index) const {
249  return m_data[index];
250  }
251 
258  constexpr Vector<I, 2> toPosition(std::size_t pos) const noexcept {
259  return { pos % m_size.col, pos / m_size.col };
260  }
261 
290  template<typename Func>
291  void visit4Neighbors(Vector<I, 2> pos, Func func) {
292  visitNeighborsDiamond(pos, func, 1);
293  }
294 
316  template<typename Func>
317  void visit4Neighbors(Vector<I, 2> pos, Func func) const {
318  visitNeighborsDiamond(pos, func, 1);
319  }
320 
342  template<typename Func>
343  void visit12Neighbors(Vector<I, 2> pos, Func func) {
344  visitNeighborsDiamond(pos, func, 2);
345  }
346 
368  template<typename Func>
369  void visit12Neighbors(Vector<I, 2> pos, Func func) const {
370  visitNeighborsDiamond(pos, func, 2);
371  }
372 
394  template<typename Func>
395  void visit8Neighbors(Vector<I, 2> pos, Func func) {
396  visitNeighborsSquare(pos, func, 1);
397  }
398 
422  template<typename Func>
423  void visit8Neighbors(Vector<I, 2> pos, Func func) const {
424  visitNeighborsSquare(pos, func, 1);
425  }
426 
448  template<typename Func>
449  void visit24Neighbors(Vector<I, 2> pos, Func func) {
450  visitNeighborsSquare(pos, func, 2);
451  }
452 
474  template<typename Func>
475  void visit24Neighbors(Vector<I, 2> pos, Func func) const {
476  visitNeighborsSquare(pos, func, 2);
477  }
478 
492  const T *begin() const noexcept {
493  return m_data.data();
494  }
495 
502  const T *end() const noexcept {
503  return m_data.data() + m_data.size();
504  }
505 
512  T *begin() noexcept {
513  return m_data.data();
514  }
515 
522  T *end() noexcept {
523  return m_data.data() + m_data.size();
524  }
525 
531  constexpr RangeZ getIndexRange() const noexcept {
532  return { 0, m_size.col * m_size.row };
533  }
534 
540  constexpr Range<I> getRowRange() const noexcept {
541  return { 0, m_size.row };
542  }
543 
549  constexpr Range<I> getColRange() const noexcept {
550  return { 0, m_size.col };
551  }
552 
558  constexpr PositionRange<I> getPositionRange() const noexcept {
559  return { getColRange(), getRowRange() };
560  }
561 
564  private:
565  T& get(Vector<I, 2> pos) {
566  return m_data[pos.row * m_size.col + pos.col];
567  }
568 
569  const T& get(Vector<I, 2> pos) const {
570  return m_data[pos.row * m_size.col + pos.col];
571  }
572 
573  template<typename Func>
574  void visitNeighborsSquare(Vector<I, 2> pos, Func func, I n) const {
575  assert(isValid(pos));
576 
577  auto colMin = pos.col - std::min(pos.col, n);
578  auto colMax = pos.col + std::min(m_size.col - pos.col - 1, n);
579  auto rowMin = pos.row - std::min(pos.row, n);
580  auto rowMax = pos.row + std::min(m_size.row - pos.row - 1, n);
581 
582  for (auto row = rowMin; row <= rowMax; ++row) {
583  for (auto col = colMin; col <= colMax; ++col) {
584  if (col == pos.col && row == pos.row) { // avoid to include VectorOps.h
585  continue;
586  }
587 
588  func({ col, row }, get({ col, row }));
589  }
590  }
591  }
592 
593  template<typename Func>
594  void visitNeighborsSquare(Vector<I, 2> pos, Func func, I n) {
595  assert(isValid(pos));
596 
597  auto colMin = pos.col - std::min(pos.col, n);
598  auto colMax = pos.col + std::min(m_size.col - pos.col - 1, n);
599  auto rowMin = pos.row - std::min(pos.row, n);
600  auto rowMax = pos.row + std::min(m_size.row - pos.row - 1, n);
601 
602  for (auto row = rowMin; row <= rowMax; ++row) {
603  for (auto col = colMin; col <= colMax; ++col) {
604  if (col == pos.col && row == pos.row) { // avoid to include VectorOps.h
605  continue;
606  }
607 
608  func({ col, row }, get({ col, row }));
609  }
610  }
611  }
612 
613 
614  template<typename Func>
615  void visitNeighborsDiamond(Vector<I, 2> pos, Func func, I n) const {
616  assert(isValid(pos));
617 
618  auto colMin = pos.col - std::min(pos.col, n);
619  auto colMax = pos.col + std::min(m_size.col - pos.col - 1, n);
620  auto rowMin = pos.row - std::min(pos.row, n);
621  auto rowMax = pos.row + std::min(m_size.row - pos.row - 1, n);
622 
623  for (auto row = rowMin; row <= rowMax; ++row) {
624  for (auto col = colMin; col <= colMax; ++col) {
625  if (col == pos.col && row == pos.row) { // avoid to include VectorOps.h
626  continue;
627  }
628 
629  if (gf::absdiff(col, pos.col) + gf::absdiff(row, pos.row) > n) {
630  continue;
631  }
632 
633  func({ col, row }, get({ col, row }));
634  }
635  }
636  }
637 
638  template<typename Func>
639  void visitNeighborsDiamond(Vector<I, 2> pos, Func func, I n) {
640  assert(isValid(pos));
641 
642  auto colMin = pos.col - std::min(pos.col, n);
643  auto colMax = pos.col + std::min(m_size.col - pos.col - 1, n);
644  auto rowMin = pos.row - std::min(pos.row, n);
645  auto rowMax = pos.row + std::min(m_size.row - pos.row - 1, n);
646 
647  for (auto row = rowMin; row <= rowMax; ++row) {
648  for (auto col = colMin; col <= colMax; ++col) {
649  if (col == pos.col && row == pos.row) { // avoid to include VectorOps.h
650  continue;
651  }
652 
653  if (gf::absdiff(col, pos.col) + gf::absdiff(row, pos.row) > n) {
654  continue;
655  }
656 
657  func({ col, row }, get({ col, row }));
658  }
659  }
660  }
661 
662  private:
663  Vector<I, 2> m_size;
664  std::vector<T> m_data;
665  };
666 
667 #ifndef DOXYGEN_SHOULD_SKIP_THIS
668 }
669 #endif
670 }
671 
672 #endif // ARRAY2D_H
A two-dimensional array.
Definition: Array2D.h:63
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:522
const T * begin() const noexcept
Get an iterator to the first element of the array.
Definition: Array2D.h:492
const T * getDataPtr() const noexcept
Get the pointer to raw data.
Definition: Array2D.h:144
std::size_t getDataSize() const noexcept
Get the raw data size.
Definition: Array2D.h:153
void swap(Array2D &other)
Swap with another array.
Definition: Array2D.h:126
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:317
constexpr Range< I > getRowRange() const noexcept
Get the row range.
Definition: Array2D.h:540
constexpr PositionRange< I > getPositionRange() const noexcept
Get the position range.
Definition: Array2D.h:558
void visit12Neighbors(Vector< I, 2 > pos, Func func) const
Visit the 12 neighbors of a given position.
Definition: Array2D.h:369
constexpr I getCols() const noexcept
Get the number of columns.
Definition: Array2D.h:171
constexpr Vector< I, 2 > toPosition(std::size_t pos) const noexcept
Transform a 1D position into a 2D position.
Definition: Array2D.h:258
void visit24Neighbors(Vector< I, 2 > pos, Func func) const
Visit the 24 neighbors of a given position.
Definition: Array2D.h:475
void visit8Neighbors(Vector< I, 2 > pos, Func func) const
Visit the 8 neighbors of a given position.
Definition: Array2D.h:423
The namespace for gf classes.
Definition: Action.h:34
Array2D()
Default constructor.
Definition: Array2D.h:70
Array2D(Vector< I, 2 > size)
Constructor with a size.
Definition: Array2D.h:81
constexpr bool isValid(Vector< I, 2 > pos) const noexcept
Check if a position is valid.
Definition: Array2D.h:203
void visit24Neighbors(Vector< I, 2 > pos, Func func)
Visit the 24 neighbors of a given position.
Definition: Array2D.h:449
T & operator()(Vector< I, 2 > pos)
Get the element at a given 2D position.
Definition: Array2D.h:219
const T & operator()(std::size_t index) const
Get the element at a given 1D index.
Definition: Array2D.h:248
constexpr bool isEmpty() const noexcept
Check if the array is empty.
Definition: Array2D.h:192
constexpr I getRows() const noexcept
Get the number of rows.
Definition: Array2D.h:180
constexpr Vector< I, 2 > getSize() const noexcept
Get the size of the array.
Definition: Array2D.h:162
A 2D range.
Definition: Range.h:225
constexpr Range< I > getColRange() const noexcept
Get the column range.
Definition: Array2D.h:549
T * begin() noexcept
Get an iterator to the first element of the array.
Definition: Array2D.h:512
Array2D(Vector< I, 2 > size, const T &value)
Constructor with a size and a value.
Definition: Array2D.h:94
constexpr RangeZ getIndexRange() const noexcept
Get the 1D index range of the array.
Definition: Array2D.h:531
T & operator()(std::size_t index)
Get the element at a given 1D index.
Definition: Array2D.h:229
const T & operator()(Vector< I, 2 > pos) const
Get the element at a given 2D position.
Definition: Array2D.h:238
void visit12Neighbors(Vector< I, 2 > pos, Func func)
Visit the 12 neighbors of a given position.
Definition: Array2D.h:343
void visit8Neighbors(Vector< I, 2 > pos, Func func)
Visit the 8 neighbors of a given position.
Definition: Array2D.h:395
void visit4Neighbors(Vector< I, 2 > pos, Func func)
Visit the 4 neighbors of a given position.
Definition: Array2D.h:291
const T * end() const noexcept
Get an iterator to the element following the last element of the array.
Definition: Array2D.h:502