[ Index ] |
|
Code source de Cr@wltr@ck 2.2.1 |
1 <?php 2 /* 3 * This work is hereby released into the Public Domain. 4 * To view a copy of the public domain dedication, 5 * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to 6 * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. 7 * 8 */ 9 10 require_once dirname(__FILE__)."/../Graph.class.php"; 11 12 /** 13 * Handle axis 14 * 15 * @package Artichow 16 */ 17 class awAxis { 18 19 /** 20 * Axis line 21 * 22 * @var Line 23 */ 24 public $line; 25 26 /** 27 * Axis labels 28 * 29 * @var Label 30 */ 31 public $label; 32 33 /** 34 * Axis title 35 * 36 * @var Label 37 */ 38 public $title; 39 40 /** 41 * Title position 42 * 43 * @var float 44 */ 45 protected $titlePosition = 0.5; 46 47 /** 48 * Labels number 49 * 50 * @var int 51 */ 52 protected $labelNumber; 53 54 /** 55 * Axis ticks 56 * 57 * @var array 58 */ 59 protected $ticks = array(); 60 61 /** 62 * Axis and ticks color 63 * 64 * @var Color 65 */ 66 protected $color; 67 68 /** 69 * Axis left and right padding 70 * 71 * @var Side 72 */ 73 protected $padding; 74 75 /** 76 * Axis range 77 * 78 * @var array 79 */ 80 protected $range; 81 82 /** 83 * Hide axis 84 * 85 * @var bool 86 */ 87 protected $hide = FALSE; 88 89 /** 90 * Auto-scaling mode 91 * 92 * @var bool 93 */ 94 protected $auto = TRUE; 95 96 /** 97 * Axis range callback function 98 * 99 * @var array 100 */ 101 protected $rangeCallback = array( 102 'toValue' => 'toProportionalValue', 103 'toPosition' => 'toProportionalPosition' 104 ); 105 106 /** 107 * Build the axis 108 * 109 * @param float $min Begin of the range of the axis 110 * @param float $max End of the range of the axis 111 */ 112 public function __construct($min = NULL, $max = NULL) { 113 114 $this->line = new awVector( 115 new awPoint(0, 0), 116 new awPoint(0, 0) 117 ); 118 119 $this->label = new awLabel; 120 $this->padding = new awSide; 121 122 $this->title = new awLabel( 123 NULL, 124 NULL, 125 NULL, 126 0 127 ); 128 129 $this->setColor(new awBlack); 130 131 if($min !== NULL and $max !== NULL) { 132 $this->setRange($min, $max); 133 } 134 135 } 136 137 /** 138 * Enable/disable auto-scaling mode 139 * 140 * @param bool $auto 141 */ 142 public function auto($auto) { 143 $this->auto = (bool)$auto; 144 } 145 146 /** 147 * Get auto-scaling mode status 148 * 149 * @return bool 150 */ 151 public function isAuto() { 152 return $this->auto; 153 } 154 155 /** 156 * Hide axis 157 * 158 * @param bool $hide 159 */ 160 public function hide($hide = TRUE) { 161 $this->hide = (bool)$hide; 162 } 163 164 /** 165 * Show axis 166 * 167 * @param bool $show 168 */ 169 public function show($show = TRUE) { 170 $this->hide = !(bool)$show; 171 } 172 173 /** 174 * Return a tick object from its name 175 * 176 * @param string $name Tick object name 177 * @return Tick 178 */ 179 public function tick($name) { 180 /* <php5> */ 181 return array_key_exists($name, $this->ticks) ? $this->ticks[$name] : NULL; 182 /* </php5> */ 183 /* <php4> -- 184 if(array_key_exists($name, $this->ticks)) { 185 return $tick = &$this->ticks[$name]; 186 } else { 187 return NULL; 188 } 189 -- </php4> */ 190 } 191 192 /** 193 * Add a tick object 194 * 195 * @param string $name Tick object name 196 * @param awTick $tick Tick object 197 */ 198 public function addTick($name, awTick $tick) { 199 /* <php5> */ 200 $this->ticks[$name] = $tick; 201 /* </php5> */ 202 /* <php4> -- 203 $this->ticks[$name] = &$tick; 204 -- </php4> */ 205 } 206 207 /** 208 * Delete a tick object 209 * 210 * @param string $name Tick object name 211 */ 212 public function deleteTick($name) { 213 if(array_key_exists($name, $this->ticks)) { 214 unset($this->ticks[$name]); 215 } 216 } 217 218 /** 219 * Hide all ticks 220 * 221 * @param bool $hide Hide or not ? 222 */ 223 public function hideTicks($hide = TRUE) { 224 /* <php5> */ 225 foreach($this->ticks as $tick) { 226 $tick->hide($hide); 227 } 228 /* </php5> */ 229 /* <php4> -- 230 foreach($this->ticks as $key => $tick) { 231 $this->ticks[$key]->hide($hide); 232 } 233 -- </php4> */ 234 } 235 236 /** 237 * Change ticks style 238 * 239 * @param int $style Ticks style 240 */ 241 public function setTickStyle($style) { 242 /* <php5> */ 243 foreach($this->ticks as $tick) { 244 $tick->setStyle($style); 245 } 246 /* </php5> */ 247 /* <php4> -- 248 foreach($this->ticks as $key => $tick) { 249 $this->ticks[$key]->setStyle($style); 250 } 251 -- </php4> */ 252 } 253 254 /** 255 * Change ticks interval 256 * 257 * @param int $interval Ticks interval 258 */ 259 public function setTickInterval($interval) { 260 /* <php5> */ 261 foreach($this->ticks as $tick) { 262 $tick->setInterval($interval); 263 } 264 /* </php5> */ 265 /* <php4> -- 266 foreach($this->ticks as $key => $tick) { 267 $this->ticks[$key]->setInterval($interval); 268 } 269 -- </php4> */ 270 } 271 272 /** 273 * Change number of ticks relative to others ticks 274 * 275 * @param awTick $to Change number of theses ticks 276 * @param awTick $from Ticks reference 277 * @param float $number Number of ticks by the reference 278 */ 279 public function setNumberByTick($to, $from, $number) { 280 $this->ticks[$to]->setNumberByTick($this->ticks[$from], $number); 281 } 282 283 /** 284 * Reverse ticks style 285 */ 286 public function reverseTickStyle() { 287 /* <php5> */ 288 foreach($this->ticks as $tick) { 289 if($tick->getStyle() === awTick::IN) { 290 $tick->setStyle(awTick::OUT); 291 } else if($tick->getStyle() === awTick::OUT) { 292 $tick->setStyle(awTick::IN); 293 } 294 } 295 /* </php5> */ 296 /* <php4> -- 297 foreach($this->ticks as $key => $tick) { 298 if($this->ticks[$key]->getStyle() === awTick::IN) { 299 $this->ticks[$key]->setStyle(awTick::OUT); 300 } else if($this->ticks[$key]->getStyle() === awTick::OUT) { 301 $this->ticks[$key]->setStyle(awTick::IN); 302 } 303 } 304 -- </php4> */ 305 } 306 307 /** 308 * Change interval of labels 309 * 310 * @param int $interval Interval 311 */ 312 public function setLabelInterval($interval) { 313 $this->auto(FALSE); 314 $this->setTickInterval($interval); 315 $this->label->setInterval($interval); 316 } 317 318 /** 319 * Change number of labels 320 * 321 * @param int $number Number of labels to display (can be NULL) 322 */ 323 public function setLabelNumber($number) { 324 $this->auto(FALSE); 325 $this->labelNumber = is_null($number) ? NULL : (int)$number; 326 } 327 328 /** 329 * Get number of labels 330 * 331 * @return int 332 */ 333 public function getLabelNumber() { 334 return $this->labelNumber; 335 } 336 337 /** 338 * Change precision of labels 339 * 340 * @param int $precision Precision 341 */ 342 public function setLabelPrecision($precision) { 343 $this->auto(FALSE); 344 $function = 'axis'.time().'_'.(microtime() * 1000000); 345 eval('function '.$function.'($value) { 346 return sprintf("%.'.(int)$precision.'f", $value); 347 }'); 348 $this->label->setCallbackFunction($function); 349 } 350 351 /** 352 * Change text of labels 353 * 354 * @param array $texts Some texts 355 */ 356 public function setLabelText($texts) { 357 if(is_array($texts)) { 358 $this->auto(FALSE); 359 $function = 'axis'.time().'_'.(microtime() * 1000000); 360 eval('function '.$function.'($value) { 361 $texts = '.var_export($texts, TRUE).'; 362 return isset($texts[$value]) ? $texts[$value] : \'?\'; 363 }'); 364 $this->label->setCallbackFunction($function); 365 } 366 } 367 368 /** 369 * Get the position of a point 370 * 371 * @param awAxis $xAxis X axis 372 * @param awAxis $yAxis Y axis 373 * @param awPoint $p Position of the point 374 * @return Point Position on the axis 375 */ 376 public static function toPosition(awAxis $xAxis, awAxis $yAxis, awPoint $p) { 377 378 $p1 = $xAxis->getPointFromValue($p->x); 379 $p2 = $yAxis->getPointFromValue($p->y); 380 381 return new awPoint( 382 round($p1->x), 383 round($p2->y) 384 ); 385 386 } 387 388 /** 389 * Change title alignment 390 * 391 * @param int $alignment New Alignment 392 */ 393 public function setTitleAlignment($alignment) { 394 395 switch($alignment) { 396 397 case awLabel::TOP : 398 $this->setTitlePosition(1); 399 $this->title->setAlign(NULL, awLabel::BOTTOM); 400 break; 401 402 case awLabel::BOTTOM : 403 $this->setTitlePosition(0); 404 $this->title->setAlign(NULL, awLabel::TOP); 405 break; 406 407 case awLabel::LEFT : 408 $this->setTitlePosition(0); 409 $this->title->setAlign(awLabel::LEFT); 410 break; 411 412 case awLabel::RIGHT : 413 $this->setTitlePosition(1); 414 $this->title->setAlign(awLabel::RIGHT); 415 break; 416 417 } 418 419 } 420 421 /** 422 * Change title position on the axis 423 * 424 * @param float $position A new awposition between 0 and 1 425 */ 426 public function setTitlePosition($position) { 427 $this->titlePosition = (float)$position; 428 } 429 430 /** 431 * Change axis and axis title color 432 * 433 * @param awColor $color 434 */ 435 public function setColor(awColor $color) { 436 $this->color = $color; 437 $this->title->setColor($color); 438 } 439 440 /** 441 * Change axis padding 442 * 443 * @param int $left Left padding in pixels 444 * @param int $right Right padding in pixels 445 */ 446 public function setPadding($left, $right) { 447 $this->padding->set($left, $right); 448 } 449 450 /** 451 * Get axis padding 452 * 453 * @return Side 454 */ 455 public function getPadding() { 456 return $this->padding; 457 } 458 459 /** 460 * Change axis range 461 * 462 * @param float $min 463 * @param float $max 464 */ 465 public function setRange($min, $max) { 466 if($min !== NULL) { 467 $this->range[0] = (float)$min; 468 } 469 if($max !== NULL) { 470 $this->range[1] = (float)$max; 471 } 472 } 473 474 /** 475 * Get axis range 476 * 477 * @return array 478 */ 479 public function getRange() { 480 return $this->range; 481 } 482 483 /** 484 * Change axis range callback function 485 * 486 * @param string $toValue Transform a position between 0 and 1 to a value 487 * @param string $toPosition Transform a value to a position between 0 and 1 on the axis 488 */ 489 public function setRangeCallback($toValue, $toPosition) { 490 $this->rangeCallback = array( 491 'toValue' => (string)$toValue, 492 'toPosition' => (string)$toPosition 493 ); 494 } 495 496 /** 497 * Center X values of the axis 498 * 499 * @param awAxis $axis An axis 500 * @param float $value The reference value on the axis 501 */ 502 public function setXCenter(awAxis $axis, $value) { 503 504 // Check vector angle 505 if($this->line->isVertical() === FALSE) { 506 awImage::drawError("Class Axis: setXCenter() can only be used on vertical axes."); 507 } 508 509 $p = $axis->getPointFromValue($value); 510 511 $this->line->setX( 512 $p->x, 513 $p->x 514 ); 515 516 } 517 518 /** 519 * Center Y values of the axis 520 * 521 * @param awAxis $axis An axis 522 * @param float $value The reference value on the axis 523 */ 524 public function setYCenter(awAxis $axis, $value) { 525 526 // Check vector angle 527 if($this->line->isHorizontal() === FALSE) { 528 awImage::drawError("Class Axis: setYCenter() can only be used on horizontal axes."); 529 } 530 531 $p = $axis->getPointFromValue($value); 532 533 $this->line->setY( 534 $p->y, 535 $p->y 536 ); 537 538 } 539 540 /** 541 * Get the distance between to values on the axis 542 * 543 * @param float $from The first value 544 * @param float $to The last value 545 * @return Point 546 */ 547 public function getDistance($from, $to) { 548 549 $p1 = $this->getPointFromValue($from); 550 $p2 = $this->getPointFromValue($to); 551 552 return $p1->getDistance($p2); 553 554 } 555 556 /** 557 * Get a point on the axis from a value 558 * 559 * @param float $value 560 * @return Point 561 */ 562 protected function getPointFromValue($value) { 563 564 $callback = $this->rangeCallback['toPosition']; 565 566 list($min, $max) = $this->range; 567 $position = $callback($value, $min, $max); 568 569 return $this->getPointFromPosition($position); 570 571 } 572 573 /** 574 * Get a point on the axis from a position 575 * 576 * @param float $position A position between 0 and 1 577 * @return Point 578 */ 579 protected function getPointFromPosition($position) { 580 581 $vector = $this->getVector(); 582 583 $angle = $vector->getAngle(); 584 $size = $vector->getSize(); 585 586 return $vector->p1->move( 587 cos($angle) * $size * $position, 588 -1 * sin($angle) * $size * $position 589 ); 590 591 } 592 593 /** 594 * Draw axis 595 * 596 * @param awDrawer $drawer A drawer 597 */ 598 public function draw(awDrawer $drawer) { 599 600 if($this->hide) { 601 return; 602 } 603 604 $vector = $this->getVector(); 605 606 // Draw axis ticks 607 $this->drawTicks($drawer, $vector); 608 609 // Draw axis line 610 $this->line($drawer); 611 612 // Draw labels 613 $this->drawLabels($drawer); 614 615 // Draw axis title 616 $p = $this->getPointFromPosition($this->titlePosition); 617 $this->title->draw($drawer, $p); 618 619 } 620 621 public function autoScale() { 622 623 if($this->isAuto() === FALSE) { 624 return; 625 } 626 627 list($min, $max) = $this->getRange(); 628 $interval = $max - $min; 629 630 if($interval > 0) { 631 $partMax = $max / $interval; 632 $partMin = $min / $interval; 633 } else { 634 $partMax = 0; 635 $partMin = 0; 636 } 637 638 $difference = log($interval) / log(10); 639 $difference = floor($difference); 640 641 $pow = pow(10, $difference); 642 643 if($pow > 0) { 644 $intervalNormalize = $interval / $pow; 645 } else { 646 $intervalNormalize = 0; 647 } 648 649 if($difference <= 0) { 650 651 $precision = $difference * -1 + 1; 652 653 if($intervalNormalize > 2) { 654 $precision--; 655 } 656 657 } else { 658 $precision = 0; 659 } 660 661 if($min != 0 and $max != 0) { 662 $precision++; 663 } 664 665 $this->setLabelPrecision($precision); 666 667 if($intervalNormalize <= 1.5) { 668 $intervalReal = 1.5; 669 $labelNumber = 4; 670 } else if($intervalNormalize <= 2) { 671 $intervalReal = 2; 672 $labelNumber = 5; 673 } else if($intervalNormalize <= 3) { 674 $intervalReal = 3; 675 $labelNumber = 4; 676 } else if($intervalNormalize <= 4) { 677 $intervalReal = 4; 678 $labelNumber = 5; 679 } else if($intervalNormalize <= 5) { 680 $intervalReal = 5; 681 $labelNumber = 6; 682 } else if($intervalNormalize <= 8) { 683 $intervalReal = 8; 684 $labelNumber = 5; 685 } else if($intervalNormalize <= 10) { 686 $intervalReal = 10; 687 $labelNumber = 6; 688 } 689 690 if($min == 0) { 691 692 $this->setRange( 693 $min, 694 $intervalReal * $pow 695 ); 696 697 } else if($max == 0) { 698 699 $this->setRange( 700 $intervalReal * $pow * -1, 701 0 702 ); 703 704 } 705 706 $this->setLabelNumber($labelNumber); 707 708 } 709 710 protected function line(awDrawer $drawer) { 711 712 $drawer->line( 713 $this->color, 714 $this->line 715 ); 716 717 } 718 719 protected function drawTicks(awDrawer $drawer, awVector $vector) { 720 721 foreach($this->ticks as $tick) { 722 $tick->setColor($this->color); 723 $tick->draw($drawer, $vector); 724 } 725 726 } 727 728 protected function drawLabels($drawer) { 729 730 if($this->labelNumber !== NULL) { 731 list($min, $max) = $this->range; 732 $number = $this->labelNumber - 1; 733 if($number < 1) { 734 return; 735 } 736 $function = $this->rangeCallback['toValue']; 737 $labels = array(); 738 for($i = 0; $i <= $number; $i++) { 739 $labels[] = $function($i / $number, $min, $max); 740 } 741 $this->label->set($labels); 742 } 743 744 $labels = $this->label->count(); 745 746 for($i = 0; $i < $labels; $i++) { 747 748 $p = $this->getPointFromValue($this->label->get($i)); 749 $this->label->draw($drawer, $p, $i); 750 751 } 752 753 } 754 755 protected function getVector() { 756 757 $angle = $this->line->getAngle(); 758 759 // Compute paddings 760 $vector = new awVector( 761 $this->line->p1->move( 762 cos($angle) * $this->padding->left, 763 -1 * sin($angle) * $this->padding->left 764 ), 765 $this->line->p2->move( 766 -1 * cos($angle) * $this->padding->right, 767 -1 * -1 * sin($angle) * $this->padding->right 768 ) 769 ); 770 771 return $vector; 772 773 } 774 775 public function __clone() { 776 777 $this->label = clone $this->label; 778 $this->line = clone $this->line; 779 $this->title = clone $this->title; 780 781 foreach($this->ticks as $name => $tick) { 782 $this->ticks[$name] = clone $tick; 783 } 784 785 } 786 787 } 788 789 registerClass('Axis'); 790 791 function toProportionalValue($position, $min, $max) { 792 return $min + ($max - $min) * $position; 793 } 794 795 function toProportionalPosition($value, $min, $max) { 796 if($max - $min == 0) { 797 return 0; 798 } 799 return ($value - $min) / ($max - $min); 800 } 801 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Sep 6 14:14:11 2007 | par Balluche grâce à PHPXref 0.7 |