[ Index ] |
|
Code source de jpGraph 2.2 |
1 <?php 2 //======================================================================= 3 // File: JPGRAPH_PLOTBAND.PHP 4 // Description: PHP4 Graph Plotting library. Extension module. 5 // Created: 2004-02-18 6 // Ver: $Id: jpgraph_plotband.php 781 2006-10-08 08:07:47Z ljp $ 7 // 8 // Copyright (c) Aditus Consulting. All rights reserved. 9 //======================================================================== 10 11 // Constants for types of static bands in plot area 12 DEFINE("BAND_RDIAG",1); // Right diagonal lines 13 DEFINE("BAND_LDIAG",2); // Left diagonal lines 14 DEFINE("BAND_SOLID",3); // Solid one color 15 DEFINE("BAND_VLINE",4); // Vertical lines 16 DEFINE("BAND_HLINE",5); // Horizontal lines 17 DEFINE("BAND_3DPLANE",6); // "3D" Plane 18 DEFINE("BAND_HVCROSS",7); // Vertical/Hor crosses 19 DEFINE("BAND_DIAGCROSS",8); // Diagonal crosses 20 21 22 // Utility class to hold coordinates for a rectangle 23 class Rectangle { 24 public $x,$y,$w,$h; 25 public $xe, $ye; 26 function Rectangle($aX,$aY,$aWidth,$aHeight) { 27 $this->x=$aX; 28 $this->y=$aY; 29 $this->w=$aWidth; 30 $this->h=$aHeight; 31 $this->xe=$aX+$aWidth-1; 32 $this->ye=$aY+$aHeight-1; 33 } 34 } 35 36 //===================================================================== 37 // Class RectPattern 38 // Base class for pattern hierarchi that is used to display patterned 39 // bands on the graph. Any subclass that doesn't override Stroke() 40 // must at least implement method DoPattern($aImg) which is responsible 41 // for drawing the pattern onto the graph. 42 //===================================================================== 43 class RectPattern { 44 protected $color; 45 protected $weight; 46 protected $rect=null; 47 protected $doframe=true; 48 protected $linespacing; // Line spacing in pixels 49 protected $iBackgroundColor=-1; // Default is no background fill 50 51 function RectPattern($aColor,$aWeight=1) { 52 $this->color = $aColor; 53 $this->weight = $aWeight; 54 } 55 56 function SetBackground($aBackgroundColor) { 57 $this->iBackgroundColor=$aBackgroundColor; 58 } 59 60 function SetPos($aRect) { 61 $this->rect = $aRect; 62 } 63 64 function ShowFrame($aShow=true) { 65 $this->doframe=$aShow; 66 } 67 68 function SetDensity($aDens) { 69 if( $aDens < 1 || $aDens > 100 ) 70 JpGraphError::RaiseL(16001,$aDens); 71 //(" Desity for pattern must be between 1 and 100. (You tried $aDens)"); 72 // 1% corresponds to linespacing=50 73 // 100 % corresponds to linespacing 1 74 $this->linespacing = floor(((100-$aDens)/100.0)*50)+1; 75 76 } 77 78 function Stroke($aImg) { 79 if( $this->rect == null ) 80 JpGraphError::RaiseL(16002); 81 //(" No positions specified for pattern."); 82 83 if( !(is_numeric($this->iBackgroundColor) && $this->iBackgroundColor==-1) ) { 84 $aImg->SetColor($this->iBackgroundColor); 85 $aImg->FilledRectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye); 86 } 87 88 $aImg->SetColor($this->color); 89 $aImg->SetLineWeight($this->weight); 90 91 // Virtual function implemented by subclass 92 $this->DoPattern($aImg); 93 94 // Frame around the pattern area 95 if( $this->doframe ) 96 $aImg->Rectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye); 97 } 98 99 } 100 101 102 //===================================================================== 103 // Class RectPatternSolid 104 // Implements a solid band 105 //===================================================================== 106 class RectPatternSolid extends RectPattern { 107 108 function RectPatternSolid($aColor="black",$aWeight=1) { 109 parent::RectPattern($aColor,$aWeight); 110 } 111 112 function DoPattern($aImg) { 113 $aImg->SetColor($this->color); 114 $aImg->FilledRectangle($this->rect->x,$this->rect->y, 115 $this->rect->xe,$this->rect->ye); 116 } 117 } 118 119 //===================================================================== 120 // Class RectPatternHor 121 // Implements horizontal line pattern 122 //===================================================================== 123 class RectPatternHor extends RectPattern { 124 125 function RectPatternHor($aColor="black",$aWeight=1,$aLineSpacing=7) { 126 parent::RectPattern($aColor,$aWeight); 127 $this->linespacing = $aLineSpacing; 128 } 129 130 function DoPattern($aImg) { 131 $x0 = $this->rect->x; 132 $x1 = $this->rect->xe; 133 $y = $this->rect->y; 134 while( $y < $this->rect->ye ) { 135 $aImg->Line($x0,$y,$x1,$y); 136 $y += $this->linespacing; 137 } 138 } 139 } 140 141 //===================================================================== 142 // Class RectPatternVert 143 // Implements vertical line pattern 144 //===================================================================== 145 class RectPatternVert extends RectPattern { 146 147 function RectPatternVert($aColor="black",$aWeight=1,$aLineSpacing=7) { 148 parent::RectPattern($aColor,$aWeight); 149 $this->linespacing = $aLineSpacing; 150 } 151 152 //-------------------- 153 // Private methods 154 // 155 function DoPattern($aImg) { 156 $x = $this->rect->x; 157 $y0 = $this->rect->y; 158 $y1 = $this->rect->ye; 159 while( $x < $this->rect->xe ) { 160 $aImg->Line($x,$y0,$x,$y1); 161 $x += $this->linespacing; 162 } 163 } 164 } 165 166 167 //===================================================================== 168 // Class RectPatternRDiag 169 // Implements right diagonal pattern 170 //===================================================================== 171 class RectPatternRDiag extends RectPattern { 172 173 function RectPatternRDiag($aColor="black",$aWeight=1,$aLineSpacing=12) { 174 parent::RectPattern($aColor,$aWeight); 175 $this->linespacing = $aLineSpacing; 176 } 177 178 function DoPattern($aImg) { 179 // -------------------- 180 // | / / / / /| 181 // |/ / / / / | 182 // | / / / / | 183 // -------------------- 184 $xe = $this->rect->xe; 185 $ye = $this->rect->ye; 186 $x0 = $this->rect->x + round($this->linespacing/2); 187 $y0 = $this->rect->y; 188 $x1 = $this->rect->x; 189 $y1 = $this->rect->y + round($this->linespacing/2); 190 191 while($x0<=$xe && $y1<=$ye) { 192 $aImg->Line($x0,$y0,$x1,$y1); 193 $x0 += $this->linespacing; 194 $y1 += $this->linespacing; 195 } 196 197 if( $xe-$x1 > $ye-$y0 ) { 198 // Width larger than height 199 $x1 = $this->rect->x + ($y1-$ye); 200 $y1 = $ye; 201 $y0 = $this->rect->y; 202 while( $x0 <= $xe ) { 203 $aImg->Line($x0,$y0,$x1,$y1); 204 $x0 += $this->linespacing; 205 $x1 += $this->linespacing; 206 } 207 208 $y0=$this->rect->y + ($x0-$xe); 209 $x0=$xe; 210 } 211 else { 212 // Height larger than width 213 $diff = $x0-$xe; 214 $y0 = $diff+$this->rect->y; 215 $x0 = $xe; 216 $x1 = $this->rect->x; 217 while( $y1 <= $ye ) { 218 $aImg->Line($x0,$y0,$x1,$y1); 219 $y1 += $this->linespacing; 220 $y0 += $this->linespacing; 221 } 222 223 $diff = $y1-$ye; 224 $y1 = $ye; 225 $x1 = $diff + $this->rect->x; 226 } 227 228 while( $y0 <= $ye ) { 229 $aImg->Line($x0,$y0,$x1,$y1); 230 $y0 += $this->linespacing; 231 $x1 += $this->linespacing; 232 } 233 } 234 } 235 236 //===================================================================== 237 // Class RectPatternLDiag 238 // Implements left diagonal pattern 239 //===================================================================== 240 class RectPatternLDiag extends RectPattern { 241 242 function RectPatternLDiag($aColor="black",$aWeight=1,$aLineSpacing=12) { 243 $this->linespacing = $aLineSpacing; 244 parent::RectPattern($aColor,$aWeight); 245 } 246 247 function DoPattern($aImg) { 248 // -------------------- 249 // |\ \ \ \ \ | 250 // | \ \ \ \ \| 251 // | \ \ \ \ | 252 // |------------------| 253 $xe = $this->rect->xe; 254 $ye = $this->rect->ye; 255 $x0 = $this->rect->x + round($this->linespacing/2); 256 $y0 = $this->rect->ye; 257 $x1 = $this->rect->x; 258 $y1 = $this->rect->ye - round($this->linespacing/2); 259 260 while($x0<=$xe && $y1>=$this->rect->y) { 261 $aImg->Line($x0,$y0,$x1,$y1); 262 $x0 += $this->linespacing; 263 $y1 -= $this->linespacing; 264 } 265 if( $xe-$x1 > $ye-$this->rect->y ) { 266 // Width larger than height 267 $x1 = $this->rect->x + ($this->rect->y-$y1); 268 $y0=$ye; $y1=$this->rect->y; 269 while( $x0 <= $xe ) { 270 $aImg->Line($x0,$y0,$x1,$y1); 271 $x0 += $this->linespacing; 272 $x1 += $this->linespacing; 273 } 274 275 $y0=$this->rect->ye - ($x0-$xe); 276 $x0=$xe; 277 } 278 else { 279 // Height larger than width 280 $diff = $x0-$xe; 281 $y0 = $ye-$diff; 282 $x0 = $xe; 283 while( $y1 >= $this->rect->y ) { 284 $aImg->Line($x0,$y0,$x1,$y1); 285 $y0 -= $this->linespacing; 286 $y1 -= $this->linespacing; 287 } 288 $diff = $this->rect->y - $y1; 289 $x1 = $this->rect->x + $diff; 290 $y1 = $this->rect->y; 291 } 292 while( $y0 >= $this->rect->y ) { 293 $aImg->Line($x0,$y0,$x1,$y1); 294 $y0 -= $this->linespacing; 295 $x1 += $this->linespacing; 296 } 297 } 298 } 299 300 //===================================================================== 301 // Class RectPattern3DPlane 302 // Implements "3D" plane pattern 303 //===================================================================== 304 class RectPattern3DPlane extends RectPattern { 305 private $alpha=50; // Parameter that specifies the distance 306 // to "simulated" horizon in pixel from the 307 // top of the band. Specifies how fast the lines 308 // converge. 309 310 function RectPattern3DPlane($aColor="black",$aWeight=1) { 311 parent::RectPattern($aColor,$aWeight); 312 $this->SetDensity(10); // Slightly larger default 313 } 314 315 function SetHorizon($aHorizon) { 316 $this->alpha=$aHorizon; 317 } 318 319 function DoPattern($aImg) { 320 // "Fake" a nice 3D grid-effect. 321 $x0 = $this->rect->x + $this->rect->w/2; 322 $y0 = $this->rect->y; 323 $x1 = $x0; 324 $y1 = $this->rect->ye; 325 $x0_right = $x0; 326 $x1_right = $x1; 327 328 // BTW "apa" means monkey in Swedish but is really a shortform for 329 // "alpha+a" which was the labels I used on paper when I derived the 330 // geometric to get the 3D perspective right. 331 // $apa is the height of the bounding rectangle plus the distance to the 332 // artifical horizon (alpha) 333 $apa = $this->rect->h + $this->alpha; 334 335 // Three cases and three loops 336 // 1) The endpoint of the line ends on the bottom line 337 // 2) The endpoint ends on the side 338 // 3) Horizontal lines 339 340 // Endpoint falls on bottom line 341 $middle=$this->rect->x + $this->rect->w/2; 342 $dist=$this->linespacing; 343 $factor=$this->alpha /($apa); 344 while($x1>$this->rect->x) { 345 $aImg->Line($x0,$y0,$x1,$y1); 346 $aImg->Line($x0_right,$y0,$x1_right,$y1); 347 $x1 = $middle - $dist; 348 $x0 = $middle - $dist * $factor; 349 $x1_right = $middle + $dist; 350 $x0_right = $middle + $dist * $factor; 351 $dist += $this->linespacing; 352 } 353 354 // Endpoint falls on sides 355 $dist -= $this->linespacing; 356 $d=$this->rect->w/2; 357 $c = $apa - $d*$apa/$dist; 358 while( $x0>$this->rect->x ) { 359 $aImg->Line($x0,$y0,$this->rect->x,$this->rect->ye-$c); 360 $aImg->Line($x0_right,$y0,$this->rect->xe,$this->rect->ye-$c); 361 $dist += $this->linespacing; 362 $x0 = $middle - $dist * $factor; 363 $x1 = $middle - $dist; 364 $x0_right = $middle + $dist * $factor; 365 $c = $apa - $d*$apa/$dist; 366 } 367 368 // Horizontal lines 369 // They need some serious consideration since they are a function 370 // of perspective depth (alpha) and density (linespacing) 371 $x0=$this->rect->x; 372 $x1=$this->rect->xe; 373 $y=$this->rect->ye; 374 375 // The first line is drawn directly. Makes the loop below slightly 376 // more readable. 377 $aImg->Line($x0,$y,$x1,$y); 378 $hls = $this->linespacing; 379 380 // A correction factor for vertical "brick" line spacing to account for 381 // a) the difference in number of pixels hor vs vert 382 // b) visual apperance to make the first layer of "bricks" look more 383 // square. 384 $vls = $this->linespacing*0.6; 385 386 $ds = $hls*($apa-$vls)/$apa; 387 // Get the slope for the "perspective line" going from bottom right 388 // corner to top left corner of the "first" brick. 389 390 // Uncomment the following lines if you want to get a visual understanding 391 // of what this helpline does. BTW this mimics the way you would get the 392 // perspective right when drawing on paper. 393 /* 394 $x0 = $middle; 395 $y0 = $this->rect->ye; 396 $len=floor(($this->rect->ye-$this->rect->y)/$vls); 397 $x1 = $middle+round($len*$ds); 398 $y1 = $this->rect->ye-$len*$vls; 399 $aImg->PushColor("red"); 400 $aImg->Line($x0,$y0,$x1,$y1); 401 $aImg->PopColor(); 402 */ 403 404 $y -= $vls; 405 $k=($this->rect->ye-($this->rect->ye-$vls))/($middle-($middle-$ds)); 406 $dist = $hls; 407 while( $y>$this->rect->y ) { 408 $aImg->Line($this->rect->x,$y,$this->rect->xe,$y); 409 $adj = $k*$dist/(1+$dist*$k/$apa); 410 if( $adj < 2 ) $adj=1; 411 $y = $this->rect->ye - round($adj); 412 $dist += $hls; 413 } 414 } 415 } 416 417 //===================================================================== 418 // Class RectPatternCross 419 // Vert/Hor crosses 420 //===================================================================== 421 class RectPatternCross extends RectPattern { 422 private $vert=null; 423 private $hor=null; 424 function RectPatternCross($aColor="black",$aWeight=1) { 425 parent::RectPattern($aColor,$aWeight); 426 $this->vert = new RectPatternVert($aColor,$aWeight); 427 $this->hor = new RectPatternHor($aColor,$aWeight); 428 } 429 430 function SetOrder($aDepth) { 431 $this->vert->SetOrder($aDepth); 432 $this->hor->SetOrder($aDepth); 433 } 434 435 function SetPos($aRect) { 436 parent::SetPos($aRect); 437 $this->vert->SetPos($aRect); 438 $this->hor->SetPos($aRect); 439 } 440 441 function SetDensity($aDens) { 442 $this->vert->SetDensity($aDens); 443 $this->hor->SetDensity($aDens); 444 } 445 446 function DoPattern($aImg) { 447 $this->vert->DoPattern($aImg); 448 $this->hor->DoPattern($aImg); 449 } 450 } 451 452 //===================================================================== 453 // Class RectPatternDiagCross 454 // Vert/Hor crosses 455 //===================================================================== 456 457 class RectPatternDiagCross extends RectPattern { 458 private $left=null; 459 private $right=null; 460 function RectPatternDiagCross($aColor="black",$aWeight=1) { 461 parent::RectPattern($aColor,$aWeight); 462 $this->right = new RectPatternRDiag($aColor,$aWeight); 463 $this->left = new RectPatternLDiag($aColor,$aWeight); 464 } 465 466 function SetOrder($aDepth) { 467 $this->left->SetOrder($aDepth); 468 $this->right->SetOrder($aDepth); 469 } 470 471 function SetPos($aRect) { 472 parent::SetPos($aRect); 473 $this->left->SetPos($aRect); 474 $this->right->SetPos($aRect); 475 } 476 477 function SetDensity($aDens) { 478 $this->left->SetDensity($aDens); 479 $this->right->SetDensity($aDens); 480 } 481 482 function DoPattern($aImg) { 483 $this->left->DoPattern($aImg); 484 $this->right->DoPattern($aImg); 485 } 486 487 } 488 489 //===================================================================== 490 // Class RectPatternFactory 491 // Factory class for rectangular pattern 492 //===================================================================== 493 class RectPatternFactory { 494 function RectPatternFactory() { 495 // Empty 496 } 497 function Create($aPattern,$aColor,$aWeight=1) { 498 switch($aPattern) { 499 case BAND_RDIAG: 500 $obj = new RectPatternRDiag($aColor,$aWeight); 501 break; 502 case BAND_LDIAG: 503 $obj = new RectPatternLDiag($aColor,$aWeight); 504 break; 505 case BAND_SOLID: 506 $obj = new RectPatternSolid($aColor,$aWeight); 507 break; 508 case BAND_VLINE: 509 $obj = new RectPatternVert($aColor,$aWeight); 510 break; 511 case BAND_HLINE: 512 $obj = new RectPatternHor($aColor,$aWeight); 513 break; 514 case BAND_3DPLANE: 515 $obj = new RectPattern3DPlane($aColor,$aWeight); 516 break; 517 case BAND_HVCROSS: 518 $obj = new RectPatternCross($aColor,$aWeight); 519 break; 520 case BAND_DIAGCROSS: 521 $obj = new RectPatternDiagCross($aColor,$aWeight); 522 break; 523 default: 524 JpGraphError::RaiseL(16003,$aPattern); 525 //(" Unknown pattern specification ($aPattern)"); 526 } 527 return $obj; 528 } 529 } 530 531 532 //===================================================================== 533 // Class PlotBand 534 // Factory class which is used by the client. 535 // It is responsible for factoring the corresponding pattern 536 // concrete class. 537 //===================================================================== 538 class PlotBand { 539 public $depth; // Determine if band should be over or under the plots 540 private $prect=null; 541 private $dir, $min, $max; 542 543 function PlotBand($aDir,$aPattern,$aMin,$aMax,$aColor="black",$aWeight=1,$aDepth=DEPTH_BACK) { 544 $f = new RectPatternFactory(); 545 $this->prect = $f->Create($aPattern,$aColor,$aWeight); 546 if( is_numeric($aMin) && is_numeric($aMax) && ($aMin > $aMax) ) 547 JpGraphError::RaiseL(16004); 548 //('Min value for plotband is larger than specified max value. Please correct.'); 549 $this->dir = $aDir; 550 $this->min = $aMin; 551 $this->max = $aMax; 552 $this->depth=$aDepth; 553 } 554 555 // Set position. aRect contains absolute image coordinates 556 function SetPos($aRect) { 557 assert( $this->prect != null ) ; 558 $this->prect->SetPos($aRect); 559 } 560 561 function ShowFrame($aFlag=true) { 562 $this->prect->ShowFrame($aFlag); 563 } 564 565 // Set z-order. In front of pplot or in the back 566 function SetOrder($aDepth) { 567 $this->depth=$aDepth; 568 } 569 570 function SetDensity($aDens) { 571 $this->prect->SetDensity($aDens); 572 } 573 574 function GetDir() { 575 return $this->dir; 576 } 577 578 function GetMin() { 579 return $this->min; 580 } 581 582 function GetMax() { 583 return $this->max; 584 } 585 586 function PreStrokeAdjust($aGraph) { 587 // Nothing to do 588 } 589 590 // Display band 591 function Stroke($aImg,$aXScale,$aYScale) { 592 assert( $this->prect != null ) ; 593 if( $this->dir == HORIZONTAL ) { 594 if( $this->min === 'min' ) $this->min = $aYScale->GetMinVal(); 595 if( $this->max === 'max' ) $this->max = $aYScale->GetMaxVal(); 596 597 // Only draw the bar if it actually appears in the range 598 if ($this->min < $aYScale->GetMaxVal() && $this->max > $aYScale->GetMinVal()) { 599 600 // Trucate to limit of axis 601 $this->min = max($this->min, $aYScale->GetMinVal()); 602 $this->max = min($this->max, $aYScale->GetMaxVal()); 603 604 $x=$aXScale->scale_abs[0]; 605 $y=$aYScale->Translate($this->max); 606 $width=$aXScale->scale_abs[1]-$aXScale->scale_abs[0]+1; 607 $height=abs($y-$aYScale->Translate($this->min))+1; 608 $this->prect->SetPos(new Rectangle($x,$y,$width,$height)); 609 $this->prect->Stroke($aImg); 610 } 611 } 612 else { // VERTICAL 613 if( $this->min === 'min' ) $this->min = $aXScale->GetMinVal(); 614 if( $this->max === 'max' ) $this->max = $aXScale->GetMaxVal(); 615 616 // Only draw the bar if it actually appears in the range 617 if ($this->min < $aXScale->GetMaxVal() && $this->max > $aXScale->GetMinVal()) { 618 619 // Trucate to limit of axis 620 $this->min = max($this->min, $aXScale->GetMinVal()); 621 $this->max = min($this->max, $aXScale->GetMaxVal()); 622 623 $y=$aYScale->scale_abs[1]; 624 $x=$aXScale->Translate($this->min); 625 $height=abs($aYScale->scale_abs[1]-$aYScale->scale_abs[0]); 626 $width=abs($x-$aXScale->Translate($this->max)); 627 $this->prect->SetPos(new Rectangle($x,$y,$width,$height)); 628 $this->prect->Stroke($aImg); 629 } 630 } 631 } 632 } 633 634 635 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sat Nov 24 09:27:55 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |