[ Index ]
 

Code source de jpGraph 2.2

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/src/ -> jpgraph_plotband.php (source)

   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  ?>


Généré le : Sat Nov 24 09:27:55 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics