| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * File containing the ezcGraphAxisRotatedLabelRenderer 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 * Can render axis labels rotated, so that more axis labels fit on one axis. 12 * Produces best results if the axis space was increased, so that more spcae is 13 * available below the axis. 14 * 15 * <code> 16 * $chart->xAxis->axisLabelRenderer = new ezcGraphAxisRotatedLabelRenderer(); 17 * 18 * // Define angle manually in degree 19 * $chart->xAxis->axisLabelRenderer->angle = 45; 20 * 21 * // Increase axis space 22 * $chart->xAxis->axisSpace = .2; 23 * </code> 24 * 25 * @property float $angle 26 * Angle of labels on axis in degrees. 27 * 28 * @version 1.5 29 * @package Graph 30 * @mainclass 31 */ 32 class ezcGraphAxisRotatedLabelRenderer extends ezcGraphAxisLabelRenderer 33 { 34 /** 35 * Store step array for later coordinate modifications 36 * 37 * @var array(ezcGraphStep) 38 */ 39 protected $steps; 40 41 /** 42 * Store direction for later coordinate modifications 43 * 44 * @var ezcGraphVector 45 */ 46 protected $direction; 47 48 /** 49 * Store coordinate width modifier for later coordinate modifications 50 * 51 * @var float 52 */ 53 protected $widthModifier; 54 55 /** 56 * Store coordinate offset for later coordinate modifications 57 * 58 * @var float 59 */ 60 protected $offset; 61 62 /** 63 * Constructor 64 * 65 * @param array $options Default option array 66 * @return void 67 * @ignore 68 */ 69 public function __construct( array $options = array() ) 70 { 71 parent::__construct( $options ); 72 $this->properties['angle'] = null; 73 $this->properties['labelOffset'] = true; 74 } 75 76 /** 77 * __set 78 * 79 * @param mixed $propertyName 80 * @param mixed $propertyValue 81 * @throws ezcBaseValueException 82 * If a submitted parameter was out of range or type. 83 * @throws ezcBasePropertyNotFoundException 84 * If a the value for the property options is not an instance of 85 * @return void 86 * @ignore 87 */ 88 public function __set( $propertyName, $propertyValue ) 89 { 90 switch ( $propertyName ) 91 { 92 case 'angle': 93 if ( !is_numeric( $propertyValue ) ) 94 { 95 throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float < 360' ); 96 } 97 98 $reducement = (int) ( $propertyValue - $propertyValue % 360 ); 99 $this->properties['angle'] = (float) $propertyValue - $reducement; 100 break; 101 102 case 'labelOffset': 103 if ( !is_bool( $propertyValue ) ) 104 { 105 throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' ); 106 } 107 108 $this->properties[$propertyName] = (bool) $propertyValue; 109 break; 110 111 default: 112 return parent::__set( $propertyName, $propertyValue ); 113 } 114 } 115 116 /** 117 * Determine label angle 118 * 119 * Determine the optiomal angle for the axis labels, of no angle has been 120 * provided by the user. 121 * 122 * @param array $steps 123 * @return void 124 */ 125 protected function determineAngle( array $steps, $xSpace, $ySpace, ezcGraphBoundings $axisBoundings ) 126 { 127 if ( $this->angle === null ) 128 { 129 $minimumStepWidth = null; 130 foreach ( $steps as $nr => $step ) 131 { 132 if ( ( $minimumStepWidth === null ) || 133 ( $step->width < $minimumStepWidth ) ) 134 { 135 $minimumStepWidth = $step->width; 136 } 137 } 138 139 $width = abs( 140 $axisBoundings->width * $minimumStepWidth * $this->direction->x + 141 $axisBoundings->height * $minimumStepWidth * $this->direction->y 142 ); 143 $height = abs( 144 $ySpace * $this->direction->x + 145 $xSpace * $this->direction->y 146 ); 147 148 $length = sqrt( pow( $width, 2 ) + pow( $height, 2 ) ); 149 $this->angle = rad2deg( acos( $height / $length ) ); 150 } 151 } 152 153 /** 154 * Determine text offset. 155 * 156 * Calculate the label offset and angle, from the configured or evaluated 157 * text angle. 158 * 159 * Returns the text angle in degrees. 160 * 161 * @param ezcGraphChartElementAxis $axis 162 * @param array $steps 163 * @return float 164 */ 165 protected function determineTextOffset( ezcGraphChartElementAxis $axis, array $steps ) { 166 // Determine additional required axis space by boxes 167 $firstStep = reset( $steps ); 168 $lastStep = end( $steps ); 169 170 $axisAngle = -$this->direction->angle( new ezcGraphVector( 1, 0 ) ); 171 $textAngle = $axisAngle + 172 deg2rad( $this->angle ) + 173 ( $axis->position & ( ezcGraph::TOP | ezcGraph::BOTTOM ) ? deg2rad( 270 ) : deg2rad( 90 ) ); 174 175 // Ensure angle between 0 and 360 degrees 176 $degTextAngle = rad2deg( $textAngle ); 177 while ( $degTextAngle < 0 ) 178 { 179 $degTextAngle += 360.; 180 } 181 182 if ( $this->properties['labelOffset'] ) 183 { 184 $this->offset = 185 ( $this->angle < 0 ? -1 : 1 ) * 186 ( $axis->position & ( ezcGraph::TOP | ezcGraph::LEFT ) ? 1 : -1 ) * 187 ( 1 - cos( deg2rad( $this->angle * 2 ) ) ); 188 } 189 else 190 { 191 $this->offset = 0; 192 } 193 194 return $degTextAngle; 195 } 196 197 /** 198 * Calculate label size 199 * 200 * Calculate the size of a single lable in a single step. 201 * 202 * @param array $steps 203 * @param int $nr 204 * @param array $step 205 * @param float $xSpace 206 * @param float $ySpace 207 * @param ezcGraphBoundings $axisBoundings 208 * @return float 209 */ 210 protected function calculateLabelSize( array $steps, $nr, $step, $xSpace, $ySpace, ezcGraphBoundings $axisBoundings ) 211 { 212 switch ( true ) 213 { 214 case ( $nr === 0 ): 215 $labelSize = min( 216 abs( 217 $xSpace * 2 * $this->direction->y + 218 $ySpace * 2 * $this->direction->x ), 219 abs( 220 $step->width * $axisBoundings->width * $this->direction->x + 221 $step->width * $axisBoundings->height * $this->direction->y ) 222 ); 223 break; 224 case ( $step->isLast ): 225 $labelSize = min( 226 abs( 227 $xSpace * 2 * $this->direction->y + 228 $ySpace * 2 * $this->direction->x ), 229 abs( 230 $steps[$nr - 1]->width * $axisBoundings->width * $this->direction->x + 231 $steps[$nr - 1]->width * $axisBoundings->height * $this->direction->y ) 232 ); 233 break; 234 default: 235 $labelSize = abs( 236 $step->width * $axisBoundings->width * $this->direction->x + 237 $step->width * $axisBoundings->height * $this->direction->y 238 ); 239 break; 240 } 241 242 return $labelSize * cos( deg2rad( $this->angle ) ); 243 } 244 245 /** 246 * Calculate general label length 247 * 248 * @param ezcGraphCoordinate $start 249 * @param ezcGraphCoordinate $end 250 * @param float $xSpace 251 * @param float $ySpace 252 * @param ezcGraphBoundings $axisBoundings 253 * @return float 254 */ 255 protected function calculateLabelLength( ezcGraphCoordinate $start, ezcGraphCoordinate $end, $xSpace, $ySpace, ezcGraphBoundings $axisBoundings ) 256 { 257 $axisSpaceFactor = abs( 258 ( $this->direction->x == 0 ? 0 : 259 $this->direction->x * $ySpace / $axisBoundings->width ) + 260 ( $this->direction->y == 0 ? 0 : 261 $this->direction->y * $xSpace / $axisBoundings->height ) 262 ); 263 264 $axisWidth = $end->x - $start->x; 265 $axisHeight = $end->y - $start->y; 266 267 $start->x += max( 0., $axisSpaceFactor * $this->offset ) * $axisWidth; 268 $start->y += max( 0., $axisSpaceFactor * $this->offset ) * $axisHeight; 269 270 $end->x += min( 0., $axisSpaceFactor * $this->offset ) * $axisWidth; 271 $end->y += min( 0., $axisSpaceFactor * $this->offset ) * $axisHeight; 272 273 $labelLength = sqrt( 274 pow( 275 $xSpace * $this->direction->y + 276 ( $this->labelOffset ? 277 $axisSpaceFactor * $this->offset * ( $end->x - $start->x ) : 278 $ySpace * 2 * $this->direction->x 279 ), 280 2 ) + 281 pow( 282 $ySpace * $this->direction->x + 283 ( $this->labelOffset ? 284 $axisSpaceFactor * $this->offset * ( $end->y - $start->y ) : 285 $xSpace * 2 * $this->direction->y 286 ), 287 2 ) 288 ); 289 290 $this->offset *= $axisSpaceFactor; 291 return $labelLength; 292 } 293 294 /** 295 * Render label text. 296 * 297 * Render the text of a single label, depending on the position, length and 298 * rotation of the label. 299 * 300 * @param ezcGraphRenderer $renderer 301 * @param ezcGraphChartElementAxis $axis 302 * @param ezcGraphCoordinate $position 303 * @param string $label 304 * @param float $degTextAngle 305 * @param float $labelLength 306 * @param float $labelSize 307 * @param float $lengthReducement 308 * @return void 309 */ 310 protected function renderLabelText( ezcGraphRenderer $renderer, ezcGraphChartElementAxis $axis, ezcGraphCoordinate $position, $label, $degTextAngle, $labelLength, $labelSize, $lengthReducement ) 311 { 312 switch ( true ) 313 { 314 case ( ( ( $degTextAngle >= 0 ) && 315 ( $degTextAngle < 90 ) && 316 ( ( $axis->position === ezcGraph::LEFT ) || 317 ( $axis->position === ezcGraph::RIGHT ) 318 ) 319 ) || 320 ( ( $degTextAngle >= 270 ) && 321 ( $degTextAngle < 360 ) && 322 ( ( $axis->position === ezcGraph::TOP ) || 323 ( $axis->position === ezcGraph::BOTTOM ) 324 ) 325 ) 326 ): 327 $labelBoundings = new ezcGraphBoundings( 328 $position->x, 329 $position->y, 330 $position->x + abs( $labelLength ) - $lengthReducement, 331 $position->y + $labelSize 332 ); 333 $labelAlignement = ezcGraph::LEFT | ezcGraph::TOP; 334 $labelRotation = $degTextAngle; 335 break; 336 case ( ( ( $degTextAngle >= 90 ) && 337 ( $degTextAngle < 180 ) && 338 ( ( $axis->position === ezcGraph::LEFT ) || 339 ( $axis->position === ezcGraph::RIGHT ) 340 ) 341 ) || 342 ( ( $degTextAngle >= 180 ) && 343 ( $degTextAngle < 270 ) && 344 ( ( $axis->position === ezcGraph::TOP ) || 345 ( $axis->position === ezcGraph::BOTTOM ) 346 ) 347 ) 348 ): 349 $labelBoundings = new ezcGraphBoundings( 350 $position->x - abs( $labelLength ) + $lengthReducement, 351 $position->y, 352 $position->x, 353 $position->y + $labelSize 354 ); 355 $labelAlignement = ezcGraph::RIGHT | ezcGraph::TOP; 356 $labelRotation = $degTextAngle - 180; 357 break; 358 case ( ( ( $degTextAngle >= 180 ) && 359 ( $degTextAngle < 270 ) && 360 ( ( $axis->position === ezcGraph::LEFT ) || 361 ( $axis->position === ezcGraph::RIGHT ) 362 ) 363 ) || 364 ( ( $degTextAngle >= 90 ) && 365 ( $degTextAngle < 180 ) && 366 ( ( $axis->position === ezcGraph::TOP ) || 367 ( $axis->position === ezcGraph::BOTTOM ) 368 ) 369 ) 370 ): 371 $labelBoundings = new ezcGraphBoundings( 372 $position->x - abs( $labelLength ) + $lengthReducement, 373 $position->y - $labelSize, 374 $position->x, 375 $position->y 376 ); 377 $labelAlignement = ezcGraph::RIGHT | ezcGraph::BOTTOM; 378 $labelRotation = $degTextAngle - 180; 379 break; 380 case ( ( ( $degTextAngle >= 270 ) && 381 ( $degTextAngle < 360 ) && 382 ( ( $axis->position === ezcGraph::LEFT ) || 383 ( $axis->position === ezcGraph::RIGHT ) 384 ) 385 ) || 386 ( ( $degTextAngle >= 0 ) && 387 ( $degTextAngle < 90 ) && 388 ( ( $axis->position === ezcGraph::TOP ) || 389 ( $axis->position === ezcGraph::BOTTOM ) 390 ) 391 ) 392 ): 393 $labelBoundings = new ezcGraphBoundings( 394 $position->x, 395 $position->y, 396 $position->x - abs( $labelLength ) + $lengthReducement, 397 $position->y + $labelSize 398 ); 399 $labelAlignement = ezcGraph::LEFT | ezcGraph::TOP; 400 $labelRotation = $degTextAngle; 401 break; 402 } 403 404 $renderer->drawText( 405 $labelBoundings, 406 $label, 407 $labelAlignement, 408 new ezcGraphRotation( 409 $labelRotation, 410 $position 411 ) 412 ); 413 } 414 415 /** 416 * Render Axis labels 417 * 418 * Render labels for an axis. 419 * 420 * @param ezcGraphRenderer $renderer Renderer used to draw the chart 421 * @param ezcGraphBoundings $boundings Boundings of the axis 422 * @param ezcGraphCoordinate $start Axis starting point 423 * @param ezcGraphCoordinate $end Axis ending point 424 * @param ezcGraphChartElementAxis $axis Axis instance 425 * @return void 426 */ 427 public function renderLabels( 428 ezcGraphRenderer $renderer, 429 ezcGraphBoundings $boundings, 430 ezcGraphCoordinate $start, 431 ezcGraphCoordinate $end, 432 ezcGraphChartElementAxis $axis, 433 ezcGraphBoundings $innerBoundings = null ) 434 { 435 // receive rendering parameters from axis 436 $steps = $axis->getSteps(); 437 438 $axisBoundings = new ezcGraphBoundings( 439 $start->x, $start->y, 440 $end->x, $end->y 441 ); 442 443 // Determine normalized axis direction 444 $this->direction = new ezcGraphVector( 445 $end->x - $start->x, 446 $end->y - $start->y 447 ); 448 $this->direction->unify(); 449 450 // Get axis space 451 $gridBoundings = null; 452 list( $xSpace, $ySpace ) = $this->getAxisSpace( $renderer, $boundings, $axis, $innerBoundings, $gridBoundings ); 453 454 // Determine optimal angle if none specified 455 $this->determineAngle( $steps, $xSpace, $ySpace, $axisBoundings ); 456 $degTextAngle = $this->determineTextOffset( $axis, $steps ); 457 $labelLength = $this->calculateLabelLength( $start, $end, $xSpace, $ySpace, $axisBoundings ); 458 459 // Draw steps and grid 460 foreach ( $steps as $nr => $step ) 461 { 462 $position = new ezcGraphCoordinate( 463 $start->x + ( $end->x - $start->x ) * $step->position * abs( $this->direction->x ), 464 $start->y + ( $end->y - $start->y ) * $step->position * abs( $this->direction->y ) 465 ); 466 467 $stepSize = new ezcGraphCoordinate( 468 ( $end->x - $start->x ) * $step->width, 469 ( $end->y - $start->y ) * $step->width 470 ); 471 472 // Calculate label boundings 473 $labelSize = $this->calculateLabelSize( $steps, $nr, $step, $xSpace, $ySpace, $axisBoundings ); 474 $lengthReducement = min( 475 abs( tan( deg2rad( $this->angle ) ) * ( $labelSize / 2 ) ), 476 abs( $labelLength / 2 ) 477 ); 478 479 $this->renderLabelText( $renderer, $axis, $position, $step->label, $degTextAngle, $labelLength, $labelSize, $lengthReducement ); 480 481 // Major grid 482 if ( $axis->majorGrid ) 483 { 484 $this->drawGrid( $renderer, $gridBoundings, $position, $stepSize, $axis->majorGrid ); 485 } 486 487 // Major step 488 $this->drawStep( $renderer, $position, $this->direction, $axis->position, $this->majorStepSize, $axis->border ); 489 } 490 } 491 492 /** 493 * Modify chart data position 494 * 495 * Optionally additionally modify the coodinate of a data point 496 * 497 * @param ezcGraphCoordinate $coordinate Data point coordinate 498 * @return ezcGraphCoordinate Modified coordinate 499 */ 500 public function modifyChartDataPosition( ezcGraphCoordinate $coordinate ) 501 { 502 return new ezcGraphCoordinate( 503 $coordinate->x * abs( $this->direction->y ) + 504 ( $coordinate->x * ( 1 - abs( $this->offset ) ) * abs( $this->direction->x ) ) + 505 ( abs( $this->offset ) * abs( $this->direction->x ) ), 506 $coordinate->y * abs( $this->direction->x ) + 507 ( $coordinate->y * ( 1 - abs( $this->offset ) ) * abs( $this->direction->y ) ) + 508 ( abs( $this->offset ) * abs( $this->direction->y ) ) 509 ); 510 } 511 } 512 ?>
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 |