Generating Mandelbrot sets in TrafficScript

mandelbrot imageHere's a fun example of the power of ZXTM's TrafficScript language. While it is clearly not very useful as a tool for your busy e-commerce sites, hopefully it will get you thinking about the possibilities of TrafficScript!

To set up, create a new virtual server. It can use the 'discard' pool for traffic, since no back-end nodes will be needed - ZXTM will be generating all of the content. Next, create a new TrafficScript rule with the following code. Finally, don't forget to associate this TrafficScript rule with the virtual server. That's it!

# Mandelbrot set viewer in TrafficScript.
#
# This rule is split into two distinct parts. The first half generates the
# HTML for the page, and the second half calculates the colour of each
# individual image on the page.

$path = http.getPath();
if( $path == "/" ) {
   # Generating the HTML for the page
   $rows = 60.0;
   $columns = 60.0;

   # Get the area of the mandelbrot set to view
   $minx = http.getFormParam( "minx" );
   $miny = http.getFormParam( "miny" );
   $maxx = http.getFormParam( "maxx" );
   $maxy = http.getFormParam( "maxy" );
   if( $minx == "" ) $minx = -2.5;
   if( $miny == "" ) $miny = -2.0;
   if( $maxx == "" ) $maxx = 1.5;
   if( $maxy == "" ) $maxy = 2.0;
   $minx = lang.toDouble( $minx );
   $miny = lang.toDouble( $miny );
   $maxx = lang.toDouble( $maxx );
   $maxy = lang.toDouble( $maxy );

   $width = $maxx - $minx;
   $height = $maxy - $miny;
   $magf = 4.0;
   $stepx = $width / $columns;
   $stepy = $height / $rows;

   # Build up the initial web page
   $page = "<html><head><title>Mandlebrot</title>"
         . "<style type=\"text/css\">\nimg { border: none; }\n</style>"
         . "</head><body>\n"
         . "<a href=/>Zoom back out</a><br>";

   # Scan each row
   $yval = $maxy;
   while( $yval > $miny ) {
      # Build each row separately, and append them one at a time to the
      # main $page string, as this is more efficient
      $line = "";

      # Zoom parameters
      $nminy = $yval - $height / $magf;
      $nmaxy = $yval + $height / $magf;

      $aref = "<a href=\"/?miny=" . $nminy . "&maxy=" . $nmaxy . "&minx=";

      $xval = $minx;
      $w2 = $width / $magf;
      while( $xval < $maxx ) {
         $line = $line . $aref . ( $xval - $w2 ) . "&maxx=" . ( $xval + $w2 )
               . "\">" . "<img width=8 height=8 src=\"s.gif?x="
               . $xval . "&y=" . $yval . "\"></img></a>";
         $xval = $xval + $stepx;
      }
      $page = $page . $line . "<br>";
      $yval = $yval - $stepy;
   }

   $page = $page . "</body></html>\n";
   http.sendResponse( "200 OK", "text/html", $page, "" );

} else if( $path == "/s.gif" ) {
   # Calculating the colour of one particular area of the mandelbrot.

   # Maximum number of iterations before we drop out
   $maxiter = 255;

   # real and imaginary components of c, based on the co-ordinates
   $cr = lang.toDouble( http.getFormParam( "x" ));
   $ci = lang.toDouble( http.getFormParam( "y" ));

   $zr = 0.0;
   $zc = 0.0;

   # The main loop. It calculates z=z*z+c, and loops until z*z >= 2
   $n = $maxiter;
   while( $n > 0 ) {
      $zrs = $zr * $zr;
      $zis = $zi * $zi;

      if(( $zrs + $zis ) >= 4.0 ) break;

      $zi = 2 * $zr * $zi + $ci;
      $zr = $zrs - $zis + $cr;
      $n = $n - 1;
   }

   # Scale the colours. Use a logarithmic scaling, so that the low iterations
   # can be seen
   $c = 255 * ( $maxiter - $n ) / lang.toDouble( $maxiter );
   $c = 255 - ( math.log( $c ) * 255 / math.log( 255 ));

   # An 8x8 GIF, completely black
   $image = string.hexDecode( "47494638376108000800800100000000ffffff2c".
                              "0000000008000800000207848fa9cbed5d00003b" );

   # Red component of the colour is byte 13
   $image = string.replaceBytes( $image, lang.chr( $c ), 13 );
   http.sendResponse( "200 OK", "image/gif", $image, "" );
}

