[ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
1 <?php 2 /*======================================================================= 3 // File: JPGRAPH_SPIDER.PHP 4 // Description: Spider plot extension for JpGraph 5 // Created: 2001-02-04 6 // Author: Johan Persson (johanp@aditus.nu) 7 // Ver: $Id: jpgraph_spider.php 18250 2005-05-07 14:13:43Z ralfbecker $ 8 // 9 // License: This code is released under GPL 2.0 10 // Copyright (C) 2001 Johan Persson 11 //======================================================================== 12 */ 13 14 //=================================================== 15 // CLASS FontProp 16 // Description: Utility class to enable the use 17 // of a "title" instance variable for the spider axis. 18 // This clas is only used to hold a font and a color 19 // property for the axis title. 20 //=================================================== 21 class FontProp { 22 var $font_family=FF_FONT1, $font_style=FS_NORMAL,$font_size=14,$font_color=array(0,0,0); 23 function SetFont($family,$style=FS_NORMAL,$size=14) { 24 $this->font_family = $family; 25 $this->font_style = $style; 26 $this->font_size = $size; 27 } 28 29 function SetColor($c) { 30 $this->font_color = $c; 31 } 32 } 33 34 class SpiderLogTicks extends Ticks { 35 //--------------- 36 // CONSTRUCTOR 37 function SpiderLogTicks() { 38 } 39 //--------------- 40 // PUBLIC METHODS 41 42 // TODO: Add Argument grid 43 function Stroke(&$aImg,&$grid,$aPos,$aAxisAngle,&$aScale,&$aMajPos,&$aMajLabel) { 44 $start = $aScale->GetMinVal(); 45 $limit = $aScale->GetMaxVal(); 46 $nextMajor = 10*$start; 47 $step = $nextMajor / 10.0; 48 $count=1; 49 50 $ticklen_maj=5; 51 $dx_maj=round(sin($aAxisAngle)*$ticklen_maj); 52 $dy_maj=round(cos($aAxisAngle)*$ticklen_maj); 53 $ticklen_min=3; 54 $dx_min=round(sin($aAxisAngle)*$ticklen_min); 55 $dy_min=round(cos($aAxisAngle)*$ticklen_min); 56 57 $aMajPos=array(); 58 $aMajLabel=array(); 59 60 if( $this->supress_first ) 61 $aMajLabel[]=""; 62 else 63 $aMajLabel[]=$start; 64 $yr=$aScale->RelTranslate($start); 65 $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0]; 66 $yt=$aPos-round($yr*sin($aAxisAngle)); 67 $aMajPos[]=$xt+2*$dx_maj; 68 $aMajPos[]=$yt-$aImg->GetFontheight()/2; 69 $grid[]=$xt; 70 $grid[]=$yt; 71 72 $aImg->SetLineWeight($this->weight); 73 74 for($y=$start; $y<=$limit; $y+=$step,++$count ) { 75 $yr=$aScale->RelTranslate($y); 76 $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0]; 77 $yt=$aPos-round($yr*sin($aAxisAngle)); 78 if( $count % 10 == 0 ) { 79 $grid[]=$xt; 80 $grid[]=$yt; 81 $aMajPos[]=$xt+2*$dx_maj; 82 $aMajPos[]=$yt-$aImg->GetFontheight()/2; 83 if( !$this->supress_tickmarks ) { 84 if( $this->majcolor!="" ) $aImg->PushColor($this->majcolor); 85 $aImg->Line($xt+$dx_maj,$yt+$dy_maj,$xt-$dx_maj,$yt-$dy_maj); 86 if( $this->majcolor!="" ) $aImg->PopColor(); 87 } 88 $aMajLabel[]=$nextMajor; 89 $nextMajor *= 10; 90 $step *= 10; 91 $count=1; 92 } 93 else 94 if( !$this->supress_minor_tickmarks ) { 95 if( $this->mincolor!="" ) $aImg->PushColor($this->mincolor); 96 $aImg->Line($xt+$dx_min,$yt+$dy_min,$xt-$dx_min,$yt-$dy_min); 97 if( $this->mincolor!="" ) $aImg->PopColor(); 98 } 99 } 100 } 101 } 102 103 class SpiderLinearTicks extends LinearTicks { 104 //--------------- 105 // CONSTRUCTOR 106 function SpiderLinearTicks() { 107 // Empty 108 } 109 110 //--------------- 111 // PUBLIC METHODS 112 113 // TODO: Add argument grid 114 function Stroke(&$aImg,&$grid,$aPos,$aAxisAngle,&$aScale,&$aMajPos,&$aMajLabel) { 115 // Prepare to draw linear ticks 116 $maj_step_abs = abs($aScale->scale_factor*$this->major_step); 117 $min_step_abs = abs($aScale->scale_factor*$this->minor_step); 118 $nbrmaj = floor(($aScale->world_abs_size)/$maj_step_abs); 119 $nbrmin = floor(($aScale->world_abs_size)/$min_step_abs); 120 $skip = round($nbrmin/$nbrmaj); // Don't draw minor ontop of major 121 122 // Draw major ticks 123 $ticklen2=4; 124 $dx=round(sin($aAxisAngle)*$ticklen2); 125 $dy=round(cos($aAxisAngle)*$ticklen2); 126 $label=$aScale->scale[0]+$this->major_step; 127 128 $aImg->SetLineWeight($this->weight); 129 130 for($i=1; $i<=$nbrmaj; ++$i) { 131 $xt=round($i*$maj_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0]; 132 $yt=$aPos-round($i*$maj_step_abs*sin($aAxisAngle)); 133 $aMajLabel[]=$label; 134 $label += $this->major_step; 135 $grid[]=$xt; 136 $grid[]=$yt; 137 $aMajPos[($i-1)*2]=$xt+2*$dx; 138 $aMajPos[($i-1)*2+1]=$yt-$aImg->GetFontheight()/2; 139 if( !$this->supress_tickmarks ) { 140 if( $this->majcolor!="" ) $aImg->PushColor($this->majcolor); 141 $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy); 142 if( $this->majcolor!="" ) $aImg->PopColor(); 143 } 144 } 145 146 // Draw minor ticks 147 $ticklen2=3; 148 $dx=round(sin($aAxisAngle)*$ticklen2); 149 $dy=round(cos($aAxisAngle)*$ticklen2); 150 if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) { 151 if( $this->mincolor!="" ) $aImg->PushColor($this->mincolor); 152 for($i=1; $i<=$nbrmin; ++$i) { 153 if( ($i % $skip) == 0 ) continue; 154 $xt=round($i*$min_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0]; 155 $yt=$pos-round($i*$min_step_abs*sin($aAxisAngle)); 156 $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy); 157 } 158 if( $this->mincolor!="" ) $aImg->PopColor(); 159 } 160 } 161 } 162 163 164 165 //=================================================== 166 // CLASS SpiderAxis 167 // Description: Implements axis for the spider graph 168 //=================================================== 169 class SpiderAxis extends Axis { 170 var $title_color="navy"; 171 var $title=null; 172 //--------------- 173 // CONSTRUCTOR 174 function SpiderAxis(&$img,&$aScale,$color=array(0,0,0)) { 175 parent::Axis($img,$aScale,$color); 176 $this->len=$img->plotheight; 177 $this->font_size = FF_FONT1; 178 $this->title = new FontProp(); 179 $this->color = array(0,0,0); 180 } 181 //--------------- 182 // PUBLIC METHODS 183 function SetTickLabels($l) { 184 $this->ticks_label = $l; 185 } 186 187 188 // Stroke the axis 189 // $pos = Vertical position of axis 190 // $aAxisAngle = Axis angle 191 // $grid = Returns an array with positions used to draw the grid 192 // $lf = Label flag, TRUE if the axis should have labels 193 function Stroke($pos,$aAxisAngle,&$grid,$title,$lf) { 194 $this->img->SetColor($this->color); 195 196 // Determine end points for the axis 197 $x=round($this->scale->world_abs_size*cos($aAxisAngle)+$this->scale->scale_abs[0]); 198 $y=round($pos-$this->scale->world_abs_size*sin($aAxisAngle)); 199 200 // Draw axis 201 $this->img->SetColor($this->color); 202 $this->img->SetLineWeight($this->weight); 203 if( !$this->hide ) 204 $this->img->Line($this->scale->scale_abs[0],$pos,$x,$y); 205 206 $this->scale->ticks->Stroke($this->img,$grid,$pos,$aAxisAngle,$this->scale,$majpos,$majlabel); 207 208 // Draw labels 209 if( $lf && !$this->hide ) { 210 $this->img->SetFont($this->font_family,$this->font_style,$this->font_size); 211 $this->img->SetTextAlign("left","top"); 212 $this->img->SetColor($this->color); 213 214 // majpos contsins (x,y) coordinates for labels 215 for($i=0; $i<count($majpos)/2; ++$i) { 216 if( $this->ticks_label != null ) 217 $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$this->ticks_label[$i]); 218 else 219 $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$majlabel[$i]); 220 } 221 } 222 $this->_StrokeAxisTitle($pos,$aAxisAngle,$title); 223 } 224 //--------------- 225 // PRIVATE METHODS 226 227 function _StrokeAxisTitle($pos,$aAxisAngle,$title) { 228 // Draw title of this axis 229 $this->img->SetFont($this->title->font_family,$this->title->font_style,$this->title->font_size); 230 $this->img->SetColor($this->title->font_color); 231 $marg=6; 232 $xt=round(($this->scale->world_abs_size+$marg)*cos($aAxisAngle)+$this->scale->scale_abs[0]); 233 $yt=round($pos-($this->scale->world_abs_size+$marg)*sin($aAxisAngle)); 234 235 // Position the axis title. 236 // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text 237 // that intersects with the extension of the corresponding axis. The code looks a little 238 // bit messy but this is really the only way of having a reasonable position of the 239 // axis titles. 240 $h=$this->img->GetFontHeight(); 241 $w=$this->img->GetTextWidth($title); 242 while( $aAxisAngle > 2*M_PI ) $aAxisAngle -= 2*M_PI; 243 if( $aAxisAngle>=7*M_PI/4 || $aAxisAngle <= M_PI/4 ) $dx=0; 244 if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dx=($aAxisAngle-M_PI/4)*2/M_PI; 245 if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dx=1; 246 if( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dx=(1-($aAxisAngle-M_PI*5/4)*2/M_PI); 247 248 if( $aAxisAngle>=7*M_PI/4 ) $dy=(($aAxisAngle-M_PI)-3*M_PI/4)*2/M_PI; 249 if( $aAxisAngle<=M_PI/4 ) $dy=(1-$aAxisAngle*2/M_PI); 250 if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dy=1; 251 if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dy=(1-($aAxisAngle-3*M_PI/4)*2/M_PI); 252 if( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dy=0; 253 254 if( !$this->hide ) 255 $this->img->StrokeText($xt-$dx*$w,$yt-$dy*$h,$title); 256 257 } 258 259 260 } // Class 261 262 263 //=================================================== 264 // CLASS SpiderGrid 265 // Description: Draws grid for the spider graph 266 //=================================================== 267 class SpiderGrid extends Grid { 268 //------------ 269 // CONSTRUCTOR 270 function SpiderGrid() { 271 } 272 273 //---------------- 274 // PRIVATE METHODS 275 function Stroke(&$img,&$grid) { 276 if( !$this->show ) return; 277 $nbrticks = count($grid[0])/2; 278 $nbrpnts = count($grid); 279 $img->SetColor($this->grid_color); 280 $img->SetLineWeight($this->weight); 281 for($i=0; $i<$nbrticks; ++$i) { 282 for($j=0; $j<$nbrpnts; ++$j) { 283 $pnts[$j*2]=$grid[$j][$i*2]; 284 $pnts[$j*2+1]=$grid[$j][$i*2+1]; 285 } 286 for($k=0; $k<$nbrpnts; ++$k ){ 287 $l=($k+1)%$nbrpnts; 288 if( $this->type == "solid" ) 289 $img->Line($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1]); 290 elseif( $this->type == "dotted" ) 291 $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],1,6); 292 elseif( $this->type == "dashed" ) 293 $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],2,4); 294 elseif( $this->type == "longdashed" ) 295 $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],8,6); 296 } 297 $pnts=array(); 298 } 299 } 300 } // Class 301 302 303 //=================================================== 304 // CLASS SpiderPlot 305 // Description: Plot a spiderplot 306 //=================================================== 307 class SpiderPlot { 308 var $data=array(); 309 var $fill=false, $fill_color=array(200,170,180); 310 var $color=array(0,0,0); 311 var $legend=""; 312 var $weight=1; 313 //--------------- 314 // CONSTRUCTOR 315 function SpiderPlot($data) { 316 $this->data = $data; 317 } 318 319 //--------------- 320 // PUBLIC METHODS 321 function Min() { 322 return Min($this->data); 323 } 324 325 function Max() { 326 return Max($this->data); 327 } 328 329 function SetLegend($legend) { 330 $this->legend=$legend; 331 } 332 333 function SetFill($f=true) { 334 $this->fill = $f; 335 } 336 337 function SetLineWeight($w) { 338 $this->weight=$w; 339 } 340 341 function SetColor($color,$fill_color=array(160,170,180)) { 342 $this->color = $color; 343 $this->fill_color = $fill_color; 344 } 345 346 function GetCSIMareas() { 347 JpGraphError::Raise("JpGraph Error: Client side image maps not supported for SpiderPlots."); 348 } 349 350 function Stroke(&$img, $pos, &$scale, $startangle) { 351 $nbrpnts = count($this->data); 352 $astep=2*M_PI/$nbrpnts; 353 $a=$startangle; 354 355 // Rotate each point to the correct axis-angle 356 // TODO: Update for LogScale 357 for($i=0; $i<$nbrpnts; ++$i) { 358 //$c=$this->data[$i]; 359 $cs=$scale->RelTranslate($this->data[$i]); 360 $x=round($cs*cos($a)+$scale->scale_abs[0]); 361 $y=round($pos-$cs*sin($a)); 362 /* 363 $c=log10($c); 364 $x=round(($c-$scale->scale[0])*$scale->scale_factor*cos($a)+$scale->scale_abs[0]); 365 $y=round($pos-($c-$scale->scale[0])*$scale->scale_factor*sin($a)); 366 */ 367 $pnts[$i*2]=$x; 368 $pnts[$i*2+1]=$y; 369 $a += $astep; 370 } 371 if( $this->fill ) { 372 $img->SetColor($this->fill_color); 373 $img->FilledPolygon($pnts); 374 } 375 $img->SetLineWeight($this->weight); 376 $img->SetColor($this->color); 377 $img->Polygon($pnts); 378 } 379 380 //--------------- 381 // PRIVATE METHODS 382 function GetCount() { 383 return count($this->data); 384 } 385 386 function Legend(&$graph) { 387 if( $this->legend=="" ) return; 388 if( $this->fill ) 389 $graph->legend->Add($this->legend,$this->fill_color); 390 else 391 $graph->legend->Add($this->legend,$this->color); 392 } 393 394 } // Class 395 396 //=================================================== 397 // CLASS SpiderGraph 398 // Description: Main container for a spider graph 399 //=================================================== 400 class SpiderGraph extends Graph { 401 var $posx; 402 var $posy; 403 var $len; 404 var $plots=null, $axis_title=null; 405 var $grid,$axis=null; 406 //--------------- 407 // CONSTRUCTOR 408 function SpiderGraph($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) { 409 $this->Graph($width,$height,$cachedName,$timeout,$inline); 410 $this->posx=$width/2; 411 $this->posy=$height/2; 412 $this->len=min($width,$height)*0.35; 413 $this->SetColor(array(255,255,255)); 414 $this->SetTickDensity(TICKD_NORMAL); 415 $this->SetScale("lin"); 416 } 417 418 //--------------- 419 // PUBLIC METHODS 420 function SupressTickMarks($f=true) { 421 $this->axis->scale->ticks->SupressTickMarks($f); 422 } 423 424 function SetScale($axtype,$ymin=1,$ymax=1) { 425 if( $axtype != "lin" && $axtype != "log" ) { 426 JpGraphError::Raise("Illegal scale for spiderplot ($axtype). Must be \"lin\" or \"log\""); 427 } 428 if( $axtype=="lin" ) { 429 $this->yscale = & new LinearScale(1,1); 430 $this->yscale->ticks = & new SpiderLinearTicks(); 431 $this->yscale->ticks->SupressMinorTickMarks(); 432 } 433 elseif( $axtype=="log" ) { 434 $this->yscale = & new LogScale(1,1); 435 $this->yscale->ticks = & new SpiderLogTicks(); 436 //JpGraphError::Raise("JpGraph Error: Logarithmic spider plots are not yet supported"); 437 } 438 439 $this->axis = & new SpiderAxis($this->img,$this->yscale); 440 $this->grid = & new SpiderGrid(); 441 } 442 443 function SetPlotSize($s) { 444 if( $s<0.1 || $s>1 ) 445 JpGraphError::Raise("JpGraph Error: Spider Plot size must be between 0.1 and 1. (Your value=$s)"); 446 $this->len=min($this->img->width,$this->img->height)*$s/2; 447 } 448 449 function SetTickDensity($densy=TICKD_NORMAL) { 450 $this->ytick_factor=25; 451 switch( $densy ) { 452 case TICKD_DENSE: 453 $this->ytick_factor=12; 454 break; 455 case TICKD_NORMAL: 456 $this->ytick_factor=25; 457 break; 458 case TICKD_SPARSE: 459 $this->ytick_factor=40; 460 break; 461 case TICKD_VERYSPARSE: 462 $this->ytick_factor=70; 463 break; 464 default: 465 JpGraphError::Raise("Unsupported Tick density: $densy"); 466 } 467 } 468 469 function SetCenter($px,$py=0.5) { 470 assert($px > 0 && $py > 0 ); 471 $this->posx=$this->img->width*$px; 472 $this->posy=$this->img->height*$py; 473 } 474 475 function SetColor($c) { 476 $this->SetMarginColor($c); 477 } 478 479 function SetTitles($title) { 480 $this->axis_title = $title; 481 } 482 483 function Add(&$splot) { 484 $this->plots[]=$splot; 485 } 486 487 function GetPlotsYMinMax() { 488 $min=$this->plots[0]->Min(); 489 $max=$this->plots[0]->Max(); 490 foreach( $this->plots as $p ) { 491 $max=max($max,$p->Max()); 492 $min=min($min,$p->Min()); 493 } 494 if( $min < 0 ) 495 JpGraphError::Raise("JpGraph Error: Minimum data $min (Spider plots only makes sence to use when all data points > 0)"); 496 return array($min,$max); 497 } 498 499 // Stroke the Spider graph 500 function Stroke($aStrokeFileName="") { 501 // Set Y-scale 502 if( !$this->yscale->IsSpecified() && 503 count($this->plots)>0 ) { 504 list($min,$max) = $this->GetPlotsYMinMax(); 505 $this->yscale->AutoScale($this->img,0,$max,$this->len/$this->ytick_factor); 506 } 507 // Set start position end length of scale (in absolute pixels) 508 $this->yscale->SetConstants($this->posx,$this->len); 509 510 // We need as many axis as there are data points 511 $nbrpnts=$this->plots[0]->GetCount(); 512 513 // If we have no titles just number the axis 1,2,3,... 514 if( $this->axis_title==null ) { 515 for($i=0; $i<$nbrpnts; ++$i ) 516 $this->axis_title[$i] = $i+1; 517 } 518 elseif(count($this->axis_title)<$nbrpnts) 519 JpGraphError::Raise("JpGraph: Number of titles does not match number of points in plot."); 520 for($i=0; $i<count($this->plots); ++$i ) 521 if( $nbrpnts != $this->plots[$i]->GetCount() ) 522 JpGraphError::Raise("JpGraph: Each spider plot must have the same number of data points."); 523 524 $this->StrokeFrame(); 525 $astep=2*M_PI/$nbrpnts; 526 527 // Prepare legends 528 for($i=0; $i<count($this->plots); ++$i) 529 $this->plots[$i]->Legend($this); 530 $this->legend->Stroke($this->img); 531 532 // Plot points 533 $a=M_PI/2; 534 for($i=0; $i<count($this->plots); ++$i ) 535 $this->plots[$i]->Stroke($this->img, $this->posy, $this->yscale, $a); 536 537 // Draw axis and grid 538 for( $i=0,$a=M_PI/2; $i<$nbrpnts; ++$i, $a+=$astep ) { 539 $this->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0); 540 } 541 $this->grid->Stroke($this->img,$grid); 542 $this->title->Center($this->img->left_margin,$this->img->width-$this->img->right_margin,5); 543 $this->title->Stroke($this->img); 544 545 // Stroke texts 546 if( $this->texts != null ) 547 foreach( $this->texts as $t) 548 $t->Stroke($this->img); 549 550 551 // Finally output the image 552 $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName); 553 } 554 } // Class 555 556 /* EOF */ 557 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 17:20:01 2007 | par Balluche grâce à PHPXref 0.7 |