vADC Docs

Generating Mandelbrot sets using TrafficScript

by on ‎04-17-2013 05:33 AM - edited on ‎07-08-2015 02:04 PM by PaulWallace (1,861 Views)

Originally conceived by Ben Mansell in his favourite pub in Cambridge, the Stingray Mandelbrot generator has been wowing network managers for years!  Who would have thought a piece of networking gear could generate a picture as great as this?  Updated in Riverbed Orange, if you've not seen this demo of TrafficScript before, now's a great time to try it out.

 

The eponymous Mandelbrot Set is the subset of complex numbers that don't diverge to infinity when a particular mathematic operation is repeatedly applied.  It has a distinctive fractal (infinitely complex) boundary, and you can create some beautiful renderings of the set by coloring the points in the complex plane by how quickly they do diverge:

Screen Shot 2013-04-17 at 13.25.02.png

 

The following TrafficScript rule endeavors against all the odds to render such a picture in your browser, with full support for zooming in on the intricate boundary. Attach it as a request rule to an HTTP virtual server and start exploring...

 

# Mandelbrot set generator in TrafficScript.  
  
$pixelSize =   4;  
$rows      =  60;  
$cols      =  60;  
$magfactor =   4;  
$maxiter   = 255;  
  
  
$path = http.getPath();  
if( $path == "/" ) {  
   # Get the area of the mandelbrot set to view  
   $minx = lang.toDouble( http.getFormParam( "minx" ));  
   $miny = lang.toDouble( http.getFormParam( "miny" ));  
   $maxx = lang.toDouble( http.getFormParam( "maxx" ));  
   $maxy = lang.toDouble( http.getFormParam( "maxy" ));  
   if( !$minx ) $minx = -2.0;  
   if( !$miny ) $miny = -1.25;  
   if( !$maxx ) $maxx =  0.5;  
   if( !$maxy ) $maxy =  1.25;  
  
   $width  = $maxx - $minx;  
   $height = $maxy - $miny;  
   $stepx  = $width / $cols;  
   $stepy  = $height / $rows;  
   $w2     = $width / $magfactor;  
   $h2     = $height / $magfactor;  
    
   $grid = "";  
   $img = '<img width="'.$pixelSize.'" height="'.$pixelSize.'" src="s.gif?x=';  
  
   for( $yval = $maxy; $yval > $miny; $yval -= $stepy ) {  
      # Build the grid line-by-line... it's more efficient  
      $line = "";  
      $aref = '<a href="/?miny=' . ($yval-$h2) . '&maxy=' . ($yval+$h2) . '&minx=';  
      for( $xval = $minx; $xval < $maxx; $xval += $stepx ) {  
         $line .= $aref . ($xval-$w2) . '&maxx=' . ($xval+$w2) . '">'  
               . $img . $xval . '&y=' . $yval . '"/></a>';  
      }  
      $grid .= $line . "<br>\n";  
   }  
  
   # Deliver the web page  
   $page = '  
      <html><head><title>Mandlebrot</title>  
      <style type="text/css">img { border: none; }</style>  
      </head><body>' . $grid . '  
      <a href=/>Zoom back out</a></body></html>';  
   http.sendResponse( "200 OK", "text/html", $page, "" );  
}  
  
if( $path == "/s.gif" ) {  
   # Calculate the colour of point x,y of the mandelbrot and return an image  
  
   # real and imaginary components of c, based on the co-ordinates  
   $cr = lang.toDouble( http.getFormParam( "x" ));  
   $ci = lang.toDouble( http.getFormParam( "y" ));  
  
   # The main loop. It calculates z=z*z+c, and loops until z*z >= 2  
   $zr = 0.0;  
   $zc = 0.0;  
   $n = 0;  
   for( ; $n <= $maxiter; $n++ ) {  
      $zrs = $zr * $zr;  
      $zis = $zi * $zi;  
      if(( $zrs + $zis ) >= 4.0 ) break;  
      $zi = 2 * $zr * $zi + $ci;  
      $zr = $zrs - $zis + $cr;  
   }  
  
   # Use $n to generate the color; $n >= $maxiter means (x,y) is in set  
   # An 8x8 GIF, completely black  
   $image = string.hexDecode( "47494638376108000800800100000000ffffff2c".  
                              "0000000008000800000207848fa9cbed5d00003b" );  
   if( $n < $maxiter ) {  
      $i = lang.toDouble($n)/lang.toDouble($maxiter);  
      $i = math.sqrt( math.sqrt( $i ) );  
      # Riverbed Orange #e16832  
      $r = 0xe1*math.sqrt( $i );  
      $g = 0x68*$i;  
      $b = 0x32*$i;  
      # Replace bytes 13, 14 and 15  
      $image = string.replaceBytes( $image, lang.chr( $r ), 13 );  
      $image = string.replaceBytes( $image, lang.chr( $g ), 14 );  
      $image = string.replaceBytes( $image, lang.chr( $b ), 15 );  
   }  
   http.sendResponse( "200 OK", "image/gif", $image, "" );  
} 

 

The rule works in two steps.

 

  • When called with the URL '/', it generates a grid of images (s.gif), each image having a querystring identifying its location in the grid
  • When invoked with a request for the image, the rule performs the Mandelbrot iteration for the image location and returns a gif that is colored according to the result of the iteration

 

Be warned that trying to render a grid greater than 60x60 (i.e. 3600 concurrent image requests) can stretch the capabilities of your browser and networking stack, and certainly gave my Stingray development VM a good workout!  For note, Safari coped a lot better at loading and rendering the page than Google Chrome did.

 

Note: There's a built-in guard in Stingray to abort run-away TrafficScript rules.  If you find that you're not getting any output, and you have a 'maxinstr' error in your event log, try increasing the value of trafficscript!max_instr to a larger value

Contributors