threaded dla, _very_ naive, interest test 0...
An initial attempt at a threaded dla:
https://plus.google.com/101799841244447089430/posts/Pmm7Qsh9W2t
___________________________________________________________
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <random>
#include <functional>
#include <thread>
#include "bitmaplib.h" /* Paul Bourke's C bitmap library
http://paulbourke.net/fractals/
*/
#define WIDTH 1024U
#define HEIGHT ((unsigned int)(WIDTH * (9.0 / 16.0)))
#define POINTS 66666
static double
prv_round(
double norigin
){
return static_cast<double>(
(norigin > 0.0) ?
static_cast<long>(norigin + 0.5) :
static_cast<long>(norigin - 0.5));
}
BITMAP4
prv_color_gradient(
BITMAP4 cmin,
BITMAP4 cmax,
double cscale
){
BITMAP4 cwidth;
cwidth.r = cmax.r - cmin.r;
cwidth.g = cmax.g - cmin.g;
cwidth.b = cmax.b - cmin.b;
cwidth.a = cmax.a - cmin.a;
BITMAP4 cresult;
cresult.r = (unsigned char)(cmin.r + ((double)cwidth.r * cscale));
cresult.g = (unsigned char)(cmin.g + ((double)cwidth.g * cscale));
cresult.b = (unsigned char)(cmin.b + ((double)cwidth.b * cscale));
cresult.a = (unsigned char)(cmin.a + ((double)cwidth.a * cscale));
return cresult;
}
class simple_rand
{
unsigned int const m_seed;
mutable std::mt19937 m_engine;
mutable std::uniform_real_distribution<double> m_rdist;
public:
simple_rand(
unsigned int seed
): m_seed(seed),
m_engine(seed),
m_rdist(0.0, 1.0)
{
}
public:
double
get() const {
return m_rdist(m_engine);
}
double
get(double nmin, double nmax) const
{
double random = get();
return nmin + ((nmax - nmin) * random);
}
double
get_round(double nmin, double nmax) const
{
double random = get();
return prv_round(get(nmin, nmax));
}
};
class x_bitmap
{
public:
BITMAP4* const m_bitmap;
unsigned int const m_width;
unsigned int const m_height;
public:
x_bitmap(unsigned int width, unsigned int height)
: m_bitmap(Create_Bitmap(width, height)),
m_width(width),
m_height(height)
{
if (! m_bitmap) throw;
BITMAP4 color_bgrnd = { 0x00, 0x00, 0x00, 0x00 };
Erase_Bitmap(m_bitmap, m_width, m_height, color_bgrnd);
}
~x_bitmap() throw()
{
Destroy_Bitmap(m_bitmap);
}
public:
bool
set_pixel(int px, int py, BITMAP4 color)
{
return Draw_Pixel(m_bitmap, m_width, m_height, px, py, color);
}
BITMAP4
get_pixel(int px, int py) const
{
return Get_Pixel(m_bitmap, m_width, m_height, px, py);
}
void erase(BITMAP4 color)
{
Erase_Bitmap(m_bitmap, m_width, m_height, color);
}
bool
save(const char* fname)
{
FILE* fptr = std::fopen(fname,"wb");
if (! fptr) {
fprintf(stderr,"Failed to open output file\n");
return false;
} else {
Write_Bitmap(fptr, m_bitmap, m_width, m_height, 9);
fclose(fptr);
}
return true;
}
};
class dla_walker
{
public:
simple_rand m_rand;
x_bitmap& m_bitmap;
public:
dla_walker(x_bitmap& bitmap_)
: m_rand(((unsigned int)this) * 1331U),
m_bitmap(bitmap_)
{
}
public:
bool
check_point(int cpx, int cpy, int ximin, int ximax, int yimin, int
yimax)
{
BITMAP4 color_check;
for (int xi = ximin; xi < ximax; ++xi)
{
for (int yi = yimin; yi < yimax; ++yi)
{
int px = cpx + xi;
int py = cpy + yi;
if (px < 0) px = px * -1;
if (py < 0) py = py * -1;
if (px > m_bitmap.m_width - 1) px = px - (px - (m_bitmap.m_width - 1));
if (py > m_bitmap.m_height - 1) py = py - (py - (m_bitmap.m_height - 1));
color_check = m_bitmap.get_pixel(px, py);
if (color_check.a == 0xFF)
{
return true;
}
}
}
return false;
}
void walk_point(unsigned int imax, int cpx, int cpy, BITMAP4
color_origin)
{
unsigned int px = cpx;
unsigned int py = cpy;
for (unsigned int i = 0; i < imax; ++i)
{
int r1 = m_rand.get_round(-2, 2);
int r2 = m_rand.get_round(-2, 2);
int r3 = m_rand.get_round(-2, -1);
int r4 = m_rand.get_round(1, 2);
int r5 = m_rand.get_round(-2, -1);
int r6 = m_rand.get_round(1, 2);
px += r1;
py += r2;
if (px < 0) px = m_bitmap.m_width - 1;
if (py < 0) py = m_bitmap.m_height - 1;
if (px > m_bitmap.m_width - 1) px = 0;
if (py > m_bitmap.m_height - 1) py = 0;
if (check_point(px, py, r3, r4, r5, r6))
{
color_origin.a = 0xFF;
m_bitmap.set_pixel(px, py, color_origin);
return;
}
}
}
void walk_points(unsigned int imax, int cpx, int cpy)
{
BITMAP4 color_min = { 0xFF, 0x00, 0x00, 0x00 };
BITMAP4 color_max = { 0xFF, 0xFF, 0x00, 0x00 };
BITMAP4 color_result;
double cscale;
for (unsigned int i = 0; i < imax; ++i)
{
cscale = 1.0 - ((double)i / (double)(imax - 1));
cpx = m_rand.get_round(0, m_bitmap.m_width - 1);
cpy = m_rand.get_round(0, m_bitmap.m_height - 1);
color_result = prv_color_gradient(color_min, color_max, cscale);
walk_point(m_rand.get_round(33, 33313), cpx, cpy, color_result);
if (! (i % 8192 * 2))
{
std::printf("%p::dla_walker: plotted %d of %d\r", (void*)this, i + 1,
imax);
}
}
}
static void
seed_point(x_bitmap& bmp, int cpx, int cpy)
{
BITMAP4 color_origin = { 0xFF, 0x00, 0x00, 0xFF };
bmp.set_pixel(cpx, cpy, color_origin);
}
};
class dla_thread
{
dla_walker m_walker;
public:
dla_thread(x_bitmap& bmp)
: m_walker(bmp)
{
std::printf("%p::dla_thread::dla_thread()\n", (void*)this);
}
public:
void operator()()
{
std::printf("%p::dla_thread::operator()\n", (void*)this);
int px = m_walker.m_rand.get(10, m_walker.m_bitmap.m_width - 11);
int py = m_walker.m_rand.get(10, m_walker.m_bitmap.m_width - 11);
m_walker.walk_points(POINTS, px, py);
}
};
int
main()
{
{
{
simple_rand rand_(std::time(nullptr));
x_bitmap bmp(WIDTH, HEIGHT);
// Seed our initial growth points
{
#define ASEED_MAX 11.0
double aseed = (3.14 * 2.0) / ASEED_MAX;
double acur = .6;
double r = 50.0;
double cpx = bmp.m_width / 2.0;
double cpy = bmp.m_height / 2.0;
for (unsigned int i = 0; i < ASEED_MAX * 97; ++i)
{
acur = aseed * (i * 3.14);
r += 1.28;
r *= .9953;
double px = std::cos(acur) * r + cpx;
double py = std::sin(acur) * r + cpy;
dla_walker::seed_point(bmp, px , py);
}
}
// Spawn threads and wait...
{
dla_thread dlat1(bmp);
dla_thread dlat2(bmp);
dla_thread dlat3(bmp);
dla_thread dlat4(bmp);
{
std::thread t1(std::ref(dlat1));
std::thread t2(std::ref(dlat2));
std::thread t3(std::ref(dlat3));
std::thread t4(std::ref(dlat4));
t1.join();
t2.join();
t3.join();
t4.join();
}
}
// That's all folks! ;^)
bmp.save("dlax.bmp");
}
std::system("dlax.bmp");
}
std::puts("\n\nProgram Complete!");
std::fflush(stdout);
std::getchar();
return 0;
}
_____________________________________________________________
Enjoy?
Yikes!