graphing/class.graph.php
changeset 43 ce2e9caf2dfa
child 44 73f74d395f95
equal deleted inserted replaced
42:c24a2311f232 43:ce2e9caf2dfa
       
     1 <?php
       
     2   class CGraph {
       
     3     var $data = array();
       
     4     //---------------------------------------------
       
     5     var $graph_areaheight = 100;
       
     6     var $graph_areawidth = 50;
       
     7     var $graph_padding = array('left' => 50, 'top' => 20, 'right'  => 20, 'bottom' => 20);
       
     8     var $graph_title = "";
       
     9     var $graph_titlefont = 3;
       
    10     var $graph_bgcolor = array(255, 255, 255);
       
    11     var $graph_bgtransparent = false;
       
    12     var $graph_transparencylevel = 0;
       
    13     var $graph_borderwidth = 1;
       
    14     var $graph_bordercolor = array(218, 218, 239);
       
    15     var $graph_titlecolor = array(99, 88, 78);
       
    16     //---------------------------------------------
       
    17     var $axis_stepX = 1;
       
    18     var $axis_stepY = 1;
       
    19     var $axis_stepSize = 3;
       
    20     var $axis_deepness = 0;
       
    21     var $axis_maxX = 0;
       
    22     var $axis_minX = 0;
       
    23     var $axis_maxY = 0;
       
    24     var $axis_minY = 0;
       
    25     var $axis_bordercolor = array(99, 88, 78);
       
    26     var $axis_bgcolor = array(152, 137, 124);
       
    27     var $axis_scalefont = 2;
       
    28     var $axis_scalecolor = array(0, 0, 255);
       
    29     var $axis_xscalevisible = true;
       
    30     var $axis_yscalevisible = true;
       
    31     var $axis_gridlines = true;
       
    32     var $axis_frontgridlines = true;
       
    33     var $axis_positions = array(true, false, false, true);
       
    34     var $axis_modeX = 0; // 0=diference between steps 1=number of steps
       
    35     var $axis_modeY = 0; // 0=diference between steps 1=number of steps
       
    36     //---------------------------------------------
       
    37     var $scale_roundX = 1;
       
    38     var $scale_roundY = 1;
       
    39     var $scale_funX = "";
       
    40     var $scale_funY = "";
       
    41     //---------------------------------------------
       
    42     var $legend_visible = false;
       
    43     var $legend_floating = false;
       
    44     var $legend_borderwidth = 1;
       
    45     var $legend_bgcolor = array(255, 255, 255);
       
    46     var $legend_bordercolor = array(0, 0, 0);
       
    47     var $legend_width = 0;
       
    48     var $legend_height = 0;
       
    49     var $legend_padding = 30;
       
    50     var $legend_insidepadding = 3;
       
    51     var $legend_font = 1;
       
    52     var $legend_position = 3; // 1=bottom left | 2=top left | 3=top right | 4=bottom right
       
    53     var $legend_color = array(array(0, 0, 255));
       
    54     var $legend_data = array("Item 1");
       
    55 
       
    56     function CGraph() {
       
    57       //nothing @ the moment.. maybe later will set image at startup
       
    58     }
       
    59 
       
    60     /****************************************************************
       
    61                                 GRAPH
       
    62     ****************************************************************/
       
    63     function SetGraphAreaHeight($height) {
       
    64       if ($height > 0) {
       
    65         $this->graph_areaheight = $height;
       
    66         $this->graph_height = $this->graph_padding['top'] + $height + $this->graph_padding['bottom'];
       
    67       }
       
    68     }
       
    69     function SetGraphAreaWidth($width) {
       
    70       if ($width > 0) {
       
    71         $this->graph_areawidth = $width;
       
    72         $this->graph_width = $this->graph_padding['left'] + $width + $this->graph_padding['right'];
       
    73       }
       
    74     }
       
    75     function SetGraphPadding($left, $top, $right, $bottom) {
       
    76       $this->graph_padding = array('left' => (int)$left, 'top' => (int)$top, 'right' => (int)$right, 'bottom' => (int)$bottom);
       
    77     }
       
    78     function SetGraphTitle($title) {
       
    79       $this->graph_title = $title;
       
    80     }
       
    81     function SetGraphTitleFont($font) {
       
    82       $this->graph_titlefont = 0;
       
    83       switch ($font) {
       
    84         case 'x-large': $this->graph_titlefont++;
       
    85         case 'large':   $this->graph_titlefont++;
       
    86         case 'medium':  $this->graph_titlefont++;
       
    87         case 'small':   $this->graph_titlefont++;
       
    88         case 'x-small': $this->graph_titlefont++; break;
       
    89         default:
       
    90           $this->graph_titlefont = $font;
       
    91       }
       
    92     }
       
    93     function SetGraphTitleColor($red, $green, $blue) {
       
    94       $this->graph_titlecolor = array($red, $green, $blue);
       
    95     }
       
    96     function SetGraphBorderColor($red, $green, $blue) {
       
    97       $this->graph_bordercolor = array($red, $green, $blue);
       
    98     }
       
    99     function SetGraphBorderWidth($width = 0) {
       
   100       $this->graph_borderwidth = $width;
       
   101     }
       
   102     function SetGraphBackgroundColor($red, $green, $blue) {
       
   103       $this->graph_bgcolor = array($red, $green, $blue);
       
   104     }
       
   105     function SetGraphBackgroundTransparent($addtransparency = true, $red = 255, $green = 0, $blue = 255) {
       
   106       $this->graph_bgcolor = array($red, $green, $blue);
       
   107       $this->graph_bgtransparent = ($addtransparency ? true : false);
       
   108     }
       
   109     function SetGraphTransparency($percent) {
       
   110       if ($percent < 0) $percent = 0;
       
   111       elseif ($percent > 100) $percent = 127;
       
   112       else $percent = $percent * 1.27;
       
   113       $this->graph_transparencylevel = $percent;
       
   114     }
       
   115 
       
   116     /****************************************************************
       
   117                                  AXIS
       
   118     ****************************************************************/
       
   119     function SetAxisBorderColor($red, $green, $blue) {
       
   120       $this->axis_bordercolor = array($red, $green, $blue);
       
   121     }
       
   122     function SetAxisBackgroundColor($red, $green, $blue) {
       
   123       $this->axis_bgcolor = array($red, $green, $blue);
       
   124     }
       
   125     function SetAxisScaleColor($red, $green, $blue) {
       
   126       $this->axis_scalecolor = array($red, $green, $blue);
       
   127     }
       
   128     function SetAxisStepX($step) {
       
   129       if ($step > 0) $this->axis_stepX = $step;
       
   130     }
       
   131     function SetAxisStepY($step) {
       
   132       if ($step > 0) $this->axis_stepY = $step;
       
   133     }
       
   134     function SetAxisStepSize($size) {
       
   135       $this->axis_stepSize = (int) $size;
       
   136     }
       
   137     function SetAxisScaleXVisibility($state) {
       
   138       $this->axis_xscalevisible = ($state ? true : false);
       
   139     }
       
   140     function SetAxisScaleYVisibility($state) {
       
   141       $this->axis_yscalevisible = ($state ? true : false);
       
   142     }
       
   143     function SetAxisModeX($mode) {
       
   144       switch ($mode) {
       
   145         case '0':
       
   146         case 'value':
       
   147           $this->axis_modeX = 0; break;
       
   148         case '1':
       
   149         case 'dynamic':
       
   150           $this->axis_modeX = 1; break;
       
   151         case '2':
       
   152         case 'pixel':
       
   153           $this->axis_modeX = 2; break;
       
   154       }
       
   155     }
       
   156     function SetAxisModeY($mode) {
       
   157       switch ($mode) {
       
   158         case '0':
       
   159         case 'value':
       
   160           $this->axis_modeY = 0; break;
       
   161         case '1':
       
   162         case 'dynamic':
       
   163           $this->axis_modeY = 1; break;
       
   164         case '2':
       
   165         case 'pixel':
       
   166           $this->axis_modeY = 2; break;
       
   167       }
       
   168     }
       
   169     function SetAxisDeepness($deepness) {
       
   170       $this->axis_deepness = (int) $deepness;
       
   171     }
       
   172     function SetAxisScaleFont($font) {
       
   173       $this->axis_scalefont = 0;
       
   174       switch ($font) {
       
   175         case 'x-large': $this->axis_scalefont++;
       
   176         case 'large':   $this->axis_scalefont++;
       
   177         case 'medium':  $this->axis_scalefont++;
       
   178         case 'small':   $this->axis_scalefont++;
       
   179         case 'x-small': $this->axis_scalefont++; break;
       
   180         default:
       
   181           $this->axis_scalefont = $font;
       
   182       }
       
   183     }
       
   184     function SetAxisPositions($positions) {
       
   185       $positions = explode(",", strtolower($positions));
       
   186       $this->axis_positions = array(0, 0, 0, 0);
       
   187       for ($i = 0; $i < count($positions); $i++) {
       
   188         if ($positions[$i][0] == '-') {
       
   189           $v = false;
       
   190           $positions[$i] = substr($positions[$i], 1);
       
   191         } else $v = true;
       
   192         switch ($positions[$i]) {
       
   193           case 'all':    $this->axis_positions = array($v, $v, $v, $v); break;
       
   194           case 'left':   $this->axis_positions[0] = $v; break;
       
   195           case 'top':    $this->axis_positions[1] = $v; break;
       
   196           case 'right':  $this->axis_positions[2] = $v; break;
       
   197           case 'bottom': $this->axis_positions[3] = $v; break;
       
   198         }
       
   199       }
       
   200     }
       
   201     function SetAxisGridlines($state) {
       
   202       $this->axis_gridlines = ($state ? true : false);
       
   203     }
       
   204     function SetAxisFrontGridlines($state) {
       
   205       $this->axis_frontgridlines = ($state ? true : false);
       
   206     }
       
   207     /****************************************************************
       
   208                                  SCALE
       
   209     ****************************************************************/
       
   210     function SetScaleRoundX($number) {
       
   211       if ($number < 0) $number = 0;
       
   212       $this->scale_roundX = (int) $number;
       
   213     }
       
   214     function SetScaleRoundY($number) {
       
   215       if ($number < 0) $number = 0;
       
   216       $this->scale_roundY = (int) $number;
       
   217     }
       
   218     function SetScaleFunctionX($name) {
       
   219       $this->scale_funX = $name;
       
   220     }
       
   221     function SetScaleFunctionY($name) {
       
   222       $this->scale_funY = $name;
       
   223     }
       
   224     
       
   225     /****************************************************************
       
   226                                 LEGEND
       
   227     ****************************************************************/
       
   228     function SetLegendVisible($visible) {
       
   229       $this->legend_visible = ($visible ? true : false);
       
   230     }
       
   231     function SetLegendFloating($floating) {
       
   232       $this->legend_floating = ($floating ? true : false);
       
   233     }
       
   234     function SetLegendBackgroundColor($red, $green, $blue) {
       
   235       $this->legend_bgcolor = array($red, $green, $blue);
       
   236     }
       
   237     function SetLegendBorderColor($red, $green, $blue) {
       
   238       $this->legend_bordercolor = array($red, $green, $blue);
       
   239     }
       
   240     function SetLegendBorderWidth($width = 0) {
       
   241       $this->legend_borderwidth = $width;
       
   242     }
       
   243     function SetLegendColors($colors) {
       
   244       $this->__SetColorToValue("legend_color", $colors);
       
   245     }
       
   246     function SetLegendPadding($padding = 0) {
       
   247       $this->legend_padding = $padding;
       
   248     }
       
   249     function SetLegendInsidePadding($padding = 0) {
       
   250       $this->legend_insidepadding = $padding;
       
   251     }
       
   252     function SetLegendPosition($position) {
       
   253       switch ($position) {
       
   254         case 1:
       
   255         case 'bottom left':
       
   256           $this->legend_position = 1; break;
       
   257         case 2:
       
   258         case 'top left':
       
   259           $this->legend_position = 2; break;
       
   260         case 3:
       
   261         case 'top right':
       
   262           $this->legend_position = 3; break;
       
   263         case 4:
       
   264         case 'bottom right':
       
   265           $this->legend_position = 4; break;
       
   266 
       
   267       }
       
   268     }
       
   269     function SetLegendData($data) {
       
   270       if (is_array($data)) {
       
   271         $this->legend_data = $data;
       
   272       }
       
   273     }
       
   274     function SetLegentFont($font) {
       
   275       $this->legend_font = 0;
       
   276       switch ($font) {
       
   277         case 'x-large': $this->legend_font++;
       
   278         case 'large':   $this->legend_font++;
       
   279         case 'medium':  $this->legend_font++;
       
   280         case 'small':   $this->legend_font++;
       
   281         case 'x-small': $this->legend_font++; break;
       
   282         default:
       
   283           $this->legend_font = $font;
       
   284       }
       
   285     }
       
   286 
       
   287     /****************************************************************
       
   288                                  DATA
       
   289     ****************************************************************/
       
   290     function SetData($data) {
       
   291       if (is_array($data)) {
       
   292         $this->data = $data;
       
   293       }
       
   294     }
       
   295 
       
   296     function LoadGraph($path) {
       
   297       if (($fp = @fopen($path, "r")) !== false) {
       
   298         $content = "";
       
   299         while (!feof($fp)) {              // I do not use filesize() here
       
   300           $content .= fread($fp, 4096);   // because of remote files. If
       
   301         }                                 // there is no problem with them
       
   302         fclose($fp);                      // please let me know
       
   303         $this->__LoadGraphDefinitions($content);
       
   304         return true;
       
   305       } else return false;
       
   306     }
       
   307 
       
   308     function DrawGraph() {
       
   309       if ($this->graph_transparencylevel) {
       
   310         imagealphablending($this->im, true);
       
   311       }
       
   312       
       
   313       if ($this->legend_visible) {
       
   314         $maxlength = 0;
       
   315         for ($i = 0; $i < count($this->legend_data); $i++) {
       
   316           if (strlen($this->legend_data[$i]) > $maxlength) $maxlength = strlen($this->legend_data[$i]);
       
   317         }
       
   318         $this->legend_width = ($this->legend_insidepadding * 4) + ($maxlength * imagefontwidth($this->legend_font));
       
   319 
       
   320         if (!$this->legend_floating) {
       
   321           $this->graph_padding[($this->legend_position < 3 ? 'left' : 'right')] += $this->legend_padding + $this->legend_width;
       
   322           $this->graph_areawidth -= ($this->legend_padding + $this->legend_width);
       
   323         }
       
   324       }
       
   325 
       
   326       $this->__PaintBackground();
       
   327 
       
   328       $this->__DrawAxis();
       
   329     }
       
   330     
       
   331     function DrawGraph2() {
       
   332       if (strlen($this->graph_title)) {
       
   333         $this->__AllocateColor("im_graph_titlecolor",
       
   334                                $this->graph_titlecolor,
       
   335                                $this->graph_transparencylevel);
       
   336         $this->__DrawText($this->graph_title,
       
   337                           floor($this->graph_width / 2),
       
   338                           floor(($this->graph_padding['top'] - $this->axis_deepness - imagefontwidth($this->graph_titlefont)) / 2),
       
   339                           $this->im_graph_titlecolor,
       
   340                           $this->graph_titlefont,
       
   341                           1);
       
   342       }
       
   343 
       
   344       $this->__DrawLegend();
       
   345     }
       
   346 
       
   347     function __PaintBackground() {
       
   348       $this->__AllocateColor("im_graph_bgcolor",
       
   349                              $this->graph_bgcolor,
       
   350                              0);
       
   351       if ($this->graph_bgtransparent) {
       
   352         imagecolortransparent($this->im, $this->im_graph_bgcolor);
       
   353       }
       
   354       imagefilledrectangle($this->im, 0, 0, $this->graph_width, $this->graph_height, $this->im_graph_bgcolor);
       
   355       if ($this->graph_borderwidth) {
       
   356         $this->__AllocateColor("im_graph_bordercolor",
       
   357                                $this->graph_bordercolor,
       
   358                                $this->graph_transparencylevel);
       
   359         for ($i = 0; $i < $this->graph_borderwidth; $i++) {
       
   360           imagerectangle($this->im,
       
   361                          $i,
       
   362                          $i,
       
   363                          $this->graph_width - 1 - $i,
       
   364                          $this->graph_height - 1 - $i,
       
   365                          $this->im_graph_bordercolor);
       
   366         }
       
   367       }
       
   368     }
       
   369 
       
   370     function __DrawAxis() {
       
   371       $this->__AllocateColor("im_axis_bordercolor",
       
   372                              $this->axis_bordercolor,
       
   373                              $this->graph_transparencylevel);
       
   374       $this->__AllocateColor("im_axis_bgcolor",
       
   375                              $this->axis_bgcolor,
       
   376                              $this->graph_transparencylevel);
       
   377       $this->__AllocateColor("im_axis_scalecolor",
       
   378                              $this->axis_scalecolor,
       
   379                              $this->graph_transparencylevel);
       
   380 
       
   381       list($this->axis_minX,
       
   382            $this->axis_maxX,
       
   383            $this->axis_minY,
       
   384            $this->axis_maxY) = $this->__GetMinMaxGraphValue();
       
   385 
       
   386       if ($this->axis_gridlines) {
       
   387         $style = array($this->im_axis_bordercolor, $this->im_graph_bgcolor);
       
   388         imagesetstyle($this->im, $style);
       
   389       }
       
   390 
       
   391       if ($this->axis_modeX == 1) {
       
   392         $this->axis_stepX = ($this->axis_maxX - $this->axis_minX) / $this->axis_stepX;
       
   393       } elseif ($this->axis_modeX == 2) {
       
   394         $this->axis_stepX = $this->axis_stepX * ($this->axis_maxX - $this->axis_minX) / $this->graph_areawidth;
       
   395       }
       
   396 
       
   397       if ($this->axis_modeY == 1) {
       
   398         $this->axis_stepY = ($this->axis_maxY - $this->axis_minY) / $this->axis_stepY;
       
   399       } elseif ($this->axis_modeY == 2) {
       
   400         $this->axis_stepY = $this->axis_stepY * ($this->axis_maxY - $this->axis_minY) / $this->graph_areaheight;
       
   401         $rest = abs($this->axis_maxY) % $this->axis_stepY;
       
   402           // need to center a step on coord 0
       
   403           
       
   404       }
       
   405       
       
   406       if (!$this->axis_deepness) {
       
   407         $this->axis_frontgridlines = 1;
       
   408       }
       
   409 
       
   410       if (!$this->axis_xscalevisible) {
       
   411         $this->axis_positions[1] = 0;
       
   412         $this->axis_positions[3] = 0;
       
   413       }
       
   414       if (!$this->axis_yscalevisible) {
       
   415         $this->axis_positions[0] = 0;
       
   416         $this->axis_positions[2] = 0;
       
   417       }
       
   418       $this->__CorrectMinMax($this->axis_minX, $this->axis_maxX, $this->axis_stepX);
       
   419       $this->__CorrectMinMax($this->axis_minY, $this->axis_maxY, $this->axis_stepY);
       
   420       if ($this->axis_yscalevisible) {
       
   421         $this->__DrawHorizontalGridlines();
       
   422       }
       
   423       $this->__DrawHorizontalGideGridlines();
       
   424       if ($this->axis_xscalevisible) {
       
   425         $this->__DrawVerticalGridlines();
       
   426       }
       
   427       $this->__DrawVerticalGideGridlines();
       
   428       
       
   429       // draw lines that separate bars
       
   430       $total_bars = count($this->data);
       
   431       if ( min($this->data) >= 0 && get_class($this) == 'BarGraph' )
       
   432       {
       
   433         $totalbarwidth = $this->bar_width + ($this->bar_padding * 2);
       
   434         for ($i = 0; $i < $total_bars; $i++) {
       
   435           $offset = $this->graph_padding['left'] +
       
   436                     ($totalbarwidth * $i);
       
   437           
       
   438           $this->__DrawPolygon(
       
   439                     array(
       
   440                           $offset + $totalbarwidth,                     $this->graph_height - $this->graph_padding['bottom'],                      // top right
       
   441                           $offset,                                      $this->graph_height - $this->graph_padding['bottom'],                      // top left
       
   442                           $offset + $this->bar_height,                  $this->graph_height - $this->graph_padding['bottom'] - $this->bar_height,  // bottom left
       
   443                           $offset + $this->bar_height + $totalbarwidth, $this->graph_height - $this->graph_padding['bottom'] - $this->bar_height), // bottom right
       
   444                     $this->im_axis_bgcolor, true);
       
   445           
       
   446           imageline($this->im,
       
   447                     $offset,                         $this->graph_height - $this->graph_padding['bottom'],
       
   448                     $offset + $this->bar_height - 1, $this->graph_height - $this->graph_padding['bottom'] - $this->bar_height + 1,
       
   449                     $this->im_axis_bordercolor);
       
   450         }
       
   451       }
       
   452     }
       
   453     
       
   454     function __Draw_LeftBottom_Axis() {
       
   455       $w = $this->graph_width;
       
   456       $h = $this->graph_height;
       
   457       $p = $this->graph_padding;
       
   458       if ($this->axis_positions[3]) {
       
   459         $this->__DrawAxisPart($p['left'], $h - $p['bottom'], $w - $p['right'], $h - $p['bottom'],
       
   460                               $this->axis_minX, $this->axis_maxX, $this->axis_stepX,
       
   461                               "right", "bottom");
       
   462       }
       
   463       if ($this->axis_positions[0]) {
       
   464         $this->__DrawAxisPart($p['left'], $p['top'], $p['left'], $h - $p['bottom'],
       
   465                               $this->axis_minY, $this->axis_maxY, $this->axis_stepY,
       
   466                               "up", "left");
       
   467       }
       
   468     }
       
   469     
       
   470     function __Draw_TopRight_Axis() {
       
   471       $w = $this->graph_width;
       
   472       $h = $this->graph_height;
       
   473       $p = $this->graph_padding;
       
   474       if ($this->axis_positions[1]) {
       
   475         $this->__DrawAxisPart($p['left'], $p['top'], $w - $p['right'], $p['top'],
       
   476                               $this->axis_minX, $this->axis_maxX, $this->axis_stepX,
       
   477                               "right", "top");
       
   478       }
       
   479       if ($this->axis_positions[2]) {
       
   480         $this->__DrawAxisPart($w - $p['right'], $p['top'], $w - $p['right'], $h - $p['bottom'],
       
   481                               $this->axis_minY, $this->axis_maxY, $this->axis_stepY,
       
   482                               "up", "right");
       
   483       }
       
   484     }
       
   485     
       
   486     function __CorrectMinMax(&$min, &$max, &$step) {
       
   487       if (($max % $step) != 0) $max += ($step - abs($max % $step));
       
   488       if (($min % $step) != 0) $min -= abs($min % $step);
       
   489     }
       
   490     
       
   491     function __DrawHorizontalGridlines() {
       
   492       $maxy = $this->graph_height - $this->graph_padding['bottom'];
       
   493       $miny = $this->graph_padding['top'];
       
   494       $maxx = $this->graph_width - $this->graph_padding['right'];
       
   495       $minx = $this->graph_padding['left'];
       
   496       $offset = ($maxy - $miny) / ($this->axis_maxY - $this->axis_minY) * $this->axis_stepY;
       
   497       $v = $miny + $offset;
       
   498 
       
   499       $deep = $this->axis_deepness;
       
   500       if (!$deep) $grid_offset = $this->axis_stepSize;
       
   501       else $grid_offset = 1;
       
   502       while ($v < $maxy) {
       
   503         imageline($this->im, $minx + $deep + (!$this->axis_positions[0] ? 0 : $grid_offset),
       
   504                              floor($v) - $deep,
       
   505                              $maxx + $deep - (!$this->axis_positions[2] ? 0 : $grid_offset),
       
   506                              floor($v) - $deep, IMG_COLOR_STYLED);
       
   507         $v += $offset;
       
   508       }
       
   509     }
       
   510     
       
   511     function __DrawHorizontalGideGridlines() {
       
   512       $maxy = $this->graph_height - $this->graph_padding['bottom'];
       
   513       $miny = $this->graph_padding['top'];
       
   514       $maxx = $this->graph_width - $this->graph_padding['right'];
       
   515       $minx = $this->graph_padding['left'];
       
   516 
       
   517       $deep = $this->axis_deepness;
       
   518       if (!$deep) $grid_offset = $this->axis_stepSize;
       
   519       else $grid_offset = 1;
       
   520       
       
   521       if (!$this->axis_positions[1]) {
       
   522         if ($deep) {
       
   523           imageline($this->im, $minx + $deep + $grid_offset, $miny - $deep,
       
   524                     $maxx + $deep + $grid_offset, $miny - $deep, IMG_COLOR_STYLED);
       
   525         }
       
   526         if ($this->axis_frontgridlines) {
       
   527           imageline($this->im, $minx, $miny, $maxx, $miny, IMG_COLOR_STYLED);
       
   528         }
       
   529       }
       
   530       if (!$this->axis_positions[3]) {
       
   531         if ($deep) {
       
   532           imageline($this->im, $minx + $deep + $grid_offset, $maxy - $deep,
       
   533                     $maxx + $deep + $grid_offset, $maxy - $deep, IMG_COLOR_STYLED);
       
   534         }
       
   535         if ($this->axis_frontgridlines) {
       
   536           imageline($this->im, $minx, $maxy, $maxx, $maxy, IMG_COLOR_STYLED);
       
   537         }
       
   538       }
       
   539     }
       
   540     
       
   541     function __DrawVerticalGridlines() {
       
   542       $maxy = $this->graph_height - $this->graph_padding['bottom'];
       
   543       $miny = $this->graph_padding['top'];
       
   544       $maxx = $this->graph_width - $this->graph_padding['right'];
       
   545       $minx = $this->graph_padding['left'];
       
   546       if ( $this->axis_maxX == 0 )
       
   547         $this->axis_maxX = 1;
       
   548       $offset = ($maxx - $minx) / ($this->axis_maxX - $this->axis_minX) * $this->axis_stepX;
       
   549       $v = $minx + $offset;
       
   550 
       
   551       $deep = $this->axis_deepness;
       
   552       if (!$deep) $grid_offset = $this->axis_stepSize;
       
   553       else $grid_offset = 1;
       
   554       
       
   555       while ($v < $maxx) {
       
   556         imageline($this->im, floor($v) + $deep,
       
   557                              $miny - $deep + (!$this->axis_positions[1] ? 0 : $grid_offset),
       
   558                              floor($v) + $deep,
       
   559                              $maxy - $deep - (!$this->axis_positions[3] ? 0 : $grid_offset),
       
   560                              IMG_COLOR_STYLED);
       
   561         $v += $offset;
       
   562       }
       
   563     }
       
   564     
       
   565     function __DrawVerticalGideGridlines() {
       
   566       $maxy = $this->graph_height - $this->graph_padding['bottom'];
       
   567       $miny = $this->graph_padding['top'];
       
   568       $maxx = $this->graph_width - $this->graph_padding['right'];
       
   569       $minx = $this->graph_padding['left'];
       
   570 
       
   571       $deep = $this->axis_deepness;
       
   572       if (!$deep) $grid_offset = $this->axis_stepSize;
       
   573       else $grid_offset = 1;
       
   574       
       
   575       if (!$this->axis_positions[0]) {
       
   576         if ($deep) {
       
   577           imageline($this->im, $minx + $deep + $grid_offset, $miny - $deep,
       
   578                     $minx + $deep + $grid_offset, $maxy - $deep, IMG_COLOR_STYLED);
       
   579         }
       
   580         if ($this->axis_frontgridlines) {
       
   581           imageline($this->im, $minx, $miny, $minx, $maxy, IMG_COLOR_STYLED);
       
   582         }
       
   583       }
       
   584       if (!$this->axis_positions[2]) {
       
   585         if ($deep) {
       
   586           imageline($this->im, $maxx + $deep + $grid_offset, $miny - $deep,
       
   587                     $maxx + $deep + $grid_offset, $maxy - $deep, IMG_COLOR_STYLED);
       
   588         }
       
   589         if ($this->axis_frontgridlines) {
       
   590           imageline($this->im, $maxx, $miny, $maxx, $maxy, IMG_COLOR_STYLED);
       
   591         }
       
   592       }
       
   593     }
       
   594     
       
   595     function __DrawAxisPart($x1, $y1, $x2, $y2, $scale_start, $scale_end, $scale_step, $scale_direction, $scaletext_side) {
       
   596       $deep = $this->axis_deepness;
       
   597       if ($deep > 0) {
       
   598         $this->__DrawPolygon(array($x1, $y1, $x1 + $deep, $y1 - $deep, $x2 + $deep, $y2 - $deep, $x2, $y2), $this->im_axis_bgcolor, true);
       
   599         $this->__DrawPolygon(array($x1, $y1, $x1 + $deep, $y1 - $deep, $x2 + $deep, $y2 - $deep, $x2, $y2), $this->im_axis_bordercolor);
       
   600       } else {
       
   601         imageline($this->im, $x1, $y1, $x2, $y2, $this->im_axis_bordercolor);
       
   602       }
       
   603       
       
   604       // reverse order if needed
       
   605       if ($x1 == $x2) {
       
   606         if ($scale_direction == "up") {
       
   607           $scale_direction = "down";
       
   608           $v = $scale_start;
       
   609           $scale_start = $scale_end;
       
   610           $scale_end = $v;
       
   611           $scale_step = -$scale_step;
       
   612         } else $scale_direction = "down";
       
   613         if ($scaletext_side != "left") $scaletext_side = "right";
       
   614       } else {
       
   615         if ($scale_direction == "left") {
       
   616           $scale_direction = "right";
       
   617           $v = $scale_start;
       
   618           $scale_start = $scale_end;
       
   619           $scale_end = $v;
       
   620           $scale_step = -$scale_step;
       
   621         } else $scale_direction = "right";
       
   622         if ($scaletext_side != "top") $scaletext_side = "bottom";
       
   623       }
       
   624       
       
   625       $v = $scale_start;
       
   626       $total = $scale_end - $v;
       
   627       if ($x1 == $x2) {
       
   628         $totalarea = $this->graph_areaheight;
       
   629       } else {
       
   630         $totalarea = $this->graph_areawidth;
       
   631       }
       
   632       
       
   633       $akeys = array_keys($this->data);
       
   634       
       
   635       while (($v <= $scale_end && $scale_step > 0) || ($v >= $scale_end && $scale_step < 0)) {
       
   636         if ($x1 == $x2) {
       
   637           $offset = ceil($y1 + (($v - $scale_start) * $totalarea / $total));
       
   638           if (strlen($this->scale_funY)) {
       
   639             $fun = str_replace("%d", $v, $this->scale_funY);
       
   640             eval("\$scale_value = " . $fun . ";");
       
   641           } else {
       
   642             $scale_value = $this->__RoundNumber($v, $this->scale_roundY);
       
   643           }
       
   644           // vertical axis scale text
       
   645           $this->__DrawText($scale_value, $x1 + ($scaletext_side == "left" ? -6 : 6 + $deep),
       
   646                             $offset, $this->im_axis_scalecolor, $this->axis_scalefont,
       
   647                             ($scaletext_side == "left" ? 2 : 0), 1);
       
   648           if ($v != $scale_start && $v != $scale_end) {
       
   649             // vertical axis scale line
       
   650             imageline($this->im, $x1 + ($scaletext_side == "left" ? 1 : -1), $offset,
       
   651                       $x1 + ($scaletext_side == "left" ? $this->axis_stepSize : -$this->axis_stepSize),
       
   652                       $offset - $this->axis_stepSize + ($scaletext_side == "left" ? 1 : -1), $this->im_axis_bordercolor);
       
   653           }
       
   654         } else {
       
   655           $offset = floor($x1 + (($v - $scale_start) * $totalarea / $total));
       
   656           if (function_exists($this->scale_funX)) {
       
   657             $fun = $this->scale_funX;
       
   658             $scale_value = $fun($v, $this);
       
   659           } else {
       
   660             $use_int = true;
       
   661             if ( isset($akeys[$v]) )
       
   662               if ( is_string($akeys[$v]) && !ctype_digit($akeys[$v]) )
       
   663                 $use_int = false;
       
   664             $scale_value = $use_int ? $this->__RoundNumber($v, $this->scale_roundX) : $akeys[$v];
       
   665           }
       
   666           // horizontal axis scale text
       
   667           $this->__DrawText($scale_value, $offset, $y1 + ($scaletext_side == "top" ? -6 - $deep : 6),
       
   668                             $this->im_axis_scalecolor, $this->axis_scalefont, 1,
       
   669                             ($scaletext_side == "top" ? 2 : 0));
       
   670           if ($v != $scale_start && $v != $scale_end) {
       
   671             // horizontal axis scale line
       
   672             imageline($this->im, $offset, $y1 + ($scaletext_side == "top" ? 1 : -1),
       
   673                       $offset,
       
   674                       $y1 + ($scaletext_side == "top" ? $this->axis_stepSize : -$this->axis_stepSize),
       
   675                       $this->im_axis_bordercolor);
       
   676           }
       
   677         }
       
   678         $v += $scale_step;
       
   679       }
       
   680     }
       
   681     
       
   682     function __DrawText($text, $x, $y, $color, $size = 1, $align = 0, $valign = 0) {
       
   683       /* Align: 0=left | 1=center | 2=right */
       
   684       if ($align == 1) $x -= floor(strlen($text) * imagefontwidth($size) / 2);
       
   685       elseif ($align == 2) $x -= (strlen($text) * imagefontwidth($size));
       
   686       if ($valign == 1) $y -= floor(imagefontheight($size) / 2);
       
   687       elseif ($valign == 2) $y -= imagefontheight($size);
       
   688       imagestring($this->im, $size, $x, $y, $text, $color);
       
   689     }
       
   690 
       
   691     function __GetMinMaxGraphValue() {
       
   692       $arrki = array_keys($this->data);
       
   693       if (is_array($this->data[$arrki[0]])) {
       
   694         for ($i = 0; $i < count($arrki); $i++) {
       
   695           $arrkj = array_keys($this->data[$arrki[$i]]);
       
   696           if ($i == 0) {
       
   697             $maxX = $minX = (int) $arrkj[0];
       
   698             $maxY = $minY = (int) $this->data[$arrki[0]][$arrkj[0]];
       
   699           }
       
   700           for ($j = 0; $j < count($arrkj); $j++) {
       
   701             if ($arrkj[$j] > $maxX) $maxX = $arrkj[$j];
       
   702             elseif ($arrkj[$j] < $minX) $minX = $arrkj[$j];
       
   703             if ($this->data[$arrki[$i]][$arrkj[$j]] > $maxY) $maxY = $this->data[$arrki[$i]][$arrkj[$j]];
       
   704             elseif ($this->data[$arrki[$i]][$arrkj[$j]] < $minY) $minY = $this->data[$arrki[$i]][$arrkj[$j]];
       
   705           }
       
   706         }
       
   707       } else {
       
   708         $maxY = $minY = (int) $this->data[$arrki[0]];
       
   709         foreach ($this->data as $x => $y) {
       
   710           if ($y > $maxY) $maxY = $y;
       
   711           elseif ($y < $minY) $minY = $y;
       
   712         }
       
   713         $minX = 0;
       
   714         $maxX = count($this->data);
       
   715       }
       
   716       if ( $maxY == 0 )
       
   717       {
       
   718         $maxY = 10;
       
   719       }
       
   720       return array($minX, $maxX, $minY, $maxY);
       
   721     }
       
   722 
       
   723     function __DrawPolygon($points, $color, $filled = false) {
       
   724       if ($filled) {
       
   725         imagefilledpolygon($this->im, $points, 4, $color);
       
   726       } else {
       
   727         imagepolygon($this->im, $points, 4, $color);
       
   728       }
       
   729     }
       
   730 
       
   731     function __LoadGraphDefinitions($text) {
       
   732       $text = preg_split("/\r?\n/", $text);
       
   733       $data = array();
       
   734       $section = '';
       
   735       for ($i = 0; $i < count($text); $i++) {
       
   736         if (preg_match("/^\s*#/", $text[$i])) {
       
   737           //ignore.. it's just a comment
       
   738         } elseif (preg_match("/^\s*\}\s*/", $text[$i])) {
       
   739           $section = '';
       
   740         } elseif (preg_match("/^\s*(\w+)\s*\{\s*$/", $text[$i], $r)) {
       
   741           $section = $r[1];
       
   742           $index = -1;
       
   743         } elseif (preg_match("/^\s*\-\s*$/", $text[$i]) && strlen($section)) {
       
   744           $index++;
       
   745         } else {
       
   746           $p = strpos($text[$i], "=");
       
   747           if ($p !== false) {
       
   748             $k = trim(substr($text[$i], 0, $p));
       
   749             $v = trim(substr($text[$i], $p + 1));
       
   750             if ($index >= 0) {
       
   751               $data[$section][$index][$k] = $v;
       
   752             } else {
       
   753               if (preg_match("/^\s*\[(.*)\]\s*$/", $v, $r)) {
       
   754                 // array
       
   755                 $data[$section][$k] = explode(";", $r[1]);
       
   756               } else {
       
   757                 $data[$section][$k] = $v;
       
   758               }
       
   759             }
       
   760           }
       
   761         }
       
   762       }
       
   763       foreach ($data as $key => $settings) {
       
   764         $func = "__Load" . ucfirst($key) . "Values";
       
   765         if (method_exists($this, $func)) {
       
   766           $this->$func($settings);
       
   767         }
       
   768       }
       
   769       if (is_array($data['data'])) {
       
   770         $this->data = $data['data'];
       
   771       }
       
   772     }
       
   773 
       
   774     function __LoadGraphValues($data) {
       
   775       foreach ($data as $name => $value) {
       
   776         $name = strtolower($name);
       
   777         switch ($name) {
       
   778           case 'background-color':
       
   779             $this->__SetColorToValue("graph_bgcolor", $value);
       
   780             break;
       
   781           case 'border-color':
       
   782             $this->__SetColorToValue("graph_bordercolor", $value);
       
   783             break;
       
   784           case 'title-color':
       
   785             $this->__SetColorToValue("graph_titlecolor", $value);
       
   786             break;
       
   787           case 'background-transparent':
       
   788             $this->graph_bgtransparent = ($value == 1 || $value == 'yes' ? 1 : 0);
       
   789             break;
       
   790           case 'transparency':
       
   791             $this->SetGraphTransparency(str_replace('%', '', $value));
       
   792             break;
       
   793           case 'title':
       
   794             $this->graph_title = $value;
       
   795             break;
       
   796           case 'title-font':
       
   797             $this->SetGraphTitleFont($value);
       
   798             break;
       
   799           case 'border-width':
       
   800             $this->graph_borderwidth = (int) $value;
       
   801             break;
       
   802           case 'area-height':
       
   803             $this->graph_areaheight = (int) $value;
       
   804             $this->graph_height = $this->graph_padding['top'] + (int)$value + $this->graph_padding['bottom'];
       
   805             break;
       
   806           case 'area-width':
       
   807             $this->graph_areawidth = (int) $value;
       
   808             $this->graph_width = $this->graph_padding['left'] + (int)$value + $this->graph_padding['right'];
       
   809             break;
       
   810           default:
       
   811             if (substr($name, 0, 8) == 'padding-' && strlen($name) > 8) {
       
   812               $this->graph_padding[substr($name, 8)] = $value;
       
   813             }
       
   814         }
       
   815       }
       
   816     }
       
   817 
       
   818     function __LoadAxisValues($data) {
       
   819       foreach ($data as $name => $value) {
       
   820         $name = strtolower($name);
       
   821         switch ($name) {
       
   822           case 'x-step':
       
   823             $this->SetAxisStepX($value);
       
   824             break;
       
   825           case 'y-step':
       
   826             $this->SetAxisStepY($value);
       
   827             break;
       
   828           case 'step-size':
       
   829             $this->axis_stepSize = (int) $value;
       
   830             break;
       
   831           case 'x-step-mode':
       
   832             $this->SetAxisModeX($value);
       
   833             break;
       
   834           case 'y-step-mode':
       
   835             $this->SetAxisModeY($value);
       
   836             break;
       
   837           case 'background-color':
       
   838           case 'border-color':
       
   839           case 'scale-color':
       
   840             $this->__SetColorToValue("axis_" . str_replace(array("ackground", "-"),
       
   841                                                            array("g", ""),
       
   842                                                            $name),
       
   843                                      $value);
       
   844             break;
       
   845           case 'scale-font':
       
   846             $this->SetAxisScaleFont($value);
       
   847             break;
       
   848           case 'show-xscale':
       
   849             $this->axis_xscalevisible = ($value == 1 || $value == 'yes' ? 1 : 0);
       
   850             break;
       
   851           case 'show-yscale':
       
   852             $this->axis_yscalevisible = ($value == 1 || $value == 'yes' ? 1 : 0);
       
   853             break;
       
   854           case 'gridlines':
       
   855             $this->axis_gridlines = ($value == 1 || $value == 'yes' ? 1 : 0);
       
   856             break;
       
   857           case 'position':
       
   858             $this->SetAxisPositions($value);
       
   859             break;
       
   860           case 'deepness':
       
   861             $this->axis_deepness = (int) $value;
       
   862             break;
       
   863         }
       
   864       }
       
   865     }
       
   866 
       
   867     function __LoadScaleValues($data) {
       
   868       foreach ($data as $name => $value) {
       
   869         $name = strtolower($name);
       
   870         switch ($name) {
       
   871           case 'x-round':
       
   872             $this->SetScaleRoundX($value);
       
   873             break;
       
   874           case 'y-round':
       
   875             $this->SetScaleRoundY($value);
       
   876             break;
       
   877           case 'x-fun':
       
   878             $this->SetScaleFunctionX($value);
       
   879             break;
       
   880           case 'y-fun':
       
   881             $this->SetScaleFunctionY($value);
       
   882             break;
       
   883         }
       
   884       }
       
   885     }
       
   886     
       
   887     function __LoadLegendValues($data) {
       
   888       foreach ($data as $name => $value) {
       
   889         $name = strtolower($name);
       
   890         switch ($name) {
       
   891           case 'background-color':
       
   892           case 'border-color':
       
   893           case 'color':
       
   894             $this->__SetColorToValue("legend_" . str_replace(array("ackground", "-"),
       
   895                                                              array("g", ""),
       
   896                                                              $name),
       
   897                                      $value);
       
   898             break;
       
   899           case 'visible':
       
   900             $this->SetLegendVisible($value);
       
   901             break;
       
   902           case 'floating':
       
   903             $this->SetLegendFloating($value);
       
   904             break;
       
   905           case 'position':
       
   906             $this->SetLegendPosition($value);
       
   907             break;
       
   908           case 'borderwidth':
       
   909             $this->SetLegendBorderWidth($value);
       
   910             break;
       
   911           case 'padding':
       
   912             $this->SetLegendPadding($value);
       
   913             break;
       
   914           case 'inside-padding':
       
   915             $this->SetLegendInsidePadding($value);
       
   916             break;
       
   917           case 'data':
       
   918             $this->SetLegendData($value);
       
   919             break;
       
   920         }
       
   921       }
       
   922     }
       
   923 
       
   924     function __SetColorToValue($varname, $color, $index = false) {
       
   925       if (is_array($color)) {
       
   926         for ($i = 0; $i < count($color); $i++) {
       
   927           $this->__SetColorToValue($varname, $color[$i], $i);
       
   928         }
       
   929       } else {
       
   930         if ($color[0] == "#") { // if it's hex (html format), change to rgb array
       
   931           if (strlen($color) == 4) {
       
   932             // if only 3 hex values (I assume it's a shade of grey: #ddd)
       
   933             $color .= substr($color, -3);
       
   934           }
       
   935           $color = array(hexdec($color[1].$color[2]),
       
   936                          hexdec($color[3].$color[4]),
       
   937                          hexdec($color[5].$color[6]));
       
   938         }
       
   939         if ($index !== false) $this->{$varname}[$index] = $color;
       
   940         else $this->$varname = $color;
       
   941       }
       
   942     }
       
   943     
       
   944     function __AllocateColor($varname, $color, $alpha, $index = false) {
       
   945       if ($index !== false) {
       
   946         $this->{$varname}[$index] = imagecolorallocatealpha($this->im, $color[0], $color[1], $color[2], $alpha);
       
   947       } else {
       
   948         $this->$varname = imagecolorallocatealpha($this->im, $color[0], $color[1], $color[2], $alpha);
       
   949       }
       
   950     }
       
   951     
       
   952     function __DrawLegend() {
       
   953       if (!$this->legend_visible) return;
       
   954       
       
   955       $this->legend_height = $this->legend_insidepadding + (count($this->legend_data) * (imagefontheight($this->legend_font) + $this->legend_insidepadding));
       
   956 
       
   957       switch ($this->legend_position) {
       
   958         case 1:
       
   959           $x = $this->legend_padding;
       
   960           $y = $this->graph_height - $this->legend_padding - $this->legend_height;
       
   961           break;
       
   962         case 2:
       
   963           $x = $y = $this->legend_padding;
       
   964           break;
       
   965         case 3:
       
   966           $x = $this->graph_width - $this->legend_padding - $this->legend_width;
       
   967           $y = $this->legend_padding;
       
   968           break;
       
   969         case 4:
       
   970           $x = $this->graph_width - $this->legend_padding - $this->legend_width;
       
   971           $y = $this->graph_height - $this->legend_padding - $this->legend_height;
       
   972           break;
       
   973       }
       
   974       if ($this->legend_floating) {
       
   975         $x = $x + ($this->legend_position < 3 ? $this->graph_padding['left'] : -$this->graph_padding['right']);
       
   976         $y = $y + ($this->legend_position == 2 || $this->legend_position == 3 ? $this->graph_padding['top'] : -$this->graph_padding['bottom']);
       
   977       }
       
   978       $this->__AllocateColor("im_legend_bordercolor",
       
   979                              $this->legend_bordercolor,
       
   980                              $this->graph_transparencylevel);
       
   981       $this->__AllocateColor("im_legend_bgcolor",
       
   982                              $this->legend_bgcolor,
       
   983                              $this->graph_transparencylevel);
       
   984 
       
   985       imagefilledrectangle($this->im, $x + 1, $y + 1, $x + $this->legend_width - 1, $y + $this->legend_height - 1, $this->im_legend_bgcolor);
       
   986       imagerectangle($this->im, $x, $y, $x + $this->legend_width, $y + $this->legend_height, $this->im_legend_bordercolor);
       
   987       for ($i = 0; $i < count($this->legend_data); $i++) {
       
   988         $this->__AllocateColor("im_legend_color", $this->legend_color[$i], $this->graph_transparencylevel, $i);
       
   989         $this->__DrawLegendItem($x, $y, $i, $this->legend_data[$i], $this->im_legend_color[$i]);
       
   990       }
       
   991     }
       
   992     
       
   993     function __DrawLegendItem($legendx, $legendy, $position, $text, $color) {
       
   994       $x = $legendx + $this->legend_insidepadding * 3;
       
   995       $y = $legendy + $this->legend_insidepadding + (($this->legend_insidepadding + imagefontheight($this->legend_font)) * $position);
       
   996       imagefilledrectangle($this->im, $legendx + $this->legend_insidepadding,
       
   997                                       $y + ((imagefontheight($this->legend_font) - $this->legend_insidepadding) / 2),
       
   998                                       $legendx + $this->legend_insidepadding * 2,
       
   999                                       $y + ((imagefontheight($this->legend_font) - $this->legend_insidepadding) / 2) + $this->legend_insidepadding,
       
  1000                                       $color);
       
  1001       $this->__DrawText($text, $x, $y, $color, $this->legend_font, 0, 0);
       
  1002     }
       
  1003     
       
  1004     function __RoundNumber($n, $round = 1) {
       
  1005       if (is_numeric($n)) {
       
  1006         $weights = " KMG";
       
  1007         $p = 0;
       
  1008         while (abs($n) >= 1000) {
       
  1009           $n = $n / 1000;
       
  1010           $p++;
       
  1011         }
       
  1012         return number_format($n, $round) . trim($weights[$p]);
       
  1013       } else return $n;
       
  1014     }
       
  1015   }
       
  1016 ?>