HTML5 Canvas Drawing: Hopalong Fractals

I've always been interested in fractal geometry. When Benoit Mandelbrot died last year, I was very sad. I still have his book, "The Fractal Geometry of Nature" which I bought back in the 1980's. The color graphics in the book (especially considering available computing power then) are stunning. I almost failed 9th grade algebra. Math didn't become interesting to me until I started programming and studied fractal geometry. Now, math is beautiful!

Martin-Attractors, also known as Hopalongs, are  a kind of orbital fractal. They are images of a simple two-dimensional iteration system. The name Hopalong is derived from the fact that such an image is built of points hopping along on an elliptical path starting from one point in the center. Hopalong orbits were discovered by Barry Martin of Aston University, Birmingham, England. A.K. Dewdney presented the Hopalongs in "Scientific American" magazine in 1986.

Dewdneys original BASIC code from his article shows the formula:

INPUT num
INPUT a, b, c
x = 0
y = 0
PLOT(x, y)
FOR i = 1 TO num
xx = y - SIGN(x) * [ABS(b*x - c)]^0.5
yy = a - x
x = xx
y = yy

ABS is the absolute value function. SIGN(x) is the same as x/ABS(x). If x>0 then SIGN(x) = 1, if x<0 then SIGN(x) = −1 and if x = 0 then the result of SIGN(x) is zero, too.

After a certain number of points the color is changed. Normally the image doesn't depend on the first point. These attractors have the "butterfly effect". That means if you change the parameters a bit, you'll get a total new image with very little similarity to the first one.

The new HTML5 Canvas tag provides us with the perfect drawing surface to do all kinds of cool things with lines, curves, rectangles and even text. So let's jump into a little exercise and draw some animating Hopalong fractals in the browser.

<html>
   <head>  
    <script>
       window.setInterval("main();",1);        
       var x=0;
        var y=0;
        var xnew=0;
        var ynew=0;
        var i=0;
        var sn=Math.random();
        if (sn<.5) sn=-1;
        if (sn >.5) sn=1;
        var a=Math.random()*sn ;
        sn=Math.random();
        if (sn<.5) sn=-1;
        if (sn >.5) sn=1;
        var b=Math.random()*sn ;
        sn=Math.random();
        if (sn<.5) sn=-1;
        if (sn >.5) sn=1;
        var c=Math.random() *sn ;
        var ctrx =screen.availWidth/2 -350;
        var ctry= screen.availHeight/2;
        scl=40;
        var cl;      
      
        // this is our main function that does the iterations,
        // picking up the values of the global variables from the last setInterval firing.
        function main(){  
        for(var q=i;q<(i+70);q++){
        xnew = y - (x>0? 1:-1)* Math.sqrt(Math.abs(b*x-c));
        ynew = a - x;
        x=xnew;
y=ynew;      
    // get a color for this pixel based on x,y and q
        cl="#"+RGBtoHex( (q*256%255),(y*256%255),(x*256%255));       
  
   setPixel( ctrx+xnew*scl, ctry+ynew*scl, cl );
         }
         i=q;
        // after some iterations, clear the screen and do a new one...
        if(i>200000){
        i =0;
         var ctx = document.getElementById('canvas').getContext("2d");
   ctx.clearRect ( 0 , 0 , 1200 , 1200 );   
        }
       }  

    function setPixel( x, y, colr ){
var ctx = document.getElementById('canvas').getContext("2d");
ctx.fillStyle = colr;
ctx.fillRect(x,y,1,1);
}

function RGBtoHex(R,G,B) {return toHex(R)+toHex(G)+toHex(B)}
function toHex(N) {
if (N==null) return "00";
N=parseInt(N); if (N==0 || isNaN(N)) return "00";
N=Math.max(0,N); N=Math.min(N,255); N=Math.round(N);
return "0123456789ABCDEF".charAt((N-N%16)/16)
      + "0123456789ABCDEF".charAt(N%16);
}
</script>
</head>
<body bgcolor="black" onload="Main();" topmargin=0>   
  <canvas align="center" id="canvas" width="1200" height="1200"></canvas>
</body>
</html>

After setting my global variables, I have a main() function that is called using the setInterval method of the window object. This sets up the iteration loop with the Hopalong formula, gets a HEX color value based on the current values of q, x, and y , and then calls my little "setPixel" method, which in HTML5 is ultra simple:

   function setPixel( x, y, colr ){
var ctx = document.getElementById('canvas').getContext("2d");
ctx.fillStyle = colr;
ctx.fillRect(x,y,1,1);
}

Once we hit a certain number of iterations (enough to get a nice image) we clear the canvas and start over.



NOTE: In IE 9, you must add the <!DOCTYPE HTML> directive at the top of the HTML document.

You can download a sample HTML page with all this code here.

By Peter Bromberg   Popularity  (10152 Views)