// // Canvas.hpp // AwesomeAttractorND // // Created by Joshua Moerman on 10/28/11. // Copyright 2011 Vadovas. All rights reserved. // /* Interface (or Concept) Canvas: Canvas canvas(width, height, ...); Constructs a Canvas with given dimensions canvas[x][y]...[z] Returns a (const) reference to an element canvas.plot(position) Plots on the canvas (where position is normalized, ie in the unit-cube) canvas.size() gives width/size for the given dimension N. canvas.begin() .end() gives iterators to the elements (directly) */ #ifndef AwesomeAttractorND_Canvas_hpp #define AwesomeAttractorND_Canvas_hpp #include #include #include #include template class Canvas2D { typedef T value_type; typedef std::vector Row; typedef std::vector Storage; public: static constexpr size_t dimension = 2; static constexpr bool layered = false; Canvas2D(size_t width, size_t height) : storage(height, Row(width, 0)) {} Row & operator[](size_t r){ return storage[r]; } Row const & operator[](size_t r) const { return storage[r]; } void plot(double const * const position){ const size_t width = size<0>(); const size_t height = size<1>(); const int c = 0.5*position[0]*width + width*.5; const int r = 0.5*position[1]*width + height*.5; if(0 <= c && (size_t)c < width && 0 <= r && (size_t)r < height) storage[r][c]++; } size_t size() const { return size<0>() * size<1>(); } template size_t size() const { if ( N == 0 ) return storage.front().size(); if ( N == 1 ) return storage.size(); return 0; } struct iterator; iterator begin(){ return iterator(this); } iterator end(){ return iterator(this, 0, size<1>()); }; struct const_iterator; const_iterator begin() const { return const_iterator(this); } const_iterator end() const { return const_iterator(this, 0, size<1>()); } const_iterator cbegin() const { return const_iterator(this); } const_iterator cend() const { return const_iterator(this, 0, size<1>()); } struct iterator : public std::iterator { iterator(iterator const & rh) : canvas(rh.canvas) , c(rh.c) , r(rh.r) {} iterator & operator++(){ ++c; if (c >= canvas->size<0>()) { c = 0; ++r; } return *this; } iterator operator++(int){ iterator temp(*this); ++(*this); return temp; } bool operator==(iterator const & rh) const { return canvas == rh.canvas && c == rh.c && r == rh.r; } bool operator!=(iterator const & rh) const { return canvas != rh.canvas || c != rh.c || r != rh.r; } value_type & operator*(){ return (*canvas)[r][c]; } value_type const & operator*() const { return (*canvas)[r][c]; } value_type & operator->(){ return (*canvas)[r][c]; } value_type const & operator->() const { return (*canvas)[r][c]; } private: friend class Canvas2D; iterator(Canvas2D * canvas, size_t c = 0, size_t r = 0) : canvas(canvas) , c(c) , r(r) {} iterator(); Canvas2D * canvas; size_t c; size_t r; }; struct const_iterator : public std::iterator { const_iterator(const_iterator const & rh) : canvas(rh.canvas) , c(rh.c) , r(rh.r) {} const_iterator & operator++(){ ++c; if (c >= canvas->size<0>()) { c = 0; ++r; } return *this; } const_iterator operator++(int){ const_iterator temp(*this); ++(*this); return temp; } bool operator==(const_iterator const & rh) const { return canvas == rh.canvas && c == rh.c && r == rh.r; } bool operator!=(const_iterator const & rh) const { return canvas != rh.canvas || c != rh.c || r != rh.r; } value_type const & operator*() const { return (*canvas)[r][c]; } value_type const & operator->() const { return (*canvas)[r][c]; } private: friend class Canvas2D; const_iterator(Canvas2D const * canvas, size_t c = 0, size_t r = 0) : canvas(canvas) , c(c) , r(r) {} const_iterator(); Canvas2D const * canvas; size_t c; size_t r; }; private: Storage storage; }; template class LayeredCanvas { public: static constexpr size_t dimension = Canvas::dimension; static constexpr bool layered = true; LayeredCanvas(size_t width, size_t height, size_t layers) : canvae(layers, Canvas(width, height)) {} Canvas & operator[](size_t layer){ return canvae[layer]; } Canvas const & operator[](size_t layer) const { return canvae[layer]; } size_t layers() const { return canvae.size(); } size_t size() const { return canvae.front().size(); } template size_t size() const { return canvae.front().size(); } void plot(double const * position, size_t layer){ canvae[layer].plot(position); } private: std::vector canvae; }; template typename std::enable_if::type filled(C const & canvas, double threshold) { struct functor { size_t operator()(size_t x, size_t y){ if(y > 0) return ++x; else return x; } } f; size_t nonempty_pixels = std::accumulate(canvas.begin(), canvas.end(), 0ul, f); return nonempty_pixels > threshold * canvas.size(); } template typename std::enable_if::type filled(C const & canvas, double threshold) { for (unsigned int l = 0; l < canvas.layers(); ++l) { if (!filled(canvas[l], threshold)) { return false; } } return true; } #endif