[ Index ]

PHP Cross Reference of MyBB

title

Body

[close]

/inc/ -> class_graph.php (source)

   1  <?php
   2  /**
   3   * MyBB 1.6
   4   * Copyright 2010 MyBB Group, All Rights Reserved
   5   *
   6   * Website: http://mybb.com
   7   * License: http://mybb.com/about/license
   8   *
   9   * $Id $
  10   */
  11   
  12  class Graph {
  13  
  14      /**
  15       * The width of the image.
  16       *
  17       * @var integer
  18       */
  19      public $img_width = 1000;
  20      
  21      /**
  22       * The height of the image.
  23       *
  24       * @var integer
  25       */
  26      public $img_height = 300;
  27      
  28      /**
  29       * The image resource handle.
  30       *
  31       * @var resource
  32       */
  33      private $im;
  34      
  35      /**
  36       * The amount of x pixels to start inside the image for the graph
  37       *
  38       * @var integer
  39       */
  40      public $inside_x = 65;
  41      
  42      /**
  43       * The amount of y pixels to start inside the image for the graph
  44       *
  45       * @var integer
  46       */
  47      public $inside_y = 30;
  48      
  49      /**
  50       * The width of the inside graph
  51       *
  52       * @var integer
  53       */
  54      public $inside_width = 930;
  55      
  56      /**
  57       * The height of the inside graph
  58       *
  59       * @var integer
  60       */
  61      public $inside_height = 220;
  62      
  63      /**
  64       * The x, y points for the graph
  65       *
  66       * @var array
  67       */
  68      public $points = array();
  69      
  70      /**
  71       * The corresponding x labels for the graph
  72       *
  73       * @var integer
  74       */
  75      public $x_labels = array();
  76      
  77      /**
  78       * The bottom label for the graph
  79       *
  80       * @var integer
  81       */
  82      public $bottom_label = array();
  83  
  84      /**
  85       * Constructor of class. Initializes the barebore graph.
  86       *
  87       * @return Graph
  88       */
  89  	public function __construct()
  90      {
  91          // Setup initial graph layout
  92          
  93          // Check for GD >= 2, create base image
  94          if(gd_version() >= 2)
  95          {
  96              $this->im = imagecreatetruecolor($this->img_width, $this->img_height);
  97          }
  98          else
  99          {
 100              $this->im = imagecreate($this->img_width, $this->img_height);
 101          }
 102          
 103          // No GD support, die.
 104          if(!$this->im)
 105          {
 106              return false;
 107          }
 108          
 109          if(function_exists("imageantialias"))
 110          {
 111              imageantialias($this->im, true);
 112          }
 113  
 114          // Fill the background
 115          imagefill($this->im, 0, 0, $this->color(239, 239, 239));
 116          
 117          // Create our internal working graph box
 118          $inside_end_x = $this->inside_x+$this->inside_width;
 119          $inside_end_y = $this->inside_y+$this->inside_height;
 120          $this->image_create_rectangle($this->inside_x, $this->inside_y, $inside_end_x, $inside_end_y, 4, $this->color(254, 254, 254));
 121          
 122          // Draw our three lines inside our internal working graph area
 123          for($i = 1; $i < 4; ++$i)
 124          {
 125              $y_value = $this->inside_y+(($this->inside_height/4)*$i);
 126              imageline($this->im, $this->inside_x, $y_value, $inside_end_x, $y_value, $this->color(185, 185, 185));
 127          }
 128      }
 129      
 130      /**
 131       * Select and allocate a color to the internal image resource
 132       *
 133       * @param integer The red value
 134       * @param integer The green value
 135       * @param integer The blue value
 136       * @return integer A color identifier
 137       */
 138  	private function color($red, $green, $blue)
 139      {
 140          return imagecolorallocate($this->im, $red, $green, $blue);
 141      }
 142      
 143      /**
 144       * Creates a filled rectangle with optional rounded corners
 145       *
 146       * @param integer The initial x value
 147       * @param integer The initial y value
 148       * @param integer The ending x value
 149       * @param integer The ending y value
 150       * @param integer The optional radius
 151       * @param integer The optional rectangle color (defaults to black)
 152       */
 153  	private function image_create_rectangle($x1, $y1, $x2, $y2, $radius=1, $color=null)
 154      {
 155          if($color == null)
 156          {
 157              $color = $this->color(0, 0, 0);
 158          }
 159          
 160          // Draw our rectangle
 161          imagefilledrectangle($this->im, $x1, $y1+$radius, $x2, $y2-$radius, $color);
 162          imagefilledrectangle($this->im, $x1+$radius, $y1, $x2-$radius, $y2, $color);
 163          
 164          if($radius > 0)
 165          {
 166              $diameter = $radius*2;
 167  
 168              // Now draw our four corners on the rectangle
 169              imagefilledellipse($this->im, $x1+$radius, $y1+$radius, $diameter, $diameter, $color);
 170              imagefilledellipse($this->im, $x1+$radius, $y2-$radius, $diameter, $diameter, $color);
 171              imagefilledellipse($this->im, $x2-$radius, $y2-$radius, $diameter, $diameter, $color);
 172              imagefilledellipse($this->im, $x2-$radius, $y1+$radius, $diameter, $diameter, $color);
 173          }
 174      }
 175      
 176      /**
 177       * Creates a nicer thick line for angled lines
 178       *
 179       * @param integer The initial x value
 180       * @param integer The initial y value
 181       * @param integer The ending x value
 182       * @param integer The ending y value
 183       * @param integer The optional rectangle color (defaults to black)
 184       * @param integer The optional thickness (defaults to 1)
 185       */
 186  	private function imagelinethick($x1, $y1, $x2, $y2, $color, $thick = 1)
 187      {
 188          if ($thick == 1)
 189          {
 190              return imageline($this->im, $x1, $y1, $x2, $y2, $color);
 191          }
 192          
 193          $t = $thick / 2 - 0.5;
 194          if ($x1 == $x2 || $y1 == $y2)
 195          {
 196              return imagefilledrectangle($this->im, round(min($x1, $x2) - $t), round(min($y1, $y2) - $t), round(max($x1, $x2) + $t), round(max($y1, $y2) + $t), $color);
 197          }
 198          
 199          $k = ($y2 - $y1) / ($x2 - $x1); //y = kx + q
 200          $a = $t / sqrt(1 + pow($k, 2));
 201          $points = array(
 202              round($x1 - (1+$k)*$a), round($y1 + (1-$k)*$a),
 203              round($x1 - (1-$k)*$a), round($y1 - (1+$k)*$a),
 204              round($x2 + (1+$k)*$a), round($y2 - (1-$k)*$a),
 205              round($x2 + (1-$k)*$a), round($y2 + (1+$k)*$a),
 206          );
 207          imagefilledpolygon($this->im, $points, 4, $color);
 208          
 209          return imagepolygon($this->im, $points, 4, $color);
 210      }
 211      
 212      /**
 213       * Adds an array of x, y points to the internal points array
 214       *
 215       * @param array The array of x, y points to add
 216       */
 217  	public function add_points($points)
 218      {
 219          $this->points = array_merge($this->points, $points);
 220      }
 221      
 222      /**
 223       * Adds an array of x labels to the internal labels array
 224       *
 225       * @param array The array of x labels to add
 226       */
 227  	public function add_x_labels($labels)
 228      {
 229          $this->x_labels = array_merge($this->x_labels, $labels);
 230      }
 231      
 232      /**
 233       * Sets a bottom label
 234       *
 235       * @param string The bottom label to set
 236       */
 237  	public function set_bottom_label($label)
 238      {
 239          $this->bottom_label = $label;
 240      }
 241      
 242      /**
 243       * Renders the graph to memory
 244       *
 245       */
 246  	public function render()
 247      {
 248          // Get our max's and min's
 249          $asorted = $this->points;
 250          sort($asorted, SORT_NUMERIC);
 251          $min = $asorted[0];
 252          $max = $asorted[count($asorted)-1];
 253          
 254          // Scale based on how many points we need to shove into 930 pixels of width
 255          $x_delta = $this->inside_width/count($this->points);
 256          
 257          // Scale our y axis to 220 pixels
 258          $y_scale_factor = ($max-$min)/$this->inside_height;
 259          
 260          // Get our Y initial
 261          $y_initial = $this->inside_y+$this->inside_height;
 262          
 263          // Get our scale for finding our points of reference to place our x axis labels
 264          $x_label_scale = ceil(count($this->points)/20);
 265          $x_label_points = array();
 266          
 267          foreach($this->points as $x => $y)
 268          {            
 269              if(($x_label_scale == 0 || (($x+1) % $x_label_scale) == 0) && $x != 0)
 270              {
 271                  $x_label_points[] = $x;
 272                  
 273                  imagedashedline($this->im, $this->inside_x+($x_delta*$x), 30, $this->inside_x+($x_delta*$x), $y_initial, $this->color(185, 185, 185));
 274                  
 275                  imagefilledellipse($this->im, $this->inside_x+($x_delta*$x), $y_initial-$next_y_scaled+0.5, 8, 8, $this->color(84, 92, 209));
 276              }
 277              
 278              // Look ahead to find our next point, if there is one
 279              if(!array_key_exists($x+1, $this->points))
 280              {
 281                  break;
 282              }
 283              $next_y = $this->points[$x+1];
 284              
 285              if($y_scale_factor == 0)
 286              {
 287                  $y_scaled = $next_y_scaled = 0;
 288              }
 289              else
 290              {
 291                  $y_scaled = ($y-$min)/$y_scale_factor;
 292                  $next_y_scaled = ($next_y-$min)/$y_scale_factor;
 293              }
 294              
 295              // Draw our line
 296              $this->imagelinethick($this->inside_x+($x_delta*$x), $y_initial-$y_scaled, $this->inside_x+($x_delta*($x+1)), $y_initial-$next_y_scaled, $this->color(84, 92, 209), 3);
 297          }
 298          
 299          // Draw our x labels
 300          foreach($x_label_points as $x)
 301          {
 302              $label = $this->x_labels[$x];
 303              $text_width = imagefontwidth(2)*strlen($label);
 304              $x = $this->inside_x+($x_delta*$x)-($text_width/2);
 305              
 306              imagestring($this->im, 2, $x, $y_initial+5, $label, $this->color(0, 0, 0));
 307          }
 308          
 309          // Draw our bottom label
 310          imagestring($this->im, 2, ($this->img_width / 2), $y_initial+25, $this->bottom_label, $this->color(0, 0, 0));
 311          
 312          if($max > 4)
 313          {
 314              // Draw our y labels
 315              for($i = 1; $i < 4; ++$i)
 316              {
 317                  $y_value = $this->inside_y+(($this->inside_height/4)*$i);
 318                  imagestring($this->im, 2, 5, $y_value-7, my_number_format(round($min+(($max-$min)/4)*(4-$i))), $this->color(0, 0, 0));
 319              }
 320          }
 321          imagestring($this->im, 2, 5, $this->inside_y+$this->inside_height-7, my_number_format($min), $this->color(0, 0, 0));
 322          imagestring($this->im, 2, 5, $this->inside_y-7, my_number_format($max), $this->color(0, 0, 0));
 323      }
 324      
 325      /**
 326       * Outputs the graph to the screen in PNG format
 327       *
 328       */
 329  	public function output()
 330      {
 331          // Output the image
 332          header("Content-type: image/png");
 333          imagepng($this->im);
 334          imagedestroy($this->im);
 335          exit;
 336      }
 337  }
 338  
 339  ?>


Generated: Tue Oct 8 19:19:50 2013 Cross-referenced by PHPXref 0.7.1