## Mandelbrot

Mandelbrot is a javascript implementation of a simple mandelbrot set calculator.

//
// Set the pixel at location <x,y> in the image data to <r,g,b,a>.  The r, g,
// and b elements are the red, green, and blue color components.  The a element
// is the alpha, or transparency value.  The r, g, b, and a values can range
// from 0 to 255.
//
function set_pixel(image_data, x, y, r, g, b, a)
{
// Compute the index into the pixel data.  Each pixel is represented by four
// sequential values in the image_data.data array.
index = (x + y * image_data.width) * 4;

image_data.data[index + 0] = r;
image_data.data[index + 1] = g;
image_data.data[index + 2] = b;
image_data.data[index + 3] = a;
}

//
// Compute the number of iterations required for a single orbit of the
// mandelbrot equation to escape from a circle of radius 2 centered at the
// origin of the complex plane.
//
function compute_escape_time(c_r, c_i, maximum_iterations)
{
z_r = 0.0;
z_i = 0.0;

for (i = 0; i < maximum_iterations; i++)
{
//
// Compute a single iteration of Z^2 + C.  Complex numbers are of the
// form "real + imaginary * i", so to square them you end up computing:
//
// (real + imaginary * i) * (real + imaginary * i)
// =
// real * real + imaginary * imaginary * i^2 + 2 * real * imaginary * i
// =
// real * real - imaginary * imaginary + 2 * real * imaginary * i
//
// So the new real value is (real * real - imaginary * imaginary)
// And the new imaginary value is (2 * real * imaginary)
//
// The reason the first + turns into a - is because i^2 is defined to be
// equal to -1, that's what makes the numbers imaginary.
//
temp = (z_r * z_r) - (z_i * z_i) + c_r;
z_i = (2.0 * z_r * z_i) + c_i;
z_r = temp;

// Check to see if the magnitude of the complex number is larger than
// 2.  We check whether the squared magnitude is greater than 4 here to
// avoid taking a square root, because square roots are slow.
if (((z_r * z_r) + (z_i * z_i)) > 4.0)
return i;
}

// Return the maximum iterations value if we never escaped.
return maximum_iterations;
}

//
// Draw a Mandelbrot set filling in a canvas specified by element_id.
//
function draw_mandelbrot(element_id)
{
// Lookup the canvas and get a 2D rendering context from it.
element = document.getElementById(element_id);
context = element.getContext("2d");

//
// Construct an image data object to hold the pixels before they are
// drawn to the screen.
//
image_data = context.createImageData(element.width,
element.height);

//
// Iterate over every pixel in the canvas and compute the escape time for
// the corresponding point in the complex plane.
//
for (y = 0; y < image_data.height; y++)
{
for (x = 0; x < image_data.width; x++)
{
//
// This scales the <x, y> values into a smaller range of the
// complex plane.  But it doesn't take into account the size of the
// canvas element.  So if the canvas element changes size, this will
// need to change as well.  This can be made automatic, but it would
// obcure the meaning for this example.  It would be a good
// experiment to change these values and try and make the result
// general.
//
iterations = compute_escape_time((x - 350.0) / 200.0,
(y - 250.0) / 200.0,
100);

//
// This is a simple use of the iteration count.  We are only looking
// at the bottom bit of the resulting escape time iterations.  This
// results in the zebra striping look.
//
if (iterations & 1)
r = g = b = 255;
else
r = g = b = 0;

//
// Write the computed color value to the image_data at the current
// location.
//
set_pixel(image_data, x, y, r, g, b, 255);
}
}

// Finally, copy the resulting image to the canvas for display.
context.putImageData(image_data, 0, 0);
}


Syntax highlighted with Prism.