My old project for strange attractors
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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 

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