You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
274 lines
5.5 KiB
274 lines
5.5 KiB
//
|
|
// 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<N>() 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 <vector>
|
|
#include <iterator>
|
|
#include <array>
|
|
#include <numeric>
|
|
|
|
template <typename T>
|
|
class Canvas2D {
|
|
typedef T value_type;
|
|
typedef std::vector<value_type> Row;
|
|
typedef std::vector<Row> 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 N>
|
|
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<std::forward_iterator_tag, value_type> {
|
|
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<std::forward_iterator_tag, value_type const> {
|
|
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 <typename Canvas>
|
|
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 N>
|
|
size_t size() const {
|
|
return canvae.front().size<N>();
|
|
}
|
|
|
|
void plot(double const * position, size_t layer){
|
|
canvae[layer].plot(position);
|
|
}
|
|
|
|
private:
|
|
std::vector<Canvas> canvae;
|
|
};
|
|
|
|
template <typename C>
|
|
typename std::enable_if<!C::layered, bool>::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 C>
|
|
typename std::enable_if<C::layered, bool>::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
|
|
|