| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * File containing the ezcGraphRadarChart 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 * Class for radar charts. 12 * Can make use of an unlimited amount of datasets and will display them as 13 * lines by default. 14 * Rotation axis: 15 * - Labeled axis 16 * - Centered axis label renderer 17 * Axis: 18 * - Numeric axis 19 * - radar axis label renderer 20 * 21 * <code> 22 * // Create a new radar chart 23 * $chart = new ezcGraphRadarChart(); 24 * 25 * // Add data to line chart 26 * $chart->data['sample dataset'] = new ezcGraphArrayDataSet( 27 * array( 28 * '100' => 1.2, 29 * '200' => 43.2, 30 * '300' => -34.14, 31 * '350' => 65, 32 * '400' => 123, 33 * ) 34 * ); 35 * 36 * // Render chart with default 2d renderer and default SVG driver 37 * $chart->render( 500, 200, 'radar_chart.svg' ); 38 * </code> 39 * 40 * Each chart consists of several chart elements which represents logical 41 * parts of the chart and can be formatted independently. The line chart 42 * consists of: 43 * - title ( {@link ezcGraphChartElementText} ) 44 * - legend ( {@link ezcGraphChartElementLegend} ) 45 * - background ( {@link ezcGraphChartElementBackground} ) 46 * - axis ( {@link ezcGraphChartElementNumericAxis} ) 47 * - ratation axis ( {@link ezcGraphChartElementLabeledAxis} ) 48 * 49 * The type of the axis may be changed and all elements can be configured by 50 * accessing them as properties of the chart: 51 * 52 * The chart itself also offers several options to configure the appearance. 53 * The extended configure options are available in 54 * {@link ezcGraphRadarChartOptions} extending the 55 * {@link ezcGraphChartOptions}. 56 * 57 * <code> 58 * $chart->legend->position = ezcGraph::RIGHT; 59 * </code> 60 * 61 * @property ezcGraphRadarChartOptions $options 62 * Chart options class 63 * 64 * @version 1.5 65 * @package Graph 66 * @mainclass 67 */ 68 class ezcGraphRadarChart extends ezcGraphChart 69 { 70 /** 71 * Store major grid color for child axis. 72 * 73 * @var ezcGraphColor 74 */ 75 protected $childAxisColor; 76 77 /** 78 * Constructor 79 * 80 * @param array $options Default option array 81 * @return void 82 * @ignore 83 */ 84 public function __construct( array $options = array() ) 85 { 86 $this->options = new ezcGraphRadarChartOptions( $options ); 87 $this->options->highlightFont = $this->options->font; 88 89 parent::__construct(); 90 91 $this->elements['rotationAxis'] = new ezcGraphChartElementLabeledAxis(); 92 93 $this->addElement( 'axis', new ezcGraphChartElementNumericAxis() ); 94 $this->elements['axis']->position = ezcGraph::BOTTOM; 95 $this->elements['axis']->axisLabelRenderer = new ezcGraphAxisRadarLabelRenderer(); 96 $this->elements['axis']->axisLabelRenderer->outerStep = true; 97 98 $this->addElement( 'rotationAxis', new ezcGraphChartElementLabeledAxis() ); 99 100 // Do not render axis with default method, because we need an axis for 101 // each label in dataset 102 $this->renderElement['axis'] = false; 103 $this->renderElement['rotationAxis'] = false; 104 } 105 106 /** 107 * Set colors and border fro this element 108 * 109 * @param ezcGraphPalette $palette Palette 110 * @return void 111 */ 112 public function setFromPalette( ezcGraphPalette $palette ) 113 { 114 $this->childAxisColor = $palette->majorGridColor; 115 116 parent::setFromPalette( $palette ); 117 } 118 119 /** 120 * Property write access 121 * 122 * @throws ezcBasePropertyNotFoundException 123 * If Option could not be found 124 * @throws ezcBaseValueException 125 * If value is out of range 126 * @param string $propertyName Option name 127 * @param mixed $propertyValue Option value; 128 * @return void 129 * @ignore 130 */ 131 public function __set( $propertyName, $propertyValue ) 132 { 133 switch ( $propertyName ) { 134 case 'axis': 135 if ( $propertyValue instanceof ezcGraphChartElementAxis ) 136 { 137 $this->addElement( 'axis', $propertyValue ); 138 $this->elements['axis']->position = ezcGraph::BOTTOM; 139 $this->elements['axis']->axisLabelRenderer = new ezcGraphAxisRadarLabelRenderer(); 140 $this->renderElement['axis'] = false; 141 } 142 else 143 { 144 throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphChartElementAxis' ); 145 } 146 break; 147 case 'rotationAxis': 148 if ( $propertyValue instanceof ezcGraphChartElementAxis ) 149 { 150 $this->addElement( 'rotationAxis', $propertyValue ); 151 $this->renderElement['rotationAxis'] = false; 152 } 153 else 154 { 155 throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphChartElementAxis' ); 156 } 157 break; 158 case 'renderer': 159 if ( $propertyValue instanceof ezcGraphRadarRenderer ) 160 { 161 parent::__set( $propertyName, $propertyValue ); 162 } 163 else 164 { 165 throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphRadarRenderer' ); 166 } 167 break; 168 default: 169 parent::__set( $propertyName, $propertyValue ); 170 } 171 } 172 173 /** 174 * Draws a single rotated axis 175 * 176 * Sets the axis label position depending on the axis rotation. 177 * 178 * @param ezcGraphChartElementAxis $axis 179 * @param ezcGraphBoundings $boundings 180 * @param ezcGraphCoordinate $center 181 * @param float $position 182 * @param float $lastPosition 183 * @return void 184 */ 185 protected function drawRotatedAxis( ezcGraphChartElementAxis $axis, ezcGraphBoundings $boundings, ezcGraphCoordinate $center, $position, $lastPosition = null ) 186 { 187 // Set axis position depending on angle for better axis label 188 // positioning 189 $angle = $position * 2 * M_PI; 190 switch ( (int) ( ( $position + .125 ) * 4 ) ) 191 { 192 case 0: 193 case 4: 194 $axis->position = ezcGraph::BOTTOM; 195 break; 196 case 1: 197 $axis->position = ezcGraph::LEFT; 198 break; 199 case 2: 200 $axis->position = ezcGraph::TOP; 201 break; 202 case 3: 203 $axis->position = ezcGraph::RIGHT; 204 break; 205 } 206 207 // Set last step to correctly draw grid 208 if ( $axis->axisLabelRenderer instanceof ezcGraphAxisRadarLabelRenderer ) 209 { 210 $axis->axisLabelRenderer->lastStep = $lastPosition; 211 } 212 213 // Do not draw axis label for last step 214 if ( abs( $position - 1 ) <= .001 ) 215 { 216 $axis->label = null; 217 } 218 219 $this->renderer->drawAxis( 220 $boundings, 221 clone $center, 222 $dest = new ezcGraphCoordinate( 223 $center->x + sin( $angle ) * ( $boundings->width / 2 ), 224 $center->y - cos( $angle ) * ( $boundings->height / 2 ) 225 ), 226 clone $axis, 227 clone $axis->axisLabelRenderer 228 ); 229 } 230 231 /** 232 * Render the assigned data 233 * 234 * Will renderer all charts data in the remaining boundings after drawing 235 * all other chart elements. The data will be rendered depending on the 236 * settings in the dataset. 237 * 238 * @param ezcGraphRenderer $renderer Renderer 239 * @param ezcGraphBoundings $boundings Remaining boundings 240 * @return void 241 */ 242 protected function renderData( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings ) 243 { 244 // Apply axis space 245 $xAxisSpace = ( $boundings->x1 - $boundings->x0 ) * $this->axis->axisSpace; 246 $yAxisSpace = ( $boundings->y1 - $boundings->y0 ) * $this->axis->axisSpace; 247 248 $center = new ezcGraphCoordinate( 249 ( $boundings->width / 2 ), 250 ( $boundings->height / 2 ) 251 ); 252 253 // We do not differentiate between display types in radar charts. 254 $nr = $count = count( $this->data ); 255 256 // Draw axis at major steps of virtual axis 257 $steps = $this->elements['rotationAxis']->getSteps(); 258 $lastStepPosition = null; 259 $axisColor = $this->elements['axis']->border; 260 foreach ( $steps as $step ) 261 { 262 $this->elements['axis']->label = $step->label; 263 $this->drawRotatedAxis( $this->elements['axis'], $boundings, $center, $step->position, $lastStepPosition ); 264 $lastStepPosition = $step->position; 265 266 if ( count( $step->childs ) ) 267 { 268 foreach ( $step->childs as $childStep ) 269 { 270 $this->elements['axis']->label = null; 271 $this->elements['axis']->border = $this->childAxisColor; 272 273 $this->drawRotatedAxis( $this->elements['axis'], $boundings, $center, $childStep->position, $lastStepPosition ); 274 $lastStepPosition = $childStep->position; 275 } 276 } 277 278 $this->elements['axis']->border = $axisColor; 279 } 280 281 // Display data 282 $this->elements['axis']->position = ezcGraph::TOP; 283 foreach ( $this->data as $datasetName => $data ) 284 { 285 --$nr; 286 // Determine fill color for dataset 287 if ( $this->options->fillLines !== false ) 288 { 289 $fillColor = clone $data->color->default; 290 $fillColor->alpha = (int) round( ( 255 - $fillColor->alpha ) * ( $this->options->fillLines / 255 ) ); 291 } 292 else 293 { 294 $fillColor = null; 295 } 296 297 // Draw lines for dataset 298 $lastPoint = false; 299 foreach ( $data as $key => $value ) 300 { 301 $point = new ezcGraphCoordinate( 302 $this->elements['rotationAxis']->getCoordinate( $key ), 303 $this->elements['axis']->getCoordinate( $value ) 304 ); 305 306 /* Transformation required for 3d like renderers ... 307 * which axis should transform here? 308 $point = $this->elements['xAxis']->axisLabelRenderer->modifyChartDataPosition( 309 $this->elements['yAxis']->axisLabelRenderer->modifyChartDataPosition( 310 new ezcGraphCoordinate( 311 $this->elements['xAxis']->getCoordinate( $key ), 312 $this->elements['yAxis']->getCoordinate( $value ) 313 ) 314 ) 315 ); 316 // */ 317 318 $renderer->drawRadarDataLine( 319 $boundings, 320 new ezcGraphContext( $datasetName, $key, $data->url[$key] ), 321 $data->color->default, 322 clone $center, 323 ( $lastPoint === false ? $point : $lastPoint ), 324 $point, 325 $nr, 326 $count, 327 $data->symbol[$key], 328 $data->color[$key], 329 $fillColor, 330 $this->options->lineThickness 331 ); 332 333 $lastPoint = $point; 334 } 335 } 336 } 337 338 /** 339 * Returns the default display type of the current chart type. 340 * 341 * @return int Display type 342 */ 343 public function getDefaultDisplayType() 344 { 345 return ezcGraph::LINE; 346 } 347 348 /** 349 * Renders the basic elements of this chart type 350 * 351 * @param int $width 352 * @param int $height 353 * @return void 354 */ 355 protected function renderElements( $width, $height ) 356 { 357 if ( !count( $this->data ) ) 358 { 359 throw new ezcGraphNoDataException(); 360 } 361 362 // Set image properties in driver 363 $this->driver->options->width = $width; 364 $this->driver->options->height = $height; 365 366 // Calculate axis scaling and labeling 367 foreach ( $this->data as $dataset ) 368 { 369 $labels = array(); 370 $values = array(); 371 foreach ( $dataset as $label => $value ) 372 { 373 $labels[] = $label; 374 $values[] = $value; 375 } 376 377 $this->elements['axis']->addData( $values ); 378 $this->elements['rotationAxis']->addData( $labels ); 379 } 380 381 $this->elements['axis']->calculateAxisBoundings(); 382 $this->elements['rotationAxis']->calculateAxisBoundings(); 383 384 // Generate legend 385 $this->elements['legend']->generateFromDataSets( $this->data ); 386 387 // Get boundings from parameters 388 $this->options->width = $width; 389 $this->options->height = $height; 390 391 // Render subelements 392 $boundings = new ezcGraphBoundings(); 393 $boundings->x1 = $this->options->width; 394 $boundings->y1 = $this->options->height; 395 396 // Render subelements 397 foreach ( $this->elements as $name => $element ) 398 { 399 // Skip element, if it should not get rendered 400 if ( $this->renderElement[$name] === false ) 401 { 402 continue; 403 } 404 405 $this->driver->options->font = $element->font; 406 $boundings = $element->render( $this->renderer, $boundings ); 407 } 408 409 // Render graph 410 $this->renderData( $this->renderer, $boundings ); 411 } 412 413 /** 414 * Render the line chart 415 * 416 * Renders the chart into a file or stream. The width and height are 417 * needed to specify the dimensions of the resulting image. For direct 418 * output use 'php://stdout' as output file. 419 * 420 * @param int $width Image width 421 * @param int $height Image height 422 * @param string $file Output file 423 * @apichange 424 * @return void 425 */ 426 public function render( $width, $height, $file = null ) 427 { 428 $this->renderElements( $width, $height ); 429 430 if ( !empty( $file ) ) 431 { 432 $this->renderer->render( $file ); 433 } 434 435 $this->renderedFile = $file; 436 } 437 438 /** 439 * Renders this chart to direct output 440 * 441 * Does the same as ezcGraphChart::render(), but renders directly to 442 * output and not into a file. 443 * 444 * @param int $width 445 * @param int $height 446 * @apichange 447 * @return void 448 */ 449 public function renderToOutput( $width, $height ) 450 { 451 // @TODO: merge this function with render an deprecate ommit of third 452 // argument in render() when API break is possible 453 $this->renderElements( $width, $height ); 454 $this->renderer->render( null ); 455 } 456 } 457 ?>
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 |