cancel
Showing results for 
Search instead for 
Did you mean: 

Generating Mandelbrot sets using TrafficScript

Originally conceived by Ben Mansell in his favourite pub in Cambridge, the TrafficScript 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?  If you've not seen this demo of TrafficScript before, now is 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="https://community.pulsesecure.net/?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 ) );  
      # 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 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 Traffic Manager 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.

 

This article originally contributed by 

Version history
Revision #:
2 of 2
Last update:
‎12-19-2019 09:56:AM
Updated by:
 
Labels (1)
Contributors