[ Index ]
 

Code source de vtiger CRM 5.0.2

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/Image/Graph/Plot/ -> Pie.php (source)

   1  <?php
   2  
   3  /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
   4  
   5  /**
   6   * Image_Graph - PEAR PHP OO Graph Rendering Utility.
   7   *
   8   * PHP versions 4 and 5
   9   *
  10   * LICENSE: This library is free software; you can redistribute it and/or modify
  11   * it under the terms of the GNU Lesser General Public License as published by
  12   * the Free Software Foundation; either version 2.1 of the License, or (at your
  13   * option) any later version. This library is distributed in the hope that it
  14   * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  15   * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
  16   * General Public License for more details. You should have received a copy of
  17   * the GNU Lesser General Public License along with this library; if not, write
  18   * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  19   * 02111-1307 USA
  20   *
  21   * @category   Images
  22   * @package    Image_Graph
  23   * @subpackage Plot
  24   * @author     Jesper Veggerby <pear.nosey@veggerby.dk>
  25   * @copyright  Copyright (C) 2003, 2004 Jesper Veggerby Hansen
  26   * @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
  27   * @version    CVS: $Id: Pie.php,v 1.19 2005/11/27 22:21:16 nosey Exp $
  28   * @link       http://pear.php.net/package/Image_Graph
  29   */
  30  
  31  /**
  32   * Include file Image/Graph/Plot.php
  33   */
  34  require_once  'Image/Graph/Plot.php';
  35  
  36  /**
  37   * 2D Piechart.
  38   *
  39   * @category   Images
  40   * @package    Image_Graph
  41   * @subpackage Plot
  42   * @author     Jesper Veggerby <pear.nosey@veggerby.dk>
  43   * @copyright  Copyright (C) 2003, 2004 Jesper Veggerby Hansen
  44   * @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
  45   * @version    Release: 0.7.2
  46   * @link       http://pear.php.net/package/Image_Graph
  47   */
  48  class Image_Graph_Plot_Pie extends Image_Graph_Plot
  49  {
  50  
  51      /**
  52       * The radius of the 'pie' spacing
  53       * @access private
  54       * @var int
  55       */
  56      var $_radius = 3;
  57  
  58      /**
  59       * Explode pie slices.
  60       * @access private
  61       * @var mixed
  62       */
  63      var $_explode = false;
  64  
  65      /**
  66       * The starting angle of the plot
  67       * @access private
  68       * @var int
  69       */
  70      var $_startingAngle = 0;
  71  
  72      /**
  73       * The angle direction (1 = CCW, -1 = CW)
  74       * @access private
  75       * @var int
  76       */
  77      var $_angleDirection = 1;
  78  
  79      /**
  80       * The diameter of the pie plot
  81       * @access private
  82       * @var int
  83       */
  84      var $_diameter = false;
  85      
  86      /**
  87       * Group items below this limit together as "the rest"
  88       * @access private
  89       * @var double
  90       */
  91      var $_restGroupLimit = false;
  92  
  93      /**
  94       * Rest group title
  95       * @access private
  96       * @var string
  97       */
  98      var $_restGroupTitle = 'The rest';
  99  
 100      /**
 101       * Perform the actual drawing on the legend.
 102       *
 103       * @param int $x0 The top-left x-coordinate
 104       * @param int $y0 The top-left y-coordinate
 105       * @param int $x1 The bottom-right x-coordinate
 106       * @param int $y1 The bottom-right y-coordinate
 107       * @access private
 108       */
 109      function _drawLegendSample($x0, $y0, $x1, $y1)
 110      {
 111          $y = ($y0 + $y1) / 2;
 112          $this->_canvas->pieslice(
 113              array(
 114                  'x' => $x1, 
 115                  'y' => $y, 
 116                  'rx' => abs($x1 - $x0) / 2, 
 117                  'ry' => abs($y1 - $y0) / 2, 
 118                  'v1' => 45, 
 119                  'v2' => 315
 120              )
 121          );
 122      }
 123  
 124      /**
 125       * Calculate marker point data
 126       *
 127       * @param array $point The point to calculate data for
 128       * @param array $nextPoint The next point
 129       * @param array $prevPoint The previous point
 130       * @param array $totals The pre-calculated totals, if needed
 131       * @return array An array containing marker point data
 132       * @access private
 133       */
 134      function _getMarkerData($point, $nextPoint, $prevPoint, &$totals)
 135      {
 136          $point = parent::_getMarkerData($point, $nextPoint, $prevPoint, $totals);
 137  
 138          $y = $totals['CURRENT_Y'];
 139          
 140          if ($this->_angleDirection < 0) {
 141              $y = $totals['ALL_SUM_Y'] - $y;
 142          }
 143  
 144          $point['ANGLE'] = 360 * (($y + ($point['Y'] / 2)) / $totals['ALL_SUM_Y']) + $this->_startingAngle;
 145          $totals['CURRENT_Y'] += $point['Y'];
 146  
 147          $point['ANG_X'] = cos(deg2rad($point['ANGLE']));
 148          $point['ANG_Y'] = sin(deg2rad($point['ANGLE']));
 149  
 150          $point['AX'] = -10 * $point['ANG_X'];
 151          $point['AY'] = -10 * $point['ANG_Y'];
 152  
 153          if ((isset($totals['ALL_SUM_Y'])) && ($totals['ALL_SUM_Y'] != 0)) {
 154              $point['PCT_MIN_Y'] = $point['PCT_MAX_Y'] = (100 * $point['Y'] / $totals['ALL_SUM_Y']);
 155          }
 156  
 157          $point['LENGTH'] = 10; //$radius;
 158  
 159          $x = $point['X'];
 160          $explodeRadius = 0;
 161          if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) {
 162              $explodeRadius = $this->_explode[$x];
 163          } elseif (is_numeric($this->_explode)) {
 164              $explodeRadius = $this->_explode;
 165          }
 166  
 167          $point['MARKER_X'] = $totals['CENTER_X'] +
 168              ($totals['RADIUS'] + $explodeRadius) * $point['ANG_X'];
 169          $point['MARKER_Y'] = $totals['CENTER_Y'] +
 170              ($totals['RADIUS'] + $explodeRadius) * $point['ANG_Y'];
 171  
 172          return $point;
 173      }
 174  
 175      /**
 176       * Draws markers on the canvas
 177       *
 178       * @access private
 179       */
 180      function _drawMarker()
 181      {
 182  
 183          if ($this->_marker) {
 184              $totals = $this->_getTotals();
 185  
 186              $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2);
 187              $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2);
 188  
 189              $totals['CURRENT_Y'] = 0;
 190              $number = 0;
 191              
 192              $diameter = $this->_getDiameter();
 193              
 194              $keys = array_keys($this->_dataset);
 195              foreach ($keys as $key) {
 196                  $dataset =& $this->_dataset[$key];
 197  
 198                  if (count($this->_dataset) == 1) {
 199                      $totals['RADIUS0'] = false;
 200                      $totals['RADIUS'] = $diameter / 2;
 201                  } else {
 202                      $dr = $diameter / (2 * count($this->_dataset));
 203  
 204                      $totals['RADIUS0'] = $number * $dr + ($number > 0 ? $this->_radius : 0);
 205                      $totals['RADIUS'] = ($number + 1) * $dr;
 206                  }
 207  
 208                  $totals['ALL_SUM_Y'] = 0;
 209                  $totals['CURRENT_Y'] = 0;
 210                  $dataset->_reset();
 211                  while ($point = $dataset->_next()) {
 212                      $totals['ALL_SUM_Y'] += $point['Y'];
 213                  }
 214  
 215                  $dataset->_reset();
 216                  $currentY = 0;
 217                  $the_rest = 0;
 218                  while ($point = $dataset->_next()) {
 219                      if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) {
 220                          $the_rest += $point['Y'];
 221                      }
 222                      else {
 223                          if ((!is_object($this->_dataSelector)) ||
 224                               ($this->_dataSelector->select($point))
 225                          ) {
 226                              $point = $this->_getMarkerData(
 227                                  $point,
 228                                  false,
 229                                  false,
 230                                  $totals
 231                              );
 232                              if (is_array($point)) {
 233                                  $this->_marker->_drawMarker(
 234                                      $point['MARKER_X'],
 235                                      $point['MARKER_Y'],
 236                                      $point
 237                                  );
 238                              }
 239                          }
 240                      }
 241                  }
 242                  if ($the_rest > 0) {
 243                      $point = array('X' => $this->_restGroupTitle, 'Y' => $the_rest);                   
 244                      $point = $this->_getMarkerData(
 245                              $point,
 246                              false,
 247                              false,
 248                              $totals
 249                          );
 250                          if (is_array($point)) {
 251                              $this->_marker->_drawMarker(
 252                                  $point['MARKER_X'],
 253                                  $point['MARKER_Y'],
 254                                  $point
 255                              );
 256                          }
 257                  }
 258                  $number++;
 259              }
 260              unset($keys);
 261          }
 262      }
 263  
 264      /**
 265       * Explodes a piece of this pie chart
 266       *
 267       * @param int $explode Radius to explode with (or an array)
 268       * @param string $x The 'x' value to explode or omitted
 269       */
 270      function explode($explode, $x = false)
 271      {
 272          if ($x === false) {
 273              $this->_explode = $explode;
 274          } else {
 275              $this->_explode[$x] = $explode;
 276          }
 277      }
 278      
 279      /**
 280       * Set the starting angle of the plot
 281       * 
 282       * East is 0 degrees
 283       * South is 90 degrees
 284       * West is 180 degrees
 285       * North is 270 degrees
 286       * 
 287       * It is also possible to specify the direction of the plot angles (i.e. clockwise 'cw' or 
 288       * counterclockwise 'ccw')
 289       */
 290      function setStartingAngle($angle = 0, $direction = 'ccw') 
 291      {
 292          $this->_startingAngle = ($angle % 360);
 293          $this->_angleDirection = ($direction == 'ccw' ? 1 : -1);
 294      }
 295      
 296      /**
 297       * Set the diameter of the pie plot (i.e. the number of pixels the
 298       * pie plot should be across)
 299       * 
 300       * Use 'max' for the maximum possible diameter
 301       * 
 302       * Use negative values for the maximum possible - minus this value (fx -2
 303       * to leave 1 pixel at each side)
 304       * 
 305       * @param mixed @diameter The number of pixels
 306       */
 307      function setDiameter($diameter)
 308      {
 309          $this->_diameter = $diameter;
 310      }
 311      
 312      /**
 313       * Set the limit for the y-value, where values below are grouped together
 314       * as "the rest"
 315       * 
 316       * @param double $limit The limit
 317       * @param string $title The title to display in the legends (default 'The
 318       * rest')
 319       */
 320      function setRestGroup($limit, $title = 'The rest')
 321      {
 322          $this->_restGroupLimit = $limit;
 323          $this->_restGroupTitle = $title;
 324      }    
 325      
 326      /**
 327       * Get the diameter of the plot
 328       * @return int The number of pixels the diameter is
 329       * @access private
 330       */
 331      function _getDiameter()
 332      {
 333          $diameter = 0;
 334          if ($this->_diameter === false) {
 335              $diameter = min($this->height(), $this->width()) * 0.75;
 336          }
 337          else {
 338              if ($this->_diameter === 'max') {
 339                  $diameter = min($this->height(), $this->width());
 340              }
 341              elseif ($this->_diameter < 0) {
 342                  $diameter = min($this->height(), $this->width()) + $this->_diameter;
 343              } else {
 344                  $diameter = $this->_diameter;
 345              }
 346          }
 347          return $diameter;
 348      }
 349       
 350  
 351      /**
 352       * Output the plot
 353       *
 354       * @return bool Was the output 'good' (true) or 'bad' (false).
 355       * @access private
 356       */
 357      function _done()
 358      {
 359          if (parent::_done() === false) {
 360              return false;
 361          }
 362  
 363          $number = 0;
 364  
 365          $keys = array_keys($this->_dataset);
 366          foreach ($keys as $key) {
 367              $dataset =& $this->_dataset[$key];
 368  
 369              $totalY = 0;
 370              $dataset->_reset();
 371              while ($point = $dataset->_next()) {
 372                  $totalY += $point['Y'];
 373              }
 374  
 375              $centerX = (int) (($this->_left + $this->_right) / 2);
 376              $centerY = (int) (($this->_top + $this->_bottom) / 2);
 377              $diameter = $this->_getDiameter();
 378              if ($this->_angleDirection < 0) {
 379                  $currentY = $totalY;
 380              } else {                
 381                  $currentY = 0; //rand(0, 100)*$totalY/100;
 382              }            
 383              $dataset->_reset();
 384  
 385              if (count($this->_dataset) == 1) {
 386                  $radius0 = false;
 387                  $radius1 = $diameter / 2;
 388              } else {
 389                  $dr = $diameter / (2 * count($this->_dataset));
 390  
 391                  $radius0 = $number * $dr + ($number > 0 ? $this->_radius : 0);
 392                  $radius1 = ($number + 1) * $dr;
 393              }
 394  
 395              $the_rest = 0;
 396              while ($point = $dataset->_next()) {
 397                  if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) {
 398                      $the_rest += $point['Y'];
 399                  }
 400                  else {
 401                      $angle1 = 360 * ($currentY / $totalY) + $this->_startingAngle;
 402                      $currentY += $this->_angleDirection * $point['Y'];
 403                      $angle2 = 360 * ($currentY / $totalY) + $this->_startingAngle;
 404      
 405                      $x = $point['X'];
 406                      $id = $point['ID'];
 407      
 408                      $dX = 0;
 409                      $dY = 0;
 410                      $explodeRadius = 0;
 411                      if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) {
 412                          $explodeRadius = $this->_explode[$x];
 413                      } elseif (is_numeric($this->_explode)) {
 414                          $explodeRadius = $this->_explode;
 415                      }
 416      
 417                      if ($explodeRadius > 0) {
 418                          $dX = $explodeRadius * cos(deg2rad(($angle1 + $angle2) / 2));
 419                          $dY = $explodeRadius * sin(deg2rad(($angle1 + $angle2) / 2));
 420                      }
 421      
 422                      $ID = $point['ID'];
 423                      $this->_getFillStyle($ID);
 424                      $this->_getLineStyle($ID);
 425                      $this->_canvas->pieslice(
 426                          $this->_mergeData(
 427                              $point,
 428                              array(
 429                                  'x' => $centerX + $dX, 
 430                                  'y' => $centerY + $dY, 
 431                                  'rx' => $radius1, 
 432                                  'ry' => $radius1, 
 433                                  'v1' => $angle1, 
 434                                  'v2' => $angle2, 
 435                                  'srx' => $radius0, 
 436                                  'sry' => $radius0
 437                              )
 438                          )
 439                      );
 440                  }
 441              }
 442              
 443              if ($the_rest > 0) {
 444                  $angle1 = 360 * ($currentY / $totalY) + $this->_startingAngle;
 445                  $currentY += $this->_angleDirection * $the_rest;
 446                  $angle2 = 360 * ($currentY / $totalY) + $this->_startingAngle;
 447  
 448                  $x = 'rest';
 449                  $id = 'rest';
 450  
 451                  $dX = 0;
 452                  $dY = 0;
 453                  $explodeRadius = 0;
 454                  if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) {
 455                      $explodeRadius = $this->_explode[$x];
 456                  } elseif (is_numeric($this->_explode)) {
 457                      $explodeRadius = $this->_explode;
 458                  }
 459  
 460                  if ($explodeRadius > 0) {
 461                      $dX = $explodeRadius * cos(deg2rad(($angle1 + $angle2) / 2));
 462                      $dY = $explodeRadius * sin(deg2rad(($angle1 + $angle2) / 2));
 463                  }
 464  
 465                  $ID = $id;
 466                  $this->_getFillStyle($ID);
 467                  $this->_getLineStyle($ID);
 468                  $this->_canvas->pieslice(
 469                      $this->_mergeData(
 470                          $point,
 471                          array(
 472                              'x' => $centerX + $dX, 
 473                              'y' => $centerY + $dY, 
 474                              'rx' => $radius1, 
 475                              'ry' => $radius1, 
 476                              'v1' => $angle1, 
 477                              'v2' => $angle2, 
 478                              'srx' => $radius0, 
 479                              'sry' => $radius0
 480                          )
 481                      )
 482                  );
 483              }
 484              $number++;
 485          }
 486          unset($keys);
 487          $this->_drawMarker();
 488          return true;
 489      }
 490  
 491      /**
 492       * Draw a sample for use with legend
 493       *
 494       * @param array $param The parameters for the legend
 495       * @access private
 496       */
 497      function _legendSample(&$param)
 498      {
 499          if (is_array($this->_dataset)) {
 500              
 501              $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
 502              $this->_clip(true);
 503              
 504              $totals = $this->_getTotals();
 505              $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2);
 506              $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2);
 507              $totals['RADIUS'] = min($this->height(), $this->width()) * 0.75 * 0.5;
 508              $totals['CURRENT_Y'] = 0;
 509  
 510              if (is_a($this->_fillStyle, "Image_Graph_Fill")) {
 511                  $this->_fillStyle->_reset();
 512              }
 513  
 514              $count = 0;
 515              $keys = array_keys($this->_dataset);
 516              foreach ($keys as $key) {
 517                  $dataset =& $this->_dataset[$key];
 518                  $count++;
 519      
 520                  $dataset->_reset();
 521                  $the_rest = 0;
 522                  while ($point = $dataset->_next()) {
 523                      $caption = $point['X'];
 524                      if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) {
 525                          $the_rest += $point['Y'];
 526                      }
 527                      else {    
 528                          $this->_canvas->setFont($param['font']);
 529                          $width = 20 + $param['width'] + $this->_canvas->textWidth($caption);
 530                          $param['maxwidth'] = max($param['maxwidth'], $width);
 531                          $x2 = $param['x'] + $width;
 532                          $y2 = $param['y'] + $param['height']+5;
 533                              
 534                          if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) {
 535                              $param['y'] = $param['top'];
 536                              $param['x'] = $x2;
 537                              $y2 = $param['y'] + $param['height'];
 538                          } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) {
 539                              $param['x'] = $param['left'];
 540                              $param['y'] = $y2;
 541                              $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption);
 542                          }
 543          
 544                          $x = $x0 = $param['x'];
 545                          $y = $param['y'];
 546                          $y0 = $param['y'] - $param['height']/2;
 547                          $x1 = $param['x'] + $param['width'];
 548                          $y1 = $param['y'] + $param['height']/2;
 549          
 550                          if (!isset($param['simulate'])) {
 551                              $this->_getFillStyle($point['ID']);
 552                              $this->_getLineStyle($point['ID']);
 553                              $this->_drawLegendSample($x0, $y0, $x1, $y1);
 554          
 555                              if (($this->_marker) && ($dataset) && ($param['show_marker'])) {
 556                                  $prevPoint = $dataset->_nearby(-2);
 557                                  $nextPoint = $dataset->_nearby();
 558          
 559                                  $p = $this->_getMarkerData($point, $nextPoint, $prevPoint, $totals);
 560                                  if (is_array($point)) {
 561                                      $p['MARKER_X'] = $x+$param['width']/2;
 562                                      $p['MARKER_Y'] = $y;
 563                                      unset ($p['AVERAGE_Y']);
 564                                      $this->_marker->_drawMarker($p['MARKER_X'], $p['MARKER_Y'], $p);
 565                                  }
 566                              }
 567                              $this->write($x + $param['width'] +10, $y, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']);
 568                          }
 569          
 570                          if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) {
 571                              $param['y'] = $y2;
 572                          } else {
 573                              $param['x'] = $x2;
 574                          }                        
 575                      }
 576                  }
 577                  if ($the_rest > 0) {
 578                      $this->_canvas->setFont($param['font']);
 579                      $width = 20 + $param['width'] + $this->_canvas->textWidth($this->_restGroupTitle);
 580                      $param['maxwidth'] = max($param['maxwidth'], $width);
 581                      $x2 = $param['x'] + $width;
 582                      $y2 = $param['y'] + $param['height']+5;
 583                          
 584                      if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) {
 585                          $param['y'] = $param['top'];
 586                          $param['x'] = $x2;
 587                          $y2 = $param['y'] + $param['height'];
 588                      } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) {
 589                          $param['x'] = $param['left'];
 590                          $param['y'] = $y2;
 591                          $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($this->_restGroupTitle);
 592                      }
 593      
 594                      $x = $x0 = $param['x'];
 595                      $y = $param['y'];
 596                      $y0 = $param['y'] - $param['height']/2;
 597                      $x1 = $param['x'] + $param['width'];
 598                      $y1 = $param['y'] + $param['height']/2;
 599      
 600                      if (!isset($param['simulate'])) {
 601                          $this->_getFillStyle('rest');
 602                          $this->_getLineStyle('rest');
 603                          $this->_drawLegendSample($x0, $y0, $x1, $y1);
 604      
 605                          $this->write($x + $param['width'] + 10, $y, $this->_restGroupTitle, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']);
 606                      }
 607      
 608                      if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) {
 609                          $param['y'] = $y2;
 610                      } else {
 611                          $param['x'] = $x2;
 612                      }
 613                  }
 614              }
 615              unset($keys);
 616              $this->_clip(false);
 617              $this->_canvas->endGroup();
 618          }
 619      }
 620  
 621  }
 622  
 623  ?>


Généré le : Sun Feb 25 10:22:19 2007 par Balluche grâce à PHPXref 0.7