Nadesłany przez Tomasz Lubiński, 08 listopada 2011 12:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
buddhabrot.js:
//Buddhabrot
//(c) 2011 by Tomasz Lubinski
//www.algorytm.org
/* Render area coordinates */
var minX = -1.5;
var maxX = 1.5;
var minY = -2.0;
var maxY = 1.0;
/* Render area size */
var width = 0;
var height = 0;
var ratioX;
var ratioY;
/* Number of fractal levels */
var levelNum = 100;
var colors = new Array(levelNum+1);
/* Number of iterations (bailout) */
var bailout = 100;
var sequence_x;
var sequence_y;
/* Number of points */
var pointsNum = 10000000;
var currentPointsNum = 0;
/* Fractal image */
var data;
var imageData;
var canvas;
var ctx;
/* initialize color table */
function initializeColors()
{
for (var level=0; level<=levelNum; level++)
{
colors[level] = new Object();
colors[level].r = 255.0*level/levelNum;
colors[level].g = 255.0*level/levelNum;
colors[level].b = 255.0*Math.log(level)/Math.log(levelNum);
}
}
/* value is inside set in the returned level */
function levelSet(p_re, p_im)
{
var z_re = 0;
var z_im = 0;
var iteration = 0;
var tmp_re, tmp_im;
do
{
tmp_re = z_re*z_re - z_im*z_im + p_re;
tmp_im = 2*z_re*z_im + p_im;
z_re = tmp_re;
z_im = tmp_im;
sequence_x[iteration] = tmp_im;
sequence_y[iteration] = tmp_re;
iteration++;
} while ((z_re*z_re+z_im*z_im) < 4 && iteration < bailout);
if (iteration >= bailout)
{
iteration = 0;
}
return iteration;
}
/* render Fractal */
function renderFractal()
{
sequence_x = new Array(bailout);
sequence_y = new Array(bailout);
/* Clear data */
for (var i=0; i<width*height; i++)
{
data[i] = 0;
}
currentPointsNum = 0;
calculateFractal();
}
function calculateFractal()
{
/* Calculate data */
proccesPointsNum = 10000000 / bailout;
for (var i=0; i<proccesPointsNum; i++)
{
p_im = 4.0*Math.random()-2.0;
p_re = 4.0*Math.random()-2.0;
level = levelSet(p_re, p_im);
for (var j=0; j<level; j++)
{
if (sequence_x[j] > minX &&
sequence_x[j] < maxX &&
sequence_y[j] > minY &&
sequence_y[j] < maxY)
{
x = Math.floor((sequence_x[j] - minX)/ratioX);
y = Math.floor((sequence_y[j] - minY)/ratioY);
x_dist = ((sequence_x[j] - minX)/ratioX) - x;
y_dist = ((sequence_y[j] - minY)/ratioY) - y;
data[x+y*width] += (1.0 - x_dist)*(1.0 - y_dist);
data[(x+1)+y*width] += (1.0 - x_dist)*(y_dist);
data[x+(y+1)*width] += (x_dist)*(1.0 - y_dist);
data[(x+1)+(y+1)*width] += (x_dist)*(y_dist);
}
}
}
/* Check range */
biggest = data[0];
smalest = data[0];
for (var i=1; i<width*height; i++)
{
if (data[i] > biggest)
{
biggest = data[i];
}
else if (data[i] < smalest)
{
smalest = data[i];
}
}
/* Generate image */
for (var i=0; i<height; i++)
{
for (var j=0; j<width; j++)
{
index = (i*width+j)*4;
imageData.data[index+3] = 0xff;
level = 2*Math.floor(((data[j+i*width]-smalest)/(biggest-smalest))*levelNum);
if (level > levelNum) level = levelNum;
imageData.data[index+0] = colors[level].r;
imageData.data[index+1] = colors[level].g;
imageData.data[index+2] = colors[level].b;
}
}
// copy the image data back onto the canvas
ctx.putImageData(imageData, 0, 0);
/* If not all points are calculated then show percent of done and call this function for 200 ms. */
currentPointsNum += proccesPointsNum;
if (currentPointsNum < pointsNum)
{
ctx.font = "15pt Arial";
ctx.fillStyle = "red";
ctx.textBaseline = "top";
ctx.textAlign = "center";
ctx.fillText(Math.floor((currentPointsNum / pointsNum)*100) + "%", width/2, height - 50);
setTimeout("calculateFractal()",200);
}
}
/* initialize environment and render Fractal */
function initializeFractal()
{
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
// read the width and height of the canvas
width = canvas.width;
height = canvas.height;
// create a new pixel array
data = new Array(width * height);
imageData = ctx.createImageData(width, height);
ratioX = (maxX - minX) / width;
ratioY = (maxY - minY) / height;
initializeColors();
renderFractal();
}