Now, when you view the front page of the website, you will see the strange pattern of the Mandelbrot fractal. Clicking on part of the image will zoom in, allowing you to see more detail. Generating the fractal is in fact fairly easy; your web browser will probably be the slowest link in the chain, as it struggles to render the 3600 images on each of the generated web pages...

So, none of us at Zeus can think of a real-world use for this code, but we think it's neat anyway! It also shows how ZXTM is adept at generating content as well as directing traffic.

Ben [Zeus Dev Team] 13 January 2006  Permalink 1 comment  

Comments:

This public messageboard is not a forum for technical support. To report technical support problems, please contact our dedicated Support team using the instructions at the bottom of this page.

Comment from: Owen Garrett [Zeus Dev Team]
Someone recently asked how they could increase the resolution and color range of the Mandelbrot image this rule generated.

Increasing resolution

Increasing resolution is very easy:
  • Increase the value of '$rows' and '$columns' from 60 to a larger number, such as 120;
  • Decrease the size of the pixels by locating the code that writes the image (<img width=8 height=8... >) and changing the 8 to a smaller number, such as 2
Before you do this though, you'll need to release a safety feature in ZXTM! ZXTM prevents runaway rules from using too much CPU time by aborting them after 100000 instructions. You can increase this limit as follows:
  • Edit the file ZEUSHOME/zxtm/global.cfg - on an appliance, you'll need to SSH in
  • Add the line 'ichor_max_instr 9999999' to the file and save it
  • Restart ZXTM using either ZEUSHOME/restart-zeus, or the System->Traffic Managers page in the UI
If you don't do this, your rule will be aborted and you'll see the following message in your error log:
WARN:Rule 'mandelbrot' aborted during execution - Possible infinite loop detected, rule terminated
Note that to image will take a long time to render - not because ZXTM is slow, but because your browser will have to fetch and draw $rows*$columns (14,400) separate images!

Changing the color range

Bytes 13, 14 and 15 are the red, green and blue components of the image respectively. Try the following code to color the image, once the mandelbrot iteration has completed:
$period = lang.toDouble( $maxiter )/4.0;
$r = 128*(math.sin( ($maxiter-$n)*2.0*3.14/$p + 2.0*3.14/3.0 )+1);
$g = 128*(math.sin( ($maxiter-$n)*2.0*3.14/$p )+1);
$b = 128*(math.sin( ($maxiter-$n)*2.0*3.14/$p + 4.0*3.14/3.0 )+1);

$s = $n/lang.toDouble( $maxiter );

# Scale so higher counts are darkened
$s = $s*$s*$s*$s;
$r = $r * $s;
$g = $g * $s;
$b = $b * $s;

# An 8x8 GIF, completely black
$image = string.hexDecode( "47494638376108000800800100000000ffffff2c".
                           "0000000008000800000207848fa9cbed5d00003b" );

# 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, "" );
Feel free to experiment with other coloring schemes.

You can download the full rule here.
Permalink 22 January 2007 @ 11:45
Leave a comment ...
Your email address will not be displayed.
Your URL will be displayed.
This public messageboard is not a forum for technical support. To report technical support problems, please contact our dedicated Support team using the instructions at the bottom of this page.
Options:
 
(Line breaks become <br />)
(Set cookies for name, email & url)
Download Free ZXTM Desktop Edition

Recent Articles

Other Resources



www.zeus.com