| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * File containing the abstract ezcGraphAxisLabelRenderer class 4 * 5 * @package Graph 6 * @version 1.5 7 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved. 8 * @license http://ez.no/licenses/new_bsd New BSD License 9 */ 10 /** 11 * Abstract class to render labels and grids on axis. Will be extended to 12 * make it possible using different algorithms for rendering axis labels. 13 * 14 * Implements basic methods to render the grid and steps on a axis. 15 * 16 * @property bool $majorStepCount 17 * Count of major steps. 18 * @property bool $minorStepCount 19 * Count of minor steps. 20 * @property int $majorStepSize 21 * Size of major steps. 22 * @property int $minorStepSize 23 * Size of minor steps. 24 * @property bool $innerStep 25 * Indicates if steps are shown on the inner side of axis. 26 * @property bool $outerStep 27 * Indicates if steps are shown on the outer side of axis. 28 * @property bool $outerGrid 29 * Indicates if the grid is shown on the outer side of axis. 30 * @property bool $showLables 31 * Indicates if the labels should be shown 32 * @property int $labelPadding 33 * Padding of labels. 34 * 35 * @version 1.5 36 * @package Graph 37 */ 38 abstract class ezcGraphAxisLabelRenderer extends ezcBaseOptions 39 { 40 /** 41 * Driver to render axis labels 42 * 43 * @var ezcGraphDriver 44 */ 45 protected $driver; 46 47 /** 48 * Constructor 49 * 50 * @param array $options Default option array 51 * @return void 52 * @ignore 53 */ 54 public function __construct( array $options = array() ) 55 { 56 $this->properties['majorStepCount'] = false; 57 $this->properties['minorStepCount'] = false; 58 $this->properties['majorStepSize'] = 3; 59 $this->properties['minorStepSize'] = 1; 60 $this->properties['innerStep'] = true; 61 $this->properties['outerStep'] = false; 62 $this->properties['outerGrid'] = false; 63 $this->properties['showLabels'] = true; 64 $this->properties['labelPadding'] = 2; 65 66 parent::__construct( $options ); 67 } 68 69 /** 70 * __set 71 * 72 * @param mixed $propertyName 73 * @param mixed $propertyValue 74 * @throws ezcBaseValueException 75 * If a submitted parameter was out of range or type. 76 * @throws ezcBasePropertyNotFoundException 77 * If a the value for the property options is not an instance of 78 * @return void 79 * @ignore 80 */ 81 public function __set( $propertyName, $propertyValue ) 82 { 83 switch ( $propertyName ) 84 { 85 case 'driver': 86 if ( $propertyValue instanceof ezcGraphDriver ) 87 { 88 $this->properties['driver'] = $propertyValue; 89 } 90 else 91 { 92 throw new ezcGraphInvalidDriverException( $propertyValue ); 93 } 94 break; 95 case 'majorStepCount': 96 if ( ( $propertyValue !== false ) && 97 !is_numeric( $propertyValue ) || 98 ( $propertyValue < 0 ) ) 99 { 100 throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' ); 101 } 102 103 $this->properties['majorStepCount'] = (int) $propertyValue; 104 break; 105 case 'minorStepCount': 106 if ( ( $propertyValue !== false ) && 107 !is_numeric( $propertyValue ) || 108 ( $propertyValue < 0 ) ) 109 { 110 throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' ); 111 } 112 113 $this->properties['minorStepCount'] = (int) $propertyValue; 114 break; 115 case 'majorStepSize': 116 if ( !is_numeric( $propertyValue ) || 117 ( $propertyValue < 0 ) ) 118 { 119 throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' ); 120 } 121 122 $this->properties['majorStepSize'] = (int) $propertyValue; 123 break; 124 case 'minorStepSize': 125 if ( !is_numeric( $propertyValue ) || 126 ( $propertyValue < 0 ) ) 127 { 128 throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' ); 129 } 130 131 $this->properties['minorStepSize'] = (int) $propertyValue; 132 break; 133 case 'innerStep': 134 if ( !is_bool( $propertyValue ) ) 135 { 136 throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' ); 137 } 138 139 $this->properties['innerStep'] = (bool) $propertyValue; 140 break; 141 case 'outerStep': 142 if ( !is_bool( $propertyValue ) ) 143 { 144 throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' ); 145 } 146 147 $this->properties['outerStep'] = (bool) $propertyValue; 148 break; 149 case 'outerGrid': 150 if ( !is_bool( $propertyValue ) ) 151 { 152 throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' ); 153 } 154 155 $this->properties['outerGrid'] = (bool) $propertyValue; 156 break; 157 case 'showLabels': 158 if ( !is_bool( $propertyValue ) ) 159 { 160 throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' ); 161 } 162 163 $this->properties['showLabels'] = (bool) $propertyValue; 164 break; 165 case 'labelPadding': 166 if ( !is_numeric( $propertyValue ) || 167 ( $propertyValue < 0 ) ) 168 { 169 throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' ); 170 } 171 172 $this->properties['labelPadding'] = (int) $propertyValue; 173 break; 174 default: 175 throw new ezcBasePropertyNotFoundException( $propertyName ); 176 } 177 } 178 179 /** 180 * Checks for the cutting point of two lines. 181 * 182 * The lines are given by a start position and the direction of the line, 183 * both as instances of {@link ezcGraphCoordinate}. If no cutting point 184 * could be calculated, because the lines are parallel the function will 185 * return false. Otherwise the factor returned can be used to calculate the 186 * cutting point using the following equatation: 187 * point = $aStart + $factor * $aDir; 188 * 189 * We return the factor instead of the resulting point because it can be 190 * easily determined from the factor if the cutting point is in "behind" 191 * the line starting point, or if the distance to the cutting point is 192 * bigger then the direction vector is long ( $factor > 1 ). 193 * 194 * @param ezcGraphCoordinate $aStart 195 * @param ezcGraphCoordinate $aDir 196 * @param ezcGraphCoordinate $bStart 197 * @param ezcGraphCoordinate $bDir 198 * @return mixed 199 */ 200 public function determineLineCuttingPoint( ezcGraphCoordinate $aStart, ezcGraphCoordinate $aDir, ezcGraphCoordinate $bStart, ezcGraphCoordinate $bDir ) 201 { 202 // Check if lines are parallel 203 if ( ( ( abs( $aDir->x ) < .000001 ) && ( abs( $bDir->x ) < .000001 ) ) || 204 ( ( abs( $aDir->y ) < .000001 ) && ( abs( $bDir->y ) < .000001 ) ) || 205 ( ( abs( $aDir->x * $bDir->x * $aDir->y * $bDir->y ) > .000001 ) && 206 ( abs( ( $aDir->x / $aDir->y ) - ( $bDir->x / $bDir->y ) ) < .000001 ) 207 ) 208 ) 209 { 210 return false; 211 } 212 213 // Use ? : to prevent division by zero 214 $denominator = 215 ( abs( $aDir->y ) > .000001 ? $bDir->y / $aDir->y : .0 ) - 216 ( abs( $aDir->x ) > .000001 ? $bDir->x / $aDir->x : .0 ); 217 218 // Solve equatation 219 if ( abs( $denominator ) < .000001 ) 220 { 221 return - ( 222 ( abs( $aDir->y ) > .000001 ? $bStart->y / $aDir->y : .0 ) - 223 ( abs( $aDir->y ) > .000001 ? $aStart->y / $aDir->y : .0 ) - 224 ( abs( $aDir->x ) > .000001 ? $bStart->x / $aDir->x : .0 ) + 225 ( abs( $aDir->x ) > .000001 ? $aStart->x / $aDir->x : .0 ) 226 ); 227 } 228 else 229 { 230 return - ( 231 ( abs( $aDir->y ) > .000001 ? $bStart->y / $aDir->y : .0 ) - 232 ( abs( $aDir->y ) > .000001 ? $aStart->y / $aDir->y : .0 ) - 233 ( abs( $aDir->x ) > .000001 ? $bStart->x / $aDir->x : .0 ) + 234 ( abs( $aDir->x ) > .000001 ? $aStart->x / $aDir->x : .0 ) 235 ) / $denominator; 236 } 237 } 238 239 /** 240 * Draw single step on a axis 241 * 242 * Draws a step on a axis at the current position 243 * 244 * @param ezcGraphRenderer $renderer Renderer to draw the step with 245 * @param ezcGraphCoordinate $position Position of step 246 * @param ezcGraphCoordinate $direction Direction of axis 247 * @param int $axisPosition Position of axis 248 * @param int $size Step size 249 * @param ezcGraphColor $color Color of axis 250 * @return void 251 */ 252 public function drawStep( ezcGraphRenderer $renderer, ezcGraphCoordinate $position, ezcGraphCoordinate $direction, $axisPosition, $size, ezcGraphColor $color ) 253 { 254 if ( ! ( $this->innerStep || $this->outerStep ) ) 255 { 256 return false; 257 } 258 259 $drawStep = false; 260 if ( ( ( $axisPosition === ezcGraph::CENTER ) && $this->innerStep ) || 261 ( ( $axisPosition === ezcGraph::BOTTOM ) && $this->outerStep ) || 262 ( ( $axisPosition === ezcGraph::TOP ) && $this->innerStep ) || 263 ( ( $axisPosition === ezcGraph::RIGHT ) && $this->outerStep ) || 264 ( ( $axisPosition === ezcGraph::LEFT ) && $this->innerStep ) ) 265 { 266 // Turn direction vector to left by 90 degrees and multiply 267 // with major step size 268 $stepStart = new ezcGraphCoordinate( 269 $position->x + $direction->y * $size, 270 $position->y - $direction->x * $size 271 ); 272 $drawStep = true; 273 } 274 else 275 { 276 $stepStart = $position; 277 } 278 279 if ( ( ( $axisPosition === ezcGraph::CENTER ) && $this->innerStep ) || 280 ( ( $axisPosition === ezcGraph::BOTTOM ) && $this->innerStep ) || 281 ( ( $axisPosition === ezcGraph::TOP ) && $this->outerStep ) || 282 ( ( $axisPosition === ezcGraph::RIGHT ) && $this->innerStep ) || 283 ( ( $axisPosition === ezcGraph::LEFT ) && $this->outerStep ) ) 284 { 285 // Turn direction vector to right by 90 degrees and multiply 286 // with major step size 287 $stepEnd = new ezcGraphCoordinate( 288 $position->x - $direction->y * $size, 289 $position->y + $direction->x * $size 290 ); 291 $drawStep = true; 292 } 293 else 294 { 295 $stepEnd = $position; 296 } 297 298 if ( $drawStep ) 299 { 300 $renderer->drawStepLine( 301 $stepStart, 302 $stepEnd, 303 $color 304 ); 305 } 306 } 307 308 /** 309 * Draw non-rectangular grid lines grid 310 * 311 * Draws a grid line at the current position, for non-rectangular axis. 312 * 313 * @param ezcGraphRenderer $renderer Renderer to draw the grid with 314 * @param ezcGraphBoundings $boundings Boundings of axis 315 * @param ezcGraphCoordinate $position Position of step 316 * @param ezcGraphCoordinate $direction Direction of axis 317 * @param ezcGraphColor $color Color of axis 318 * @return void 319 */ 320 protected function drawNonRectangularGrid( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphCoordinate $position, ezcGraphCoordinate $direction, ezcGraphColor $color ) 321 { 322 // Direction of grid line is direction of axis turned right by 90 323 // degrees 324 $gridDirection = new ezcGraphCoordinate( 325 $direction->y, 326 - $direction->x 327 ); 328 329 $cuttingPoints = array(); 330 foreach ( array( // Bounding lines 331 array( 332 'start' => new ezcGraphCoordinate( $boundings->x0, $boundings->y0 ), 333 'dir' => new ezcGraphCoordinate( 0, $boundings->y1 - $boundings->y0 ) 334 ), 335 array( 336 'start' => new ezcGraphCoordinate( $boundings->x0, $boundings->y0 ), 337 'dir' => new ezcGraphCoordinate( $boundings->x1 - $boundings->x0, 0 ) 338 ), 339 array( 340 'start' => new ezcGraphCoordinate( $boundings->x1, $boundings->y1 ), 341 'dir' => new ezcGraphCoordinate( 0, $boundings->y0 - $boundings->y1 ) 342 ), 343 array( 344 'start' => new ezcGraphCoordinate( $boundings->x1, $boundings->y1 ), 345 'dir' => new ezcGraphCoordinate( $boundings->x0 - $boundings->x1, 0 ) 346 ), 347 ) as $boundingLine ) 348 { 349 // Test for cutting points with bounding lines, where cutting 350 // position is between 0 and 1, which means, that the line is hit 351 // on the bounding box rectangle. Use these points as a start and 352 // ending point for the grid lines. There should *always* be 353 // exactly two points returned. 354 $cuttingPosition = $this->determineLineCuttingPoint( 355 $boundingLine['start'], 356 $boundingLine['dir'], 357 $position, 358 $gridDirection 359 ); 360 361 if ( $cuttingPosition === false ) 362 { 363 continue; 364 } 365 366 $cuttingPosition = abs( $cuttingPosition ); 367 368 if ( ( $cuttingPosition >= 0 ) && 369 ( $cuttingPosition <= 1 ) ) 370 { 371 $cuttingPoints[] = new ezcGraphCoordinate( 372 $boundingLine['start']->x + $cuttingPosition * $boundingLine['dir']->x, 373 $boundingLine['start']->y + $cuttingPosition * $boundingLine['dir']->y 374 ); 375 } 376 } 377 378 if ( count( $cuttingPoints ) < 2 ) 379 { 380 // This should not happpen 381 return false; 382 } 383 384 // Finally draw grid line 385 $renderer->drawGridLine( 386 $cuttingPoints[0], 387 $cuttingPoints[1], 388 $color 389 ); 390 } 391 392 /** 393 * Draw rectangular grid 394 * 395 * Draws a grid line at the current position for rectangular directed axis. 396 * 397 * Method special for rectangularly directed axis to minimize the floating 398 * point calculation inaccuracies. Those are not necessary for rectangles, 399 * while for non-rectangular directed axis. 400 * 401 * @param ezcGraphRenderer $renderer Renderer to draw the grid with 402 * @param ezcGraphBoundings $boundings Boundings of axis 403 * @param ezcGraphCoordinate $position Position of step 404 * @param ezcGraphCoordinate $direction Direction of axis 405 * @param ezcGraphColor $color Color of axis 406 * @return void 407 */ 408 protected function drawRectangularGrid( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphCoordinate $position, ezcGraphCoordinate $direction, ezcGraphColor $color ) 409 { 410 if ( abs( $direction->x ) < .00001 ) 411 { 412 $renderer->drawGridLine( 413 new ezcGraphCoordinate( 414 $boundings->x0, 415 $position->y 416 ), 417 new ezcGraphCoordinate( 418 $boundings->x1, 419 $position->y 420 ), 421 $color 422 ); 423 } 424 else 425 { 426 $renderer->drawGridLine( 427 new ezcGraphCoordinate( 428 $position->x, 429 $boundings->y0 430 ), 431 new ezcGraphCoordinate( 432 $position->x, 433 $boundings->y1 434 ), 435 $color 436 ); 437 } 438 } 439 440 /** 441 * Draw grid 442 * 443 * Draws a grid line at the current position 444 * 445 * @param ezcGraphRenderer $renderer Renderer to draw the grid with 446 * @param ezcGraphBoundings $boundings Boundings of axis 447 * @param ezcGraphCoordinate $position Position of step 448 * @param ezcGraphCoordinate $direction Direction of axis 449 * @param ezcGraphColor $color Color of axis 450 * @return void 451 */ 452 protected function drawGrid( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphCoordinate $position, ezcGraphCoordinate $direction, ezcGraphColor $color ) 453 { 454 // Check if the axis direction is rectangular 455 if ( ( abs( $direction->x ) < .00001 ) || 456 ( abs( $direction->y ) < .00001 ) ) 457 { 458 return $this->drawRectangularGrid( $renderer, $boundings, $position, $direction, $color ); 459 } 460 else 461 { 462 return $this->drawNonRectangularGrid( $renderer, $boundings, $position, $direction, $color ); 463 } 464 } 465 466 /** 467 * Modify chart boundings 468 * 469 * Optionally modify boundings of chart data 470 * 471 * @param ezcGraphBoundings $boundings Current boundings of chart 472 * @param ezcGraphCoordinate $direction Direction of the current axis 473 * @return ezcGraphBoundings Modified boundings 474 */ 475 public function modifyChartBoundings( ezcGraphBoundings $boundings, ezcGraphCoordinate $direction ) 476 { 477 return $boundings; 478 } 479 480 /** 481 * Modify chart data position 482 * 483 * Optionally additionally modify the coodinate of a data point 484 * 485 * @param ezcGraphCoordinate $coordinate Data point coordinate 486 * @return ezcGraphCoordinate Modified coordinate 487 */ 488 public function modifyChartDataPosition( ezcGraphCoordinate $coordinate ) 489 { 490 return $coordinate; 491 } 492 493 /** 494 * Get axis space values 495 * 496 * Get axis space values, depending on passed parameters. If 497 * $innerBoundings is given it will be used to caclulat the axis spaces 498 * available for label rendering. If not given the legacy method will be 499 * used, which uses the xAxisSpace and yAxisSpace values calcualted by the 500 * renderer. 501 * 502 * Returns an array( $xSpace, $ySpace ), containing the irespective size in 503 * pixels. Additionally calculates the grid boundings passed by reference. 504 * 505 * @param ezcGraphRenderer $renderer 506 * @param ezcGraphBoundings $boundings 507 * @param mixed $innerBoundings 508 * @return array 509 */ 510 protected function getAxisSpace( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphChartElementAxis $axis, $innerBoundings, &$gridBoundings ) 511 { 512 if ( $innerBoundings !== null ) 513 { 514 $gridBoundings = clone $innerBoundings; 515 $xSpace = abs( $axis->position === ezcGraph::LEFT ? $innerBoundings->x0 - $boundings->x0 : $boundings->x1 - $innerBoundings->x1 ); 516 $ySpace = abs( $axis->position === ezcGraph::TOP ? $innerBoundings->y0 - $boundings->y0 : $boundings->y1 - $innerBoundings->y1 ); 517 } 518 else 519 { 520 $gridBoundings = new ezcGraphBoundings( 521 $boundings->x0 + ( $xSpace = abs( $renderer->xAxisSpace ) ), 522 $boundings->y0 + ( $ySpace = abs( $renderer->yAxisSpace ) ), 523 $boundings->x1 - $xSpace, 524 $boundings->y1 - $ySpace 525 ); 526 } 527 528 if ( $this->outerGrid ) 529 { 530 $gridBoundings = $boundings; 531 } 532 533 return array( $xSpace, $ySpace ); 534 } 535 536 /** 537 * Render Axis labels 538 * 539 * Render labels for an axis. 540 * 541 * @param ezcGraphRenderer $renderer Renderer used to draw the chart 542 * @param ezcGraphBoundings $boundings Boundings of the axis 543 * @param ezcGraphCoordinate $start Axis starting point 544 * @param ezcGraphCoordinate $end Axis ending point 545 * @param ezcGraphChartElementAxis $axis Axis instance 546 * @return void 547 */ 548 abstract public function renderLabels( 549 ezcGraphRenderer $renderer, 550 ezcGraphBoundings $boundings, 551 ezcGraphCoordinate $start, 552 ezcGraphCoordinate $end, 553 ezcGraphChartElementAxis $axis 554 ); 555 } 556 557 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Jul 28 15:48:31 2011 | Cross-referenced by PHPXref 0.7 |