| [ Index ] |
|
Code source de vtiger CRM 5.0.2 |
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 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sun Feb 25 10:22:19 2007 | par Balluche grâce à PHPXref 0.7 |