home icon contact icon rss icon

fractal-wise

if you have ever wondered how those demo-scene guys accomplish so great images with so little code/space, it’s because of generativity. Generativity means finding very concise ways to generate very complex structures (or that’s the way I understand it, anyway :P ).

a programming language can be very generative if it lets you create complex programs in concise syntax.

math lets you express very complex structures with very concise syntax, and recursion takes this even further.

so these demoscene guys combine math with code, and accomplish those beatiful images in less than 24 Kb of machine code.

I’ve always wanted to know more of math, more of programming, and more of beauty ;)

I’m going to start investigating some math-powered image syntesis with fractals today. They are very powerful, since you can create really compelling images from very simple formulas and algorithms.

another day we will investigate particle systems (more dynamic and fun than fractals), and maybe L-systems (L for Lindenmayer), and cellular automatons, and voronoi partitions and… but today let’s do a mandelbrot set.

the theory goes like this: you want to plot points in a plane (2D, x and y, like when you draw in a canvas) and want them to look beatiful. Every point (x,y) will be representing a complex number x+y*j (where j =sqrt(-1) as you all know).

as you have seen in Mandelbrot images ( http://images.google.com/images?q=mandelbrot ) every point in this 2d plane has it’s own color. By now we will let it in just 2 colors: black or white.

Then a mandelbrot fractal is drawn by going through all the points (x,y) and testing if it satisfies the Mandelbrot test (that would mean it belongs to the mandelbrot set).

This test, basically means that you apply a formula to the point, and then to the result, and then to the result of the result and so a couple of times, and see if the resulting numbers go to infinity (grow a lot) or if they stay near some sane friendly-looking number such a s 2, 3 or 4. If it is going greater than 2, we will consider it a “crazy” number (goes to infinity).

so these are the formal definitions you can tell your Math PhD friends:

crazy number => goes to infinity friendly number => stays around what you can count with the fingers of your hands (say 2,3,4..)

now the formula: you start with z0=0+0j, then z1=(z0)^2 + (the-pixel-you're-painting), and z2=(z1)^2+(the-pixel-you're-painting), which means that:

c=x+yj => the pixel you’re painting, but expressed as a complex number. z0=0+0j => initial conditions z[n]=(z[n-1])^2 + c => the formula you will apply a couple of times until you see if z is going crazy or staying friendly.

now functions to sum and multiply complex numbers:

function complexMultiply(c1,c2){
 return [  (c1[0] * c2[0]-c1[1] * c2[1]) , (c1[0] * c2[1]+c1[1] * c2[0]) ];
}    
function complexAdd(c1,c2){
 return [ c1[0]+c2[0],c1[1]+c2[1] ];
}
function mandelTest(num,thres2){
 return (num[0] * num[0]+num[1] * num[1]) > thres2;
}
function mandelbrot(prev,c){
 return complexAdd(complexMultiply(prev,prev),c);
}
var canvas = document.getElementById("canvas");// you should have a < canvas id="canvas" width="300" height="300"/ > in your html.
var ctxt = canvas.getContext("2d");
canvas.setAttribute('width', '300'); // clears the canvas
ctxt.fillStyle = "rgb(255,0,0)";//red !
var prev=[0,0];
var c,belongs;
for(j=150;j>(- 150);j--){// for all the horizontal lines
  for(i=150;i>(- 150);i--){// and for every column in a line
      c=[i/50,j/50];//scale the coordinates (x,y) to where the mandelbrot set likes to live, which is around (2>x>-2) and  (1>y>-1) 
      prev=[0,0];//set the initial conditions
      belongs=true;//suppose the point belongs to the set
      for(a=0;a<15;a++){//do 15 iterations to see if it goes crazy or stays sane
         prev=mandelbrot(prev,c);//apply the function with the previous value and the our point (scaled)
         if(mandelTest(prev,4)){//test if it's gone insane
            belongs=false;//if insane, doesn't belong to mandelbrot
            break;//skip this point and keep iterating 
         }
      }
      if(belongs){// it seems to belong to the mandelbrot set !
         ctxt.fillRect(i+150,j+150,1,1);//let's paint it !
      }
   }
}

see ? it was easy !

you can see the results in here if you have a browser with <canvas>