Joshua Moerman
13 years ago
9 changed files with 519 additions and 310 deletions
@ -0,0 +1,75 @@ |
|||||
|
//
|
||||
|
// AttractorKernel.hpp
|
||||
|
// AwesomeAttractorND
|
||||
|
//
|
||||
|
// Created by Joshua Moerman on 11/4/11.
|
||||
|
// Copyright 2011 Vadovas. All rights reserved.
|
||||
|
//
|
||||
|
|
||||
|
#ifndef AwesomeAttractorND_AttractorKernel_hpp |
||||
|
#define AwesomeAttractorND_AttractorKernel_hpp |
||||
|
|
||||
|
#include "Vectors.hpp" |
||||
|
|
||||
|
class AttractorKernel { |
||||
|
public: |
||||
|
virtual void iterate(VectorIterator begin, VectorIterator end, VectorIterator begin2) = 0; |
||||
|
}; |
||||
|
|
||||
|
template <typename T> |
||||
|
class StaticAttractorKernel : public AttractorKernel, public T { |
||||
|
public: |
||||
|
virtual void iterate(VectorIterator begin, VectorIterator end, VectorIterator begin2){ |
||||
|
while (begin != end) { |
||||
|
T::calculate(*begin2, *begin); |
||||
|
++begin; |
||||
|
++begin2; |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct Unravel { |
||||
|
Unravel() |
||||
|
: parameters() |
||||
|
{ |
||||
|
parameters[0] = 0.761090; |
||||
|
parameters[1] = 1.426758; |
||||
|
parameters[2] = 1.516635; |
||||
|
parameters[3] = -0.02366; |
||||
|
parameters[4] = 2.398894; |
||||
|
parameters[5] = -0.32422; |
||||
|
parameters[6] = -2.12839; |
||||
|
} |
||||
|
|
||||
|
void calculate(VectorConstRef vectorOld, VectorRef vectorNew){ |
||||
|
vectorNew[0] = parameters[0]*(vectorOld[2] + parameters[1]); |
||||
|
vectorNew[1] = parameters[2]*(vectorOld[0] + parameters[3]); |
||||
|
vectorNew[2] = parameters[4]*(vectorOld[1] + parameters[5]); |
||||
|
|
||||
|
const double dist = vectorNew[0]*vectorNew[0] + vectorNew[1]*vectorNew[1] + vectorNew[2]*vectorNew[2]; |
||||
|
|
||||
|
if(dist > parameters[6]*parameters[6]) { |
||||
|
const double sqrtDist = std::sqrt(dist); |
||||
|
const double p = 1.0 - parameters[6] * (static_cast<int>(sqrtDist / parameters[6]) + 1.0) / sqrtDist; |
||||
|
vectorNew[0] *= p; |
||||
|
vectorNew[1] *= p; |
||||
|
vectorNew[2] *= p; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected: |
||||
|
std::array<double, 7> parameters; |
||||
|
static const size_t dimension = 3; |
||||
|
}; |
||||
|
|
||||
|
struct Lorenz { |
||||
|
void calculate(VectorConstRef o, VectorRef n); |
||||
|
}; |
||||
|
|
||||
|
/*
|
||||
|
IDEA: explicitly instantiate StaticAttractorKernel<Unravel>, StaticAttractorKernel<Lorenz>, ... |
||||
|
Thereby we have very little Unravel and Lorenz classes, which do only one thing. |
||||
|
And an abstract base-class. And only iterate() is virtual, thus calculate() can be inlined! |
||||
|
*/ |
||||
|
|
||||
|
#endif |
@ -0,0 +1,159 @@ |
|||||
|
//
|
||||
|
// ImageFormatBMP.hpp
|
||||
|
// AwesomeAttractorND
|
||||
|
//
|
||||
|
// Created by Joshua Moerman on 11/12/11.
|
||||
|
// Copyright 2011 Vadovas. All rights reserved.
|
||||
|
//
|
||||
|
|
||||
|
#ifndef AwesomeAttractorND_ImageFormatBMP_hpp |
||||
|
#define AwesomeAttractorND_ImageFormatBMP_hpp |
||||
|
|
||||
|
#include <ostream> |
||||
|
#include <fstream> |
||||
|
#include <stdexcept> |
||||
|
#include <algorithm> |
||||
|
|
||||
|
namespace ImageFormats { |
||||
|
namespace bmp { |
||||
|
struct pixelBGR{ |
||||
|
pixelBGR(double red, double green, double blue) |
||||
|
: blue(clamp(255*blue)) |
||||
|
, green(clamp(255*green)) |
||||
|
, red(clamp(255*red)) |
||||
|
{} |
||||
|
|
||||
|
pixelBGR(int red, int green, int blue) |
||||
|
: blue(clamp(blue)) |
||||
|
, green(clamp(green)) |
||||
|
, red(clamp(red)) |
||||
|
{} |
||||
|
|
||||
|
void swapRB(){ |
||||
|
std::swap(red, blue); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
uint8_t clamp(int n){ |
||||
|
return std::min(255, std::max(0, n)); |
||||
|
} |
||||
|
|
||||
|
uint8_t blue; |
||||
|
uint8_t green; |
||||
|
uint8_t red; |
||||
|
}; |
||||
|
|
||||
|
struct bitmap_file_header { |
||||
|
uint32_t filesize; |
||||
|
uint16_t creator1; |
||||
|
uint16_t creator2; |
||||
|
uint32_t bmp_offset; |
||||
|
|
||||
|
template <typename DIBT> |
||||
|
bitmap_file_header(DIBT dib_header): |
||||
|
filesize(dib_header.bytes() + dib_header.header_sz + 12 + 2), |
||||
|
creator1(0), |
||||
|
creator2(0), |
||||
|
bmp_offset(dib_header.header_sz + 12 + 2){} |
||||
|
|
||||
|
void write(std::ostream& out) const { |
||||
|
out << "BM"; |
||||
|
out.write(reinterpret_cast<const char*>(this), 12); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct bitmapcoreheader { |
||||
|
uint32_t header_sz; |
||||
|
uint16_t width; |
||||
|
uint16_t height; |
||||
|
uint16_t nplanes; |
||||
|
uint16_t bitspp; |
||||
|
|
||||
|
bitmapcoreheader(uint16_t width, uint16_t height, uint16_t bitspp = 24): |
||||
|
header_sz(sizeof(bitmapcoreheader)), |
||||
|
width(width), |
||||
|
height(height), |
||||
|
nplanes(1), |
||||
|
bitspp(bitspp){} |
||||
|
|
||||
|
void write(std::ostream& out) const { |
||||
|
out.write(reinterpret_cast<const char*>(this), header_sz); |
||||
|
} |
||||
|
|
||||
|
uint32_t bytes(){ |
||||
|
return width*height*bitspp/8; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template <typename P = pixelBGR, typename DIBT = bitmapcoreheader> |
||||
|
struct bitmap { |
||||
|
typedef P pixel; |
||||
|
|
||||
|
bitmap(uint16_t width, uint16_t height) |
||||
|
: dib_header(width, height, sizeof(pixel)*8) |
||||
|
, header(dib_header) |
||||
|
, data(0) {} |
||||
|
|
||||
|
void write(std::string const & filename){ |
||||
|
std::ofstream file(filename.c_str()); |
||||
|
write(file); |
||||
|
} |
||||
|
|
||||
|
void write(std::ostream& out){ |
||||
|
header.write(out); |
||||
|
dib_header.write(out); |
||||
|
//std::copy_n((char const *)data, dib_header.bytes(), std::ostream_iterator<char>(out));
|
||||
|
std::copy((char const *)data, (char const *)data + dib_header.bytes(), std::ostream_iterator<char>(out)); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
DIBT dib_header; |
||||
|
bitmap_file_header header; |
||||
|
P const * data; |
||||
|
}; |
||||
|
|
||||
|
template <typename P = pixelBGR, typename DIBT = bitmapcoreheader> |
||||
|
struct bitmap_stream { |
||||
|
typedef P pixel; |
||||
|
|
||||
|
bitmap_stream(uint16_t width, uint16_t height, std::string filename) |
||||
|
: dib_header(width, height, sizeof(pixel)*8) |
||||
|
, header(dib_header) |
||||
|
, file(filename.c_str()) |
||||
|
, x(0) |
||||
|
, y(0) |
||||
|
{ |
||||
|
if(!file) |
||||
|
throw std::runtime_error("bitmap file could not be opened."); |
||||
|
header.write(file); |
||||
|
dib_header.write(file); |
||||
|
} |
||||
|
|
||||
|
bitmap_stream& operator<<(pixel const & p){ |
||||
|
if (y >= dib_header.height){ |
||||
|
throw std::out_of_range("Writing BMP image out of bounds."); |
||||
|
} |
||||
|
|
||||
|
pixel p2(p); |
||||
|
p2.swapRB(); |
||||
|
file.write((char const *)&p2, sizeof(pixel)); |
||||
|
++x; |
||||
|
if (x >= dib_header.width){ |
||||
|
x = 0; |
||||
|
++y; |
||||
|
} |
||||
|
return *this; |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
DIBT dib_header; |
||||
|
bitmap_file_header header; |
||||
|
std::ofstream file; |
||||
|
|
||||
|
uint16_t x; |
||||
|
uint16_t y; |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,107 @@ |
|||||
|
//
|
||||
|
// ImageFormatPNG.hpp
|
||||
|
// AwesomeAttractorND
|
||||
|
//
|
||||
|
// Created by Joshua Moerman on 11/12/11.
|
||||
|
// Copyright 2011 Vadovas. All rights reserved.
|
||||
|
//
|
||||
|
|
||||
|
#ifndef AwesomeAttractorND_ImageFormatPNG_hpp |
||||
|
#define AwesomeAttractorND_ImageFormatPNG_hpp |
||||
|
|
||||
|
#include <stdio.h> |
||||
|
#include <stdexcept> |
||||
|
#include <png.h> |
||||
|
|
||||
|
namespace ImageFormats { |
||||
|
namespace png{ |
||||
|
struct pixel { |
||||
|
pixel() |
||||
|
: red(0) |
||||
|
, green(0) |
||||
|
, blue(0) |
||||
|
{} |
||||
|
|
||||
|
pixel(double red, double green, double blue) |
||||
|
: red(clamp(255*red)) |
||||
|
, green(clamp(255*green)) |
||||
|
, blue(clamp(255*blue)) |
||||
|
{} |
||||
|
|
||||
|
pixel(int red, int green, int blue) |
||||
|
: red(clamp(red)) |
||||
|
, green(clamp(green)) |
||||
|
, blue(clamp(blue)) |
||||
|
{} |
||||
|
|
||||
|
void swapRB(){ |
||||
|
std::swap(red, blue); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
uint8_t clamp(int n){ |
||||
|
return std::min(255, std::max(0, n)); |
||||
|
} |
||||
|
|
||||
|
uint8_t red; |
||||
|
uint8_t green; |
||||
|
uint8_t blue; |
||||
|
}; |
||||
|
|
||||
|
struct png_stream{ |
||||
|
typedef pixel pixel; |
||||
|
|
||||
|
png_stream(uint32_t width, uint32_t height, std::string filename) |
||||
|
: fp(0) |
||||
|
, png_ptr(0) |
||||
|
, info_ptr(0) |
||||
|
, row(width) |
||||
|
, x(0) |
||||
|
{ |
||||
|
fp = fopen(filename.c_str(), "wb"); |
||||
|
if(!fp) throw std::runtime_error("Could not open file"); |
||||
|
|
||||
|
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); |
||||
|
if(!png_ptr) throw std::runtime_error("PNG structure could not be allocated"); |
||||
|
|
||||
|
info_ptr = png_create_info_struct(png_ptr); |
||||
|
if(!info_ptr) throw std::runtime_error("PNG information structure could not be allocated"); |
||||
|
|
||||
|
png_init_io(png_ptr, fp); |
||||
|
|
||||
|
png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); |
||||
|
|
||||
|
png_set_compression_level(png_ptr, 9); |
||||
|
|
||||
|
png_write_info(png_ptr, info_ptr); |
||||
|
} |
||||
|
|
||||
|
~png_stream(){ |
||||
|
png_write_end(png_ptr, info_ptr); |
||||
|
png_destroy_info_struct(png_ptr, &info_ptr); |
||||
|
fclose(fp); |
||||
|
} |
||||
|
|
||||
|
png_stream& operator<<(pixel const & p){ |
||||
|
row[x] = p; |
||||
|
++x; |
||||
|
if(x >= row.size()){ |
||||
|
png_write_row(png_ptr, reinterpret_cast<unsigned char const*>(row.data())); |
||||
|
x = 0; |
||||
|
} |
||||
|
|
||||
|
return *this; |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
FILE* fp; |
||||
|
png_structp png_ptr; |
||||
|
png_infop info_ptr; |
||||
|
|
||||
|
std::vector<pixel> row; |
||||
|
uint32_t x; |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,133 @@ |
|||||
|
//
|
||||
|
// Vectors.hpp
|
||||
|
// AwesomeAttractorND
|
||||
|
//
|
||||
|
// Created by Joshua Moerman on 11/5/11.
|
||||
|
// Copyright 2011 Vadovas. All rights reserved.
|
||||
|
//
|
||||
|
|
||||
|
#ifndef AwesomeAttractorND_Vectors_hpp |
||||
|
#define AwesomeAttractorND_Vectors_hpp |
||||
|
|
||||
|
#include <iterator> |
||||
|
|
||||
|
typedef double* VectorRef; |
||||
|
typedef double const * VectorConstRef; |
||||
|
|
||||
|
struct VectorIterator : public std::iterator<std::random_access_iterator_tag, double> { |
||||
|
template <size_t N> |
||||
|
static VectorIterator begin(std::array<double, N> & arr, size_t dimension){ |
||||
|
return VectorIterator(arr.data(), dimension); |
||||
|
} |
||||
|
|
||||
|
template <size_t N> |
||||
|
static VectorIterator end(std::array<double, N> & arr, size_t dimension){ |
||||
|
size_t offset = N - (N % dimension); |
||||
|
return VectorIterator(arr.data() + offset, dimension); |
||||
|
} |
||||
|
|
||||
|
VectorIterator(VectorIterator const & rh) |
||||
|
: data(rh.data) |
||||
|
, dimension(rh.dimension) |
||||
|
{} |
||||
|
|
||||
|
VectorIterator & operator=(VectorIterator const & rh){ |
||||
|
data = rh.data; |
||||
|
dimension = rh.dimension; |
||||
|
return *this; |
||||
|
} |
||||
|
|
||||
|
bool operator==(VectorIterator const & rh) const { |
||||
|
return data == rh.data && dimension == rh.dimension; |
||||
|
} |
||||
|
|
||||
|
bool operator!=(VectorIterator const & rh) const { |
||||
|
return data != rh.data || dimension != rh.dimension; |
||||
|
} |
||||
|
|
||||
|
bool operator<(VectorIterator const & rh) const { |
||||
|
return data < rh.data; |
||||
|
} |
||||
|
|
||||
|
bool operator<=(VectorIterator const & rh) const { |
||||
|
return data <= rh.data; |
||||
|
} |
||||
|
|
||||
|
bool operator>(VectorIterator const & rh) const { |
||||
|
return data > rh.data; |
||||
|
} |
||||
|
|
||||
|
bool operator>=(VectorIterator const & rh) const { |
||||
|
return data >= rh.data; |
||||
|
} |
||||
|
|
||||
|
VectorRef operator*(){ |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
VectorRef operator->(){ |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
VectorIterator & operator++(){ |
||||
|
data += dimension; |
||||
|
return *this; |
||||
|
} |
||||
|
|
||||
|
VectorIterator operator++(int){ |
||||
|
VectorIterator temp(*this); |
||||
|
++(*this); |
||||
|
return temp; |
||||
|
} |
||||
|
|
||||
|
VectorIterator & operator--(){ |
||||
|
data -= dimension; |
||||
|
return *this; |
||||
|
} |
||||
|
|
||||
|
VectorIterator operator--(int){ |
||||
|
VectorIterator temp(*this); |
||||
|
++(*this); |
||||
|
return temp; |
||||
|
} |
||||
|
|
||||
|
VectorIterator & operator+=(int n){ |
||||
|
data += n*dimension; |
||||
|
return *this; |
||||
|
} |
||||
|
|
||||
|
VectorIterator operator+(int n){ |
||||
|
VectorIterator temp(*this); |
||||
|
temp += n; |
||||
|
return temp; |
||||
|
} |
||||
|
|
||||
|
VectorIterator & operator-=(int n){ |
||||
|
data -= n*dimension; |
||||
|
return *this; |
||||
|
} |
||||
|
|
||||
|
VectorIterator operator-(int n){ |
||||
|
VectorIterator temp(*this); |
||||
|
temp -= n; |
||||
|
return temp; |
||||
|
} |
||||
|
|
||||
|
VectorRef operator[](int n){ |
||||
|
VectorIterator temp(*this); |
||||
|
return *(temp += n); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
VectorIterator(double * data, size_t dimension) |
||||
|
: data(data) |
||||
|
, dimension(dimension) |
||||
|
{} |
||||
|
|
||||
|
VectorIterator(); |
||||
|
|
||||
|
double * data; |
||||
|
size_t dimension; |
||||
|
}; |
||||
|
|
||||
|
#endif |
@ -1,152 +0,0 @@ |
|||||
//
|
|
||||
// nd_array.hpp
|
|
||||
// AwesomeAttractorND
|
|
||||
//
|
|
||||
// Created by Joshua Moerman on 10/25/11.
|
|
||||
// Copyright 2011 Vadovas. All rights reserved.
|
|
||||
//
|
|
||||
|
|
||||
/*
|
|
||||
Dynamic multi-dimensional array. |
|
||||
With the usual c-syntax: v[x][y][z]. |
|
||||
Memory is allocated as one big block, instead of multiple smaller blocks (which is the case with std::vector<std::vector<...>>). |
|
||||
Showed no difference in speed compared to std::array<std::array<...>> (in release build). |
|
||||
|
|
||||
it is not yet standard compliant. |
|
||||
*/ |
|
||||
|
|
||||
#ifndef AwesomeAttractorND_nd_array_hpp |
|
||||
#define AwesomeAttractorND_nd_array_hpp |
|
||||
|
|
||||
#include <stdexcept> |
|
||||
#include <numeric> |
|
||||
#include <iterator> |
|
||||
#include "array.hpp" |
|
||||
|
|
||||
template <typename T, size_t dimension> |
|
||||
class nd_array{ |
|
||||
public: |
|
||||
typedef T & reference; |
|
||||
typedef T const & const_reference; |
|
||||
typedef T * iterator; |
|
||||
typedef T const * const_iterator; |
|
||||
typedef size_t size_type; |
|
||||
typedef ptrdiff_t difference_type; |
|
||||
typedef T value_type; |
|
||||
typedef T * pointer; |
|
||||
typedef T const * const_pointer; |
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator; |
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
|
||||
|
|
||||
template <size_type N> |
|
||||
struct proxy { |
|
||||
nd_array * const data; |
|
||||
size_t const offset; |
|
||||
|
|
||||
proxy(nd_array * const c, size_t o) |
|
||||
: data(c) |
|
||||
, offset(o) |
|
||||
{} |
|
||||
|
|
||||
proxy<N-1> operator[](size_t y){ |
|
||||
if (N == 0) throw std::logic_error("called operator[] on a value"); |
|
||||
return proxy<N-1>(data, data->sizes[dimension - N]*offset + y); |
|
||||
} |
|
||||
|
|
||||
operator reference(){ |
|
||||
if (N != 0) throw std::logic_error("using a non-value"); |
|
||||
return *(data->data + offset); |
|
||||
} |
|
||||
|
|
||||
reference operator=(T const & n){ |
|
||||
if (N != 0) throw std::logic_error("assignment to a non-value"); |
|
||||
return *(data->data + offset) = n; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
template <size_type N> |
|
||||
struct const_proxy { |
|
||||
nd_array const * const data; |
|
||||
size_t const offset; |
|
||||
|
|
||||
const_proxy(nd_array const * const c, size_t o) |
|
||||
: data(c) |
|
||||
, offset(o) |
|
||||
{} |
|
||||
|
|
||||
const_proxy<N-1> operator[](size_t y) const { |
|
||||
if (N == 0) throw std::logic_error("called operator[] on a value"); |
|
||||
return const_proxy<N-1>(data, data->sizes[dimension - N]*offset + y); |
|
||||
} |
|
||||
|
|
||||
operator const_reference() const { |
|
||||
if (N != 0) throw std::logic_error("using a non-value"); |
|
||||
return *(data->data + offset); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
nd_array(size_type width, size_type height) |
|
||||
: data(0) |
|
||||
, sizes() |
|
||||
{ |
|
||||
if (dimension != 2) throw std::logic_error("wrong constructor"); |
|
||||
sizes[0] = width; |
|
||||
sizes[1] = height; |
|
||||
data = new T[width*height]; |
|
||||
} |
|
||||
|
|
||||
nd_array(size_type width, size_type height, size_type depth) |
|
||||
: data(0) |
|
||||
, sizes() |
|
||||
{ |
|
||||
if (dimension != 3) throw std::logic_error("wrong constructor"); |
|
||||
sizes[0] = width; |
|
||||
sizes[1] = height; |
|
||||
sizes[2] = depth; |
|
||||
data = new T[width*height*depth]; |
|
||||
} |
|
||||
|
|
||||
~nd_array(){ |
|
||||
delete[] data; |
|
||||
} |
|
||||
|
|
||||
size_type get_size(size_type d) const { |
|
||||
return sizes[d]; |
|
||||
} |
|
||||
|
|
||||
size_type size() const { |
|
||||
return std::accumulate(sizes.begin(), sizes.end(), 1, std::multiplies<size_type>()); |
|
||||
} |
|
||||
|
|
||||
proxy<dimension-1> operator[](size_t x){ |
|
||||
return proxy<dimension-1>(this, x); |
|
||||
} |
|
||||
|
|
||||
const_proxy<dimension-1> operator[](size_t x) const { |
|
||||
return const_proxy<dimension-1>(this, x); |
|
||||
} |
|
||||
|
|
||||
iterator begin(){ |
|
||||
return data; |
|
||||
} |
|
||||
|
|
||||
iterator end(){ |
|
||||
size_type length = size(); |
|
||||
return data + length; |
|
||||
} |
|
||||
|
|
||||
const_iterator cbegin() const { |
|
||||
return data; |
|
||||
} |
|
||||
|
|
||||
const_iterator cend() const { |
|
||||
size_type length = size(); |
|
||||
return data + length; |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
T * data; |
|
||||
std::array<size_type, dimension> sizes; |
|
||||
}; |
|
||||
|
|
||||
#endif |
|
Reference in new issue