threaded dla, _very_ naive, interest test 0...


C

Chris M. Thomasson

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::eek:perator()\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!
 
Ad

Advertisements

Ö

Öö Tiib

This long piece of code should interest us... why, exactly?

It seems that he wrote C++ code that uses several
'std::thread's to draw some sort of diffusion fractals in that
code.

Some people like fractals as decorative; some use these for
solving some technical problems. Lot of things in nature
(including life) seem to work primarily on Brown movement
and diffusion. It is hard to tell why (and if at all) it is noteworthy.
 
Ad

Advertisements

C

Chris M. Thomasson

"Öö Tiib" wrote in message
It seems that he wrote C++ code that uses several
'std::thread's to draw some sort of diffusion fractals in that
code.
Some people like fractals as decorative; some use these for
solving some technical problems. Lot of things in nature
(including life) seem to work primarily on Brown movement
and diffusion. It is hard to tell why (and if at all) it is noteworthy.

Öö Tiib: Exactly!

I am trying to visualize a random aspect generated by
race-conditions by relating them to Brownian motion
and diffusion. I thought DLA and no synchronization
between threads would be interesting wrt detecting,
and ultimately graphing encounters with seed points.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top