[ Index ]

PHP Cross Reference of MyBB 1.8.27

title

Body

[close]

/inc/ -> class_graph.php (source)

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


2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup Cross-referenced by PHPXref