// File: crn_vector2d.h #pragma once namespace crnlib { template class vector2D { public: typedef crnlib::vector vector_type; typedef T value_type; typedef T& reference; typedef const T& const_reference; typedef T* pointer; typedef const T* const_pointer; inline vector2D(uint width = 0, uint height = 0, const T& def = T()) : m_width(width), m_height(height), m_vec(width * height), m_def(def) { } inline vector2D(const vector2D& other) : m_width(other.m_width), m_height(other.m_height), m_vec(other.m_vec), m_def(other.m_def) { } inline vector2D& operator= (const vector2D& rhs) { if (this == &rhs) return *this; m_width = rhs.m_width; m_height = rhs.m_height; m_vec = rhs.m_vec; return *this; } bool try_resize(uint width, uint height, bool preserve = true) { if ((width == m_width) && (height == m_height)) return true; vector_type new_vec; if (!new_vec.try_resize(width * height)) return false; if (preserve) { const uint nx = math::minimum(width, m_width); const uint ny = math::minimum(height, m_height); for (uint y = 0; y < ny; y++) { const T* pSrc = &m_vec[y * m_width]; T* pDst = &new_vec[y * width]; if (CRNLIB_IS_BITWISE_COPYABLE_OR_MOVABLE(T)) memcpy(pDst, pSrc, nx * sizeof(T)); else { for (uint x = 0; x < nx; x++) *pDst++ = *pSrc++; } } } m_width = width; m_height = height; m_vec.swap(new_vec); return true; } void resize(uint width, uint height, bool preserve = true) { if (!try_resize(width, height, preserve)) { CRNLIB_FAIL("vector2D::resize: Out of memory"); } } inline void clear() { m_vec.clear(); m_width = 0; m_height = 0; } inline uint width() const { return m_width; } inline uint height() const { return m_height; } inline uint size() const { return m_vec.size(); } inline uint size_in_bytes() const { return m_vec.size() * sizeof(T); } const vector_type& get_vec() const { return m_vec; } vector_type& get_vec() { return m_vec; } inline const T* get_ptr() const { return m_vec.get_ptr(); } inline T* get_ptr() { return m_vec.get_ptr(); } inline const T& operator[] (uint i) const { return m_vec[i]; } inline T& operator[] (uint i) { return m_vec[i]; } inline const T& operator() (uint x, uint y) const { CRNLIB_ASSERT((x < m_width) && (y < m_height)); return m_vec[x + y * m_width]; } inline T& operator() (uint x, uint y) { CRNLIB_ASSERT((x < m_width) && (y < m_height)); return m_vec[x + y * m_width]; } inline const T& at (uint x, uint y) const { if ((x >= m_width) || (y >= m_height)) return m_def; return m_vec[x + y * m_width]; } inline T& at (uint x, uint y) { if ((x >= m_width) || (y >= m_height)) return m_def; return m_vec[x + y * m_width]; } inline void swap(vector2D& other) { m_vec.swap(other.m_vec); anvil::swap(m_width, other.m_width); anvil::swap(m_height, other.m_height); } inline void set_all(const T& x) { m_vec.set_all(x); } private: vector_type m_vec; uint m_width; uint m_height; T m_def; }; } // namespace anvil