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