#native_company# #native_desc#
#native_cta#

slugtrail

By paddy
on October 3, 2005

Version: 1.0

Type: Full Script

Category: Graphics

License: GNU General Public License

Description: takes a string of characters as elementary instructions and draws a pattern. see example at http://www.eldwick.org.uk/?q=node/31

<?php
header("Content-type: image/png"); // tells the browser this is an image file!

$xmax = 200; $ymax = 200;
$im = ImageCreate($xmax, $ymax);

$background_color = imagecolorallocate($im, 255, 255, 255);
$trans_color = imagecolortransparent ($im, $background_color);
$pen_color = imagecolorallocate($im, 0, 0, 0);
$xPos = intval($xmax/2); $yPos = intval($ymax/2); $bearing = 0;
$rVal = 0; $gVal = 0; $bVal = 0; $penDown = 1;

$qString = $_SERVER['QUERY_STRING'];

// convert back from url encoded characters
$qString = urldecode($qString);

// get rid of '=' and spaces
$qString = str_replace("=", "", $qString);
$qString = str_replace(" ", "", $qString);

// draw the trail defined by the query string
slug($qString);

// render the image
imagepng($im);

// destroy image
ImageDestroy($im);

////////////////////////////////////////////////////////////
// the main interpreter function
////////////////////////////////////////////////////////////
function slug($dStr) {
 global $bearing; global $xPos; global $yPos; global $rVal; global $gVal; global $bVal; global $im; global $penDown; global $pen_color;
 $i=0;
 $dStr = strToUpper($dStr);
 $sLen = strlen($dStr);
 while ($i < $sLen) {
  $ch = substr($dStr, $i, 1);
  /////////////////////////// characters allowed ( ) L R S U D C X Y P Q 0123456789N
  $i++;
  switch ($ch) {
   case "(": /////////////////////////////////////////////// start of bracketed string
    $br = 1;
    $subSlug = "";
    $i--;
    while ($i < $sLen) {
     $i++;
     $ch = substr($dStr, $i, 1);
     if ($ch == "(") $br++;
     if ($ch == ")") { // ie end of a bracketed string
      $br--;
      if ($br == 0) { // ie the matching bracket for the initial opening one - call slug() for the contents
       $i++;
       $n = getNumber($dStr, $i, $sLen);
       for ($j=0; $j<$n; $j++) slug($subSlug); // do whatever was in the brakets n times using the slug function recursively
       break;
      }
     }
     $subSlug = $subSlug . $ch; // add this character to the bracketed string
    }
    break;
   case "L": /////////////////////////////////////////////// change the bearing clockwise
    $bearing += getNumber($dStr, $i, $sLen);
    break;
   case "R": /////////////////////////////////////////////// change the bearing anti-clockwise
    $bearing -= getNumber($dStr, $i, $sLen);
    break;
   case "S": /////////////////////////////////////////////// draws a line and updates the current location
    $n = getNumber($dStr, $i, $sLen);
    $xTo = intval($xPos + $n*sin(deg2rad($bearing)) + 0.5);
    $yTo = intval($yPos + $n*cos(deg2rad($bearing)) + 0.5);
    if ($penDown == 1) ImageLine($im, $xPos, $yPos, $xTo, $yTo, $pen_color); // only draw if pen's down
    $xPos = $xTo; $yPos = $yTo;
    break;
   case "C": /////////////////////////////////////////////// sets the colour as decimal numbers 00 to 99 ie C999999
    $n = getNumber($dStr, $i, $sLen);
    $rVal = intval($n/10000);
    $gVal = intval(($n - 10000*$rVal)/100);
    $bVal = $n - 10000*$rVal - 100*$gVal;
    $pen_color = imagecolorallocate($im, intval($rVal*2.55), intval($gVal*2.55), intval($bVal*2.55));
    break;
   case "U": /////////////////////////////////////////////// puts the pen up
    $penDown = 0;
    break;
   case "D": /////////////////////////////////////////////// puts the pen down
    $penDown = 1;
    break;
   case "X": /////////////////////////////////////////////// moves to absolute x coordinates without drawing
    $xPos = getNumber($dStr, $i, $sLen);
    break;
   case "Y": /////////////////////////////////////////////// moves to absolute y coordinates without drawing
    $yPos = getNumber($dStr, $i, $sLen);
    break;
   case "P": /////////////////////////////////////////////// flood fill starting n pixels to the left
    $n = getNumber($dStr, $i, $sLen);
    $xTo = intval($xPos + $n*sin(deg2rad($bearing + 90)) + 0.5);
    $yTo = intval($yPos + $n*cos(deg2rad($bearing + 90)) + 0.5);
    imageFill($im, $xTo, $yTo, $pen_color);
    break;
   case "Q": /////////////////////////////////////////////// flood fill starting n pixels to the right
    $n = getNumber($dStr, $i, $sLen);
    $xTo = intval($xPos + $n*sin(deg2rad($bearing - 90)) + 0.5);
    $yTo = intval($yPos + $n*cos(deg2rad($bearing - 90)) + 0.5);
    imageFill($im, $xTo, $yTo, $pen_color);
    break;
  }
 }
}

/////////////////////////////////////////////////////////////
// getNumber works along the given string till it finds a non numeric
// if there is a digit replaced by a "N" it will fill it with a random number 0-9
// $i is passed by reference to that it is picked up by the calling function at the end of the number
/////////////////////////////////////////////////////////////
function getNumber ($dStr, &$i, $endPoint) {
 $n = 0;
 while ($i < $endPoint) {
  $ch = substr($dStr, $i, 1);
  if ($ch == "N") $ch = rand(0,9);
  if (is_numeric($ch)) $n = 10*$n + intval($ch);
  else  return($n);
  $i++;
 }
 return($n);
}

?>