[ PHPXref.com ] [ Generated: Sun Jul 20 20:17:16 2008 ] [ Simple Spreadsheet 0.3 ]
[ Index ]     [ Variables ]     [ Functions ]     [ Classes ]     [ Constants ]     [ Statistics ]

title

Body

[close]

/jpgraph/ -> jpgraph_bar.php (source)

   1  <?php
   2  /*=======================================================================
   3  // File:    JPGRAPH_BAR.PHP
   4  // Description:    Bar plot extension for JpGraph
   5  // Created:     2001-01-08
   6  // Author:    Johan Persson (johanp@aditus.nu)
   7  // Ver:        $Id: jpgraph_bar.php 542 2006-02-14 20:10:46Z ljp $
   8  //
   9  // Copyright (c) Aditus Consulting. All rights reserved.
  10  //========================================================================
  11  */
  12  
  13  require_once ('jpgraph_plotband.php');
  14  
  15  // Pattern for Bars
  16  DEFINE('PATTERN_DIAG1',1);
  17  DEFINE('PATTERN_DIAG2',2);
  18  DEFINE('PATTERN_DIAG3',3);
  19  DEFINE('PATTERN_DIAG4',4);
  20  DEFINE('PATTERN_CROSS1',5);
  21  DEFINE('PATTERN_CROSS2',6);
  22  DEFINE('PATTERN_CROSS3',7);
  23  DEFINE('PATTERN_CROSS4',8);
  24  DEFINE('PATTERN_STRIPE1',9);
  25  DEFINE('PATTERN_STRIPE2',10);
  26  
  27  //===================================================
  28  // CLASS BarPlot
  29  // Description: Main code to produce a bar plot 
  30  //===================================================
  31  class BarPlot extends Plot {
  32      var $width=0.4; // in percent of major ticks
  33      var $abswidth=-1; // Width in absolute pixels
  34      var $fill=false,$fill_color="lightblue"; // Default is to fill with light blue
  35      var $ybase=0; // Bars start at 0 
  36      var $align="center";
  37      var $grad=false,$grad_style=1;
  38      var $grad_fromcolor=array(50,50,200),$grad_tocolor=array(255,255,255);
  39      var $bar_shadow=false;
  40      var $bar_shadow_color="black";
  41      var $bar_shadow_hsize=3,$bar_shadow_vsize=3;    
  42      var $valuepos='top';
  43      var $iPattern=-1,$iPatternDensity=80,$iPatternColor='black';
  44      
  45  //---------------
  46  // CONSTRUCTOR
  47      function BarPlot(&$datay,$datax=false) {
  48      $this->Plot($datay,$datax);        
  49      ++$this->numpoints;
  50      }
  51  
  52  //---------------
  53  // PUBLIC METHODS    
  54      
  55      // Set a drop shadow for the bar (or rather an "up-right" shadow)
  56      function SetShadow($color="black",$hsize=3,$vsize=3,$show=true) {
  57      $this->bar_shadow=$show;
  58      $this->bar_shadow_color=$color;
  59      $this->bar_shadow_vsize=$vsize;
  60      $this->bar_shadow_hsize=$hsize;
  61          
  62      // Adjust the value margin to compensate for shadow
  63      $this->value->margin += $vsize;
  64      }
  65          
  66      // DEPRECATED use SetYBase instead
  67      function SetYMin($aYStartValue) {
  68      //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead.");        
  69      $this->ybase=$aYStartValue;
  70      }
  71  
  72      // Specify the base value for the bars
  73      function SetYBase($aYStartValue) {
  74      $this->ybase=$aYStartValue;
  75      }
  76      
  77      function Legend(&$graph) {
  78      if( $this->grad && $this->legend!="" && !$this->fill ) {
  79          $color=array($this->grad_fromcolor,$this->grad_tocolor);
  80          // In order to differentiate between gradients and cooors specified as an RGB triple
  81          $graph->legend->Add($this->legend,$color,"",-$this->grad_style,
  82                  $this->legendcsimtarget,$this->legendcsimalt);
  83      }
  84      elseif( $this->legend!="" && ($this->iPattern > -1 || is_array($this->iPattern)) ) {
  85          if( is_array($this->iPattern) ) {
  86          $p1 = $this->iPattern[0];
  87          $p2 = $this->iPatternColor[0];
  88          $p3 = $this->iPatternDensity[0];
  89          }
  90          else {
  91          $p1 = $this->iPattern;
  92          $p2 = $this->iPatternColor;
  93          $p3 = $this->iPatternDensity;
  94          }
  95          $color = array($p1,$p2,$p3,$this->fill_color);
  96          // A kludge: Too mark that we add a pattern we use a type value of < 100
  97          $graph->legend->Add($this->legend,$color,"",-101,
  98                  $this->legendcsimtarget,$this->legendcsimalt);
  99      }
 100      elseif( $this->fill_color && $this->legend!="" ) {
 101          if( is_array($this->fill_color) ) {
 102          $graph->legend->Add($this->legend,$this->fill_color[0],"",0,
 103                      $this->legendcsimtarget,$this->legendcsimalt);
 104          }
 105          else {
 106          $graph->legend->Add($this->legend,$this->fill_color,"",0,
 107                      $this->legendcsimtarget,$this->legendcsimalt);    
 108          }
 109      }
 110      }
 111  
 112      // Gets called before any axis are stroked
 113      function PreStrokeAdjust(&$graph) {
 114      parent::PreStrokeAdjust($graph);
 115  
 116      // If we are using a log Y-scale we want the base to be at the
 117      // minimum Y-value unless the user have specifically set some other
 118      // value than the default.
 119      if( substr($graph->axtype,-3,3)=="log" && $this->ybase==0 )
 120          $this->ybase = $graph->yaxis->scale->GetMinVal();
 121          
 122      // For a "text" X-axis scale we will adjust the
 123      // display of the bars a little bit.
 124      if( substr($graph->axtype,0,3)=="tex" ) {
 125          // Position the ticks between the bars
 126          $graph->xaxis->scale->ticks->SetXLabelOffset(0.5,0);
 127  
 128          // Center the bars 
 129          if( $this->abswidth > -1 ) {
 130          $graph->SetTextScaleAbsCenterOff($this->abswidth);
 131          }
 132          else {
 133          if( $this->align == "center" )
 134              $graph->SetTextScaleOff(0.5-$this->width/2);
 135          elseif( $this->align == "right" )
 136              $graph->SetTextScaleOff(1-$this->width);            
 137          }
 138  
 139      }
 140      elseif( is_a($this,'AccBarPlot') || is_a($this,'GroupBarPlot') ) { 
 141          // We only set an absolute width for linear and int scale
 142          // for text scale the width will be set to a fraction of
 143          // the majstep width.
 144          if( $this->abswidth == -1 ) {
 145                  // Not set
 146          // set width to a visuable sensible default
 147          $this->abswidth = $graph->img->plotwidth/(2*count($this->coords[0]));
 148          }
 149      }
 150      }
 151  
 152      function Min() {
 153      $m = parent::Min();
 154      if( $m[1] >= $this->ybase )
 155          $m[1] = $this->ybase;
 156      return $m;    
 157      }
 158  
 159      function Max() {
 160      $m = parent::Max();
 161      if( $m[1] <= $this->ybase )
 162          $m[1] = $this->ybase;
 163      return $m;    
 164      }    
 165      
 166      // Specify width as fractions of the major stepo size
 167      function SetWidth($aFractionWidth) {
 168      $this->width=$aFractionWidth;
 169      }
 170      
 171      // Specify width in absolute pixels. If specified this
 172      // overrides SetWidth()
 173      function SetAbsWidth($aWidth) {
 174      $this->abswidth=$aWidth;
 175      }
 176          
 177      function SetAlign($aAlign) {
 178      $this->align=$aAlign;
 179      }
 180      
 181      function SetNoFill() {
 182      $this->grad = false;
 183      $this->fill_color=false;
 184      $this->fill=false;
 185      }
 186          
 187      function SetFillColor($aColor) {
 188      $this->fill = true ;
 189      $this->fill_color=$aColor;
 190      }
 191      
 192      function SetFillGradient($from_color,$to_color,$style) {
 193      $this->grad=true;
 194      $this->grad_fromcolor=$from_color;
 195      $this->grad_tocolor=$to_color;
 196      $this->grad_style=$style;
 197      }
 198      
 199      function SetValuePos($aPos) {
 200      $this->valuepos = $aPos;
 201      }
 202  
 203      function SetPattern($aPattern, $aColor='black'){
 204      if( is_array($aPattern) ) {
 205          $n = count($aPattern);
 206          $this->iPattern = array();
 207          $this->iPatternDensity = array();
 208          if( is_array($aColor) ) {
 209          $this->iPatternColor = array();
 210          if( count($aColor) != $n ) {
 211              JpGraphError::RaiseL(2001);//('NUmber of colors is not the same as the number of patterns in BarPlot::SetPattern()');
 212          }
 213          }
 214          else
 215          $this->iPatternColor = $aColor;
 216          for( $i=0; $i < $n; ++$i ) {
 217          $this->_SetPatternHelper($aPattern[$i], $this->iPattern[$i], $this->iPatternDensity[$i]);
 218          if( is_array($aColor) ) {
 219              $this->iPatternColor[$i] = $aColor[$i];
 220          }
 221          }
 222      }
 223      else {
 224          $this->_SetPatternHelper($aPattern, $this->iPattern, $this->iPatternDensity);
 225          $this->iPatternColor = $aColor;
 226      }
 227      }
 228  
 229      function _SetPatternHelper($aPattern, &$aPatternValue, &$aDensity){
 230      switch( $aPattern ) {
 231          case PATTERN_DIAG1:
 232          $aPatternValue= 1;
 233          $aDensity = 90;
 234          break;
 235          case PATTERN_DIAG2:
 236          $aPatternValue= 1;
 237          $aDensity = 75;
 238          break;
 239          case PATTERN_DIAG3:
 240          $aPatternValue= 2;
 241          $aDensity = 90;
 242          break;
 243          case PATTERN_DIAG4:
 244          $aPatternValue= 2;
 245          $aDensity = 75;
 246          break;
 247          case PATTERN_CROSS1:
 248          $aPatternValue= 8;
 249          $aDensity = 90;
 250          break;
 251          case PATTERN_CROSS2:
 252          $aPatternValue= 8;
 253          $aDensity = 78;
 254          break;
 255          case PATTERN_CROSS3:
 256          $aPatternValue= 8;
 257          $aDensity = 65;
 258          break;
 259          case PATTERN_CROSS4:
 260          $aPatternValue= 7;
 261          $aDensity = 90;
 262          break;
 263          case PATTERN_STRIPE1:
 264          $aPatternValue= 5;
 265          $aDensity = 95;
 266          break;
 267          case PATTERN_STRIPE2:
 268          $aPatternValue= 5;
 269          $aDensity = 85;
 270          break;
 271          default:
 272          JpGraphError::RaiseL(2002);//('Unknown pattern specified in call to BarPlot::SetPattern()');
 273      }
 274      }
 275  
 276      function Stroke(&$img,&$xscale,&$yscale) { 
 277          
 278      $numpoints = count($this->coords[0]);
 279      if( isset($this->coords[1]) ) {
 280          if( count($this->coords[1])!=$numpoints )
 281          JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints);
 282  //("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])."Number of Y-points:$numpoints");
 283          else
 284          $exist_x = true;
 285      }
 286      else 
 287          $exist_x = false;
 288          
 289          
 290      $numbars=count($this->coords[0]);
 291  
 292      // Use GetMinVal() instead of scale[0] directly since in the case
 293      // of log scale we get a correct value. Log scales will have negative
 294      // values for values < 1 while still not representing negative numbers.
 295      if( $yscale->GetMinVal() >= 0 ) 
 296          $zp=$yscale->scale_abs[0]; 
 297      else {
 298          $zp=$yscale->Translate(0);
 299      }
 300  
 301      if( $this->abswidth > -1 ) {
 302          $abswidth=$this->abswidth;
 303      }
 304      else
 305          $abswidth=round($this->width*$xscale->scale_factor,0);
 306  
 307      // Count potential pattern array to avoid doing the count for each iteration
 308      if( is_array($this->iPattern) ) {
 309          $np = count($this->iPattern);
 310      }
 311                      
 312      for($i=0; $i < $numbars; ++$i) {
 313  
 314           // If value is NULL, or 0 then don't draw a bar at all
 315           if ($this->coords[0][$i] === null ||
 316          $this->coords[0][$i] === '' ||
 317          $this->coords[0][$i] === 0 ) continue;    
 318  
 319          if( $exist_x ) $x=$this->coords[1][$i];
 320          else $x=$i;
 321              
 322          $x=$xscale->Translate($x);
 323  
 324  // Comment Note: This confuses the positioning when using acc together with 
 325  // grouped bars. Workaround for fixing #191
 326  /*
 327          if( !$xscale->textscale ) {
 328              if($this->align=="center")
 329              $x -= $abswidth/2;
 330          elseif($this->align=="right")
 331              $x -= $abswidth;            
 332          }
 333  
 334  */
 335          // Stroke fill color and fill gradient
 336          $pts=array(
 337          $x,$zp,
 338          $x,$yscale->Translate($this->coords[0][$i]),
 339          $x+$abswidth,$yscale->Translate($this->coords[0][$i]),
 340          $x+$abswidth,$zp);
 341          if( $this->grad ) {
 342          $grad = new Gradient($img);
 343          $grad->FilledRectangle($pts[2],$pts[3],
 344                         $pts[6],$pts[7],
 345                         $this->grad_fromcolor,$this->grad_tocolor,$this->grad_style); 
 346          }
 347          elseif( !empty($this->fill_color) ) {
 348          if(is_array($this->fill_color)) {
 349              $img->PushColor($this->fill_color[$i % count($this->fill_color)]);
 350          } else {
 351              $img->PushColor($this->fill_color);
 352          }
 353          $img->FilledPolygon($pts);
 354          $img->PopColor();
 355          }
 356   
 357              
 358          // Remember value of this bar
 359          $val=$this->coords[0][$i];
 360  
 361          if( !empty($val) && !is_numeric($val) ) {
 362          JpGraphError::RaiseL(2004,$i,$val);
 363  //('All values for a barplot must be numeric. You have specified value['.$i.'] == \''.$val.'\'');
 364          }
 365  
 366          // Determine the shadow
 367          if( $this->bar_shadow && $val != 0) {
 368  
 369          $ssh = $this->bar_shadow_hsize;
 370          $ssv = $this->bar_shadow_vsize;
 371          // Create points to create a "upper-right" shadow
 372          if( $val > 0 ) {
 373              $sp[0]=$pts[6];        $sp[1]=$pts[7];
 374              $sp[2]=$pts[4];        $sp[3]=$pts[5];
 375              $sp[4]=$pts[2];        $sp[5]=$pts[3];
 376              $sp[6]=$pts[2]+$ssh;    $sp[7]=$pts[3]-$ssv;
 377              $sp[8]=$pts[4]+$ssh;    $sp[9]=$pts[5]-$ssv;
 378              $sp[10]=$pts[6]+$ssh;    $sp[11]=$pts[7]-$ssv;
 379          } 
 380          elseif( $val < 0 ) {
 381              $sp[0]=$pts[4];        $sp[1]=$pts[5];
 382              $sp[2]=$pts[6];        $sp[3]=$pts[7];
 383              $sp[4]=$pts[0];        $sp[5]=$pts[1];
 384              $sp[6]=$pts[0]+$ssh;    $sp[7]=$pts[1]-$ssv;
 385              $sp[8]=$pts[6]+$ssh;    $sp[9]=$pts[7]-$ssv;
 386              $sp[10]=$pts[4]+$ssh;    $sp[11]=$pts[5]-$ssv;
 387          }
 388          if( is_array($this->bar_shadow_color) ) {
 389              $numcolors = count($this->bar_shadow_color);
 390              if( $numcolors == 0 ) {
 391              JpGraphError::RaiseL(2005);//('You have specified an empty array for shadow colors in the bar plot.');
 392              }
 393              $img->PushColor($this->bar_shadow_color[$i % $numcolors]);
 394          }
 395          else {
 396              $img->PushColor($this->bar_shadow_color);
 397          }
 398          $img->FilledPolygon($sp);
 399          $img->PopColor();
 400          }
 401              
 402          // Stroke the pattern
 403          if( is_array($this->iPattern) ) {
 404          $f = new RectPatternFactory();
 405          if( is_array($this->iPatternColor) ) {
 406              $pcolor = $this->iPatternColor[$i % $np];
 407          }
 408          else
 409              $pcolor = $this->iPatternColor;
 410          $prect = $f->Create($this->iPattern[$i % $np],$pcolor,1);
 411          $prect->SetDensity($this->iPatternDensity[$i % $np]);
 412  
 413          if( $val < 0 ) {
 414              $rx = $pts[0];
 415              $ry = $pts[1];
 416          }
 417          else {
 418              $rx = $pts[2];
 419              $ry = $pts[3];
 420          }
 421          $width = abs($pts[4]-$pts[0])+1;
 422          $height = abs($pts[1]-$pts[3])+1;
 423          $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
 424          $prect->Stroke($img);
 425          }
 426          else {
 427          if( $this->iPattern > -1 ) {
 428              $f = new RectPatternFactory();
 429              $prect = $f->Create($this->iPattern,$this->iPatternColor,1);
 430              $prect->SetDensity($this->iPatternDensity);
 431              if( $val < 0 ) {
 432              $rx = $pts[0];
 433              $ry = $pts[1];
 434              }
 435              else {
 436              $rx = $pts[2];
 437              $ry = $pts[3];
 438              }
 439              $width = abs($pts[4]-$pts[0])+1;
 440              $height = abs($pts[1]-$pts[3])+1;
 441              $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
 442              $prect->Stroke($img);
 443          }
 444          }
 445          // Stroke the outline of the bar
 446          if( is_array($this->color) )
 447          $img->SetColor($this->color[$i % count($this->color)]);
 448          else
 449          $img->SetColor($this->color);
 450  
 451          $pts[] = $pts[0];
 452          $pts[] = $pts[1];
 453  
 454          if( $this->weight > 0 ) {
 455          $img->SetLineWeight($this->weight);
 456          $img->Polygon($pts);
 457          }
 458              
 459          // Determine how to best position the values of the individual bars
 460          $x=$pts[2]+($pts[4]-$pts[2])/2;
 461          if( $this->valuepos=='top' ) {
 462          $y=$pts[3];
 463          if( $img->a === 90 ) {
 464              if( $val < 0 )
 465              $this->value->SetAlign('right','center');            
 466              else
 467              $this->value->SetAlign('left','center');
 468              
 469          }
 470          $this->value->Stroke($img,$val,$x,$y);
 471          }
 472          elseif( $this->valuepos=='max' ) {
 473          $y=$pts[3];
 474          if( $img->a === 90 ) {
 475              if( $val < 0 )
 476              $this->value->SetAlign('left','center');
 477              else
 478              $this->value->SetAlign('right','center');            
 479          }
 480          else {
 481              $this->value->SetAlign('center','top');
 482          }
 483          $this->value->SetMargin(-3);
 484          $this->value->Stroke($img,$val,$x,$y);
 485          }
 486          elseif( $this->valuepos=='center' ) {
 487          $y = ($pts[3] + $pts[1])/2;
 488          $this->value->SetAlign('center','center');
 489          $this->value->SetMargin(0);
 490          $this->value->Stroke($img,$val,$x,$y);
 491          }
 492          elseif( $this->valuepos=='bottom' || $this->valuepos=='min' ) {
 493          $y=$pts[1];
 494          if( $img->a === 90 ) {
 495              if( $val < 0 )
 496              $this->value->SetAlign('right','center');
 497              else
 498              $this->value->SetAlign('left','center');                        
 499          }
 500          $this->value->SetMargin(3);
 501          $this->value->Stroke($img,$val,$x,$y);
 502          }
 503          else {
 504          JpGraphError::RaiseL(2006,$this->valuepos);
 505  //('Unknown position for values on bars :'.$this->valuepos);
 506          }
 507          // Create the client side image map
 508          $rpts = $img->ArrRotate($pts);        
 509          $csimcoord=round($rpts[0]).", ".round($rpts[1]);
 510          for( $j=1; $j < 4; ++$j){
 511          $csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]);
 512          }                
 513          if( !empty($this->csimtargets[$i]) ) {
 514          $this->csimareas .= '<area shape="poly" coords="'.$csimcoord.'" ';            
 515          $this->csimareas .= " href=\"".$this->csimtargets[$i]."\"";
 516          $sval='';
 517          if( !empty($this->csimalts[$i]) ) {
 518              $sval=sprintf($this->csimalts[$i],$this->coords[0][$i]);
 519              $this->csimareas .= " title=\"$sval\" ";
 520          }
 521          $this->csimareas .= " alt=\"$sval\" />\n";
 522          }
 523      }
 524      return true;
 525      }
 526  } // Class
 527  
 528  //===================================================
 529  // CLASS GroupBarPlot
 530  // Description: Produce grouped bar plots
 531  //===================================================
 532  class GroupBarPlot extends BarPlot {
 533      var $plots;
 534      var $width=0.7;
 535      var $nbrplots=0;
 536      var $numpoints;
 537  //---------------
 538  // CONSTRUCTOR
 539      function GroupBarPlot($plots) {
 540      $this->plots = $plots;
 541      $this->nbrplots = count($plots);
 542      if( $this->nbrplots < 1 ) {
 543          JpGraphError::RaiseL(2007);//('Cannot create GroupBarPlot from empty plot array.');
 544      }
 545      for($i=0; $i < $this->nbrplots; ++$i ) {
 546          if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) {
 547          JpGraphError::RaiseL(2008,$i);//("Group bar plot element nbr $i is undefined or empty.");
 548          }
 549      }
 550      $this->numpoints = $plots[0]->numpoints;
 551      }
 552  
 553  //---------------
 554  // PUBLIC METHODS    
 555      function Legend(&$graph) {
 556      $n = count($this->plots);
 557      for($i=0; $i < $n; ++$i) {
 558          $c = get_class($this->plots[$i]);
 559          if( !is_a($this->plots[$i],'BarPlot') ) {
 560          JpGraphError::RaiseL(2009,$c);//('One of the objects submitted to GroupBar is not a BarPlot. Make sure that you create the Group Bar plot from an array of BarPlot or AccBarPlot objects. (Class = '.$c.')');
 561          }
 562          $this->plots[$i]->DoLegend($graph);
 563      }
 564      }
 565      
 566      function Min() {
 567      list($xmin,$ymin) = $this->plots[0]->Min();
 568      $n = count($this->plots);
 569      for($i=0; $i < $n; ++$i) {
 570          list($xm,$ym) = $this->plots[$i]->Min();
 571          $xmin = max($xmin,$xm);
 572          $ymin = min($ymin,$ym);
 573      }
 574      return array($xmin,$ymin);        
 575      }
 576      
 577      function Max() {
 578      list($xmax,$ymax) = $this->plots[0]->Max();
 579      $n = count($this->plots);
 580      for($i=0; $i < $n; ++$i) {
 581          list($xm,$ym) = $this->plots[$i]->Max();
 582          $xmax = max($xmax,$xm);
 583          $ymax = max($ymax,$ym);
 584      }
 585      return array($xmax,$ymax);
 586      }
 587      
 588      function GetCSIMareas() {
 589      $n = count($this->plots);
 590      $csimareas='';
 591      for($i=0; $i < $n; ++$i) {
 592          $csimareas .= $this->plots[$i]->csimareas;
 593      }
 594      return $csimareas;
 595      }
 596      
 597      // Stroke all the bars next to each other
 598      function Stroke(&$img,&$xscale,&$yscale) { 
 599      $tmp=$xscale->off;
 600      $n = count($this->plots);
 601      $subwidth = $this->width/$this->nbrplots ; 
 602      for( $i=0; $i < $n; ++$i ) {
 603          $this->plots[$i]->ymin=$this->ybase;
 604          $this->plots[$i]->SetWidth($subwidth);
 605          
 606          // If the client have used SetTextTickInterval() then
 607          // major_step will be > 1 and the positioning will fail.
 608          // If we assume it is always one the positioning will work
 609          // fine with a text scale but this will not work with
 610          // arbitrary linear scale
 611          $xscale->off = $tmp+$i*round(/*$xscale->ticks->major_step* */
 612                      $xscale->scale_factor* $subwidth);
 613          $this->plots[$i]->Stroke($img,$xscale,$yscale);
 614      }
 615      $xscale->off=$tmp;
 616      }
 617  } // Class
 618  
 619  //===================================================
 620  // CLASS AccBarPlot
 621  // Description: Produce accumulated bar plots
 622  //===================================================
 623  class AccBarPlot extends BarPlot {
 624      var $plots=null,$nbrplots=0,$numpoints=0;
 625  //---------------
 626  // CONSTRUCTOR
 627      function AccBarPlot($plots) {
 628      $this->plots = $plots;
 629      $this->nbrplots = count($plots);
 630      if( $this->nbrplots < 1 ) {
 631          JpGraphError::RaiseL(2010);//('Cannot create AccBarPlot from empty plot array.');
 632      }
 633      for($i=0; $i < $this->nbrplots; ++$i ) {
 634          if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) {
 635          JpGraphError::RaiseL(2011,$i);//("Acc bar plot element nbr $i is undefined or empty.");
 636          }
 637      }
 638      $this->numpoints = $plots[0]->numpoints;        
 639      $this->value = new DisplayValue();
 640      }
 641  
 642  //---------------
 643  // PUBLIC METHODS    
 644      function Legend(&$graph) {
 645      $n = count($this->plots);
 646      for( $i=$n-1; $i >= 0; --$i ) {
 647          $c = get_class($this->plots[$i]);
 648          if( !is_a($this->plots[$i],'BarPlot') ) {
 649          JpGraphError::RaiseL(2012,$c);//('One of the objects submitted to AccBar is not a BarPlot. Make sure that you create the AccBar plot from an array of BarPlot objects.(Class='.$c.')');
 650          }        
 651          $this->plots[$i]->DoLegend($graph);
 652      }
 653      }
 654  
 655      function Max() {
 656      list($xmax) = $this->plots[0]->Max();
 657      $nmax=0;
 658      for($i=0; $i < count($this->plots); ++$i) {
 659          $n = count($this->plots[$i]->coords[0]);
 660          $nmax = max($nmax,$n);
 661          list($x) = $this->plots[$i]->Max();
 662          $xmax = max($xmax,$x);
 663      }
 664      for( $i = 0; $i < $nmax; $i++ ) {
 665          // Get y-value for bar $i by adding the
 666          // individual bars from all the plots added.
 667          // It would be wrong to just add the
 668          // individual plots max y-value since that
 669          // would in most cases give to large y-value.
 670          $y=0;
 671          if( !isset($this->plots[0]->coords[0][$i]) ) {
 672          JpGraphError::RaiseL(2014);
 673          }
 674          if( $this->plots[0]->coords[0][$i] > 0 )
 675          $y=$this->plots[0]->coords[0][$i];
 676          for( $j = 1; $j < $this->nbrplots; $j++ ) {
 677          if( !isset($this->plots[$j]->coords[0][$i]) ) {
 678              JpGraphError::RaiseL(2014);
 679          }
 680          if( $this->plots[$j]->coords[0][$i] > 0 )
 681              $y += $this->plots[$j]->coords[0][$i];
 682          }
 683          $ymax[$i] = $y;
 684      }
 685      $ymax = max($ymax);
 686  
 687      // Bar always start at baseline
 688      if( $ymax <= $this->ybase ) 
 689          $ymax = $this->ybase;
 690      return array($xmax,$ymax);
 691      }
 692  
 693      function Min() {
 694      $nmax=0;
 695      list($xmin,$ysetmin) = $this->plots[0]->Min();
 696      for($i=0; $i < count($this->plots); ++$i) {
 697          $n = count($this->plots[$i]->coords[0]);
 698          $nmax = max($nmax,$n);
 699          list($x,$y) = $this->plots[$i]->Min();
 700          $xmin = Min($xmin,$x);
 701          $ysetmin = Min($y,$ysetmin);
 702      }
 703      for( $i = 0; $i < $nmax; $i++ ) {
 704          // Get y-value for bar $i by adding the
 705          // individual bars from all the plots added.
 706          // It would be wrong to just add the
 707          // individual plots max y-value since that
 708          // would in most cases give to large y-value.
 709          $y=0;
 710          if( $this->plots[0]->coords[0][$i] < 0 )
 711          $y=$this->plots[0]->coords[0][$i];
 712          for( $j = 1; $j < $this->nbrplots; $j++ ) {
 713          if( $this->plots[$j]->coords[0][$i] < 0 )
 714              $y += $this->plots[ $j ]->coords[0][$i];
 715          }
 716          $ymin[$i] = $y;
 717      }
 718      $ymin = Min($ysetmin,Min($ymin));
 719      // Bar always start at baseline
 720      if( $ymin >= $this->ybase )
 721          $ymin = $this->ybase;
 722      return array($xmin,$ymin);
 723      }
 724  
 725      // Stroke acc bar plot
 726      function Stroke(&$img,&$xscale,&$yscale) {
 727      $pattern=NULL;
 728      $img->SetLineWeight($this->weight);
 729      for($i=0; $i < $this->numpoints-1; $i++) {
 730          $accy = 0;
 731          $accy_neg = 0; 
 732          for($j=0; $j < $this->nbrplots; ++$j ) {                
 733          $img->SetColor($this->plots[$j]->color);
 734  
 735          if ( $this->plots[$j]->coords[0][$i] >= 0) {
 736              $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
 737              $accyt=$yscale->Translate($accy);
 738              $accy+=$this->plots[$j]->coords[0][$i];
 739          }
 740          else {
 741              //if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) {
 742              $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
 743              $accyt=$yscale->Translate($accy_neg);
 744              $accy_neg+=$this->plots[$j]->coords[0][$i];
 745          }                
 746                  
 747          $xt=$xscale->Translate($i);
 748  
 749          if( $this->abswidth > -1 )
 750              $abswidth=$this->abswidth;
 751          else
 752              $abswidth=round($this->width*$xscale->scale_factor,0);
 753          
 754          $pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt);
 755  
 756          if( $this->bar_shadow ) {
 757              $ssh = $this->bar_shadow_hsize;
 758              $ssv = $this->bar_shadow_vsize;
 759              
 760              // We must also differ if we are a positive or negative bar. 
 761              if( $j === 0 ) {
 762              // This gets extra complicated since we have to
 763              // see all plots to see if we are negative. It could
 764              // for example be that all plots are 0 until the very
 765              // last one. We therefore need to save the initial setup
 766              // for both the negative and positive case
 767  
 768              // In case the final bar is positive
 769              $sp[0]=$pts[6]+1; $sp[1]=$pts[7];
 770              $sp[2]=$pts[6]+$ssh; $sp[3]=$pts[7]-$ssv;
 771  
 772              // In case the final bar is negative
 773              $nsp[0]=$pts[0]; $nsp[1]=$pts[1];
 774              $nsp[2]=$pts[0]+$ssh; $nsp[3]=$pts[1]-$ssv;
 775              $nsp[4]=$pts[6]+$ssh; $nsp[5]=$pts[7]-$ssv;
 776              $nsp[10]=$pts[6]+1; $nsp[11]=$pts[7];
 777              }
 778  
 779              if( $j === $this->nbrplots-1 ) {
 780              // If this is the last plot of the bar and
 781              // the total value is larger than 0 then we
 782              // add the shadow.
 783              if( is_array($this->bar_shadow_color) ) {
 784                  $numcolors = count($this->bar_shadow_color);
 785                  if( $numcolors == 0 ) {
 786                  JpGraphError::RaiseL(2013);//('You have specified an empty array for shadow colors in the bar plot.');
 787                  }
 788                  $img->PushColor($this->bar_shadow_color[$i % $numcolors]);
 789              }
 790              else {
 791                  $img->PushColor($this->bar_shadow_color);
 792              }
 793  
 794              if( $accy > 0 ) {
 795                  $sp[4]=$pts[4]+$ssh; $sp[5]=$pts[5]-$ssv;
 796                  $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv;
 797                  $sp[8]=$pts[2]; $sp[9]=$pts[3]-1;
 798                  $sp[10]=$pts[4]+1; $sp[11]=$pts[5];
 799                  $img->FilledPolygon($sp,4);
 800              }
 801              elseif( $accy_neg < 0 ) {
 802                  $nsp[6]=$pts[4]+$ssh; $nsp[7]=$pts[5]-$ssv;
 803                  $nsp[8]=$pts[4]+1; $nsp[9]=$pts[5];
 804                  $img->FilledPolygon($nsp,4);
 805              }
 806              $img->PopColor();
 807              }
 808          }
 809  
 810  
 811          // If value is NULL or 0, then don't draw a bar at all
 812          if ($this->plots[$j]->coords[0][$i] == 0 ) continue;
 813  
 814          if( $this->plots[$j]->grad ) {
 815              $grad = new Gradient($img);
 816              $grad->FilledRectangle(
 817              $pts[2],$pts[3],
 818              $pts[6],$pts[7],
 819              $this->plots[$j]->grad_fromcolor,
 820              $this->plots[$j]->grad_tocolor,
 821              $this->plots[$j]->grad_style);                
 822          } else {
 823              if (is_array($this->plots[$j]->fill_color) ) {
 824              $numcolors = count($this->plots[$j]->fill_color);
 825              $img->SetColor($this->plots[$j]->fill_color[$i % $numcolors]);
 826              }
 827              else {
 828              $img->SetColor($this->plots[$j]->fill_color);
 829              }
 830              $img->FilledPolygon($pts);
 831              $img->SetColor($this->plots[$j]->color);
 832          }                  
 833  
 834          // Stroke the pattern
 835          if( $this->plots[$j]->iPattern > -1 ) {
 836              if( $pattern===NULL ) 
 837              $pattern = new RectPatternFactory();
 838          
 839              $prect = $pattern->Create($this->plots[$j]->iPattern,$this->plots[$j]->iPatternColor,1);
 840              $prect->SetDensity($this->plots[$j]->iPatternDensity);
 841              if( $this->plots[$j]->coords[0][$i] < 0 ) {
 842              $rx = $pts[0];
 843              $ry = $pts[1];
 844              }
 845              else {
 846              $rx = $pts[2];
 847              $ry = $pts[3];
 848              }
 849              $width = abs($pts[4]-$pts[0])+1;
 850              $height = abs($pts[1]-$pts[3])+1;
 851              $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
 852              $prect->Stroke($img);
 853          }
 854  
 855  
 856          // CSIM array
 857  
 858          if( $i < count($this->plots[$j]->csimtargets) ) {
 859              // Create the client side image map
 860              $rpts = $img->ArrRotate($pts);        
 861              $csimcoord=round($rpts[0]).", ".round($rpts[1]);
 862              for( $k=1; $k < 4; ++$k){
 863              $csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]);
 864              }                
 865              if( ! empty($this->plots[$j]->csimtargets[$i]) ) {
 866              $this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" '; 
 867              $this->csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\"";
 868              if( !empty($this->plots[$j]->csimalts[$i]) ) {
 869                  $sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]);
 870                  $this->csimareas .= " title=\"$sval\" ";
 871              }
 872              $this->csimareas .= " alt=\"$sval\" />\n";                
 873              }
 874          }
 875  
 876          $pts[] = $pts[0];
 877          $pts[] = $pts[1];
 878          $img->Polygon($pts);
 879          }
 880          
 881          // Draw labels for each acc.bar
 882      
 883          $x=$pts[2]+($pts[4]-$pts[2])/2;
 884          if($this->bar_shadow) $x += $ssh;
 885  
 886          // First stroke the accumulated value for the entire bar
 887          // This value is always placed at the top/bottom of the bars
 888          if( $accy_neg < 0 ) {
 889          $y=$yscale->Translate($accy_neg);            
 890          $this->value->Stroke($img,$accy_neg,$x,$y);
 891          }
 892          else {
 893          $y=$yscale->Translate($accy);            
 894          $this->value->Stroke($img,$accy,$x,$y);
 895          }
 896  
 897          $accy = 0;
 898          $accy_neg = 0; 
 899          for($j=0; $j < $this->nbrplots; ++$j ) {    
 900  
 901          // We don't print 0 values in an accumulated bar plot
 902          if( $this->plots[$j]->coords[0][$i] == 0 ) continue;
 903              
 904          if ($this->plots[$j]->coords[0][$i] > 0) {
 905              $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
 906              $accyt=$yscale->Translate($accy);
 907              if(  $this->plots[$j]->valuepos=='center' ) {
 908              $y = $accyt-($accyt-$yt)/2;
 909              }
 910              elseif( $this->plots[$j]->valuepos=='bottom' ) {
 911              $y = $accyt;
 912              }
 913              else { // top or max
 914              $y = $accyt-($accyt-$yt);
 915              }
 916              $accy+=$this->plots[$j]->coords[0][$i];
 917              if(  $this->plots[$j]->valuepos=='center' ) {
 918              $this->plots[$j]->value->SetAlign("center","center");
 919              $this->plots[$j]->value->SetMargin(0);
 920              }
 921              elseif( $this->plots[$j]->valuepos=='bottom' ) {
 922              $this->plots[$j]->value->SetAlign('center','bottom');
 923              $this->plots[$j]->value->SetMargin(2);
 924              }
 925              else {
 926              $this->plots[$j]->value->SetAlign('center','top');
 927              $this->plots[$j]->value->SetMargin(1);
 928              }
 929          } else {
 930              $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
 931              $accyt=$yscale->Translate($accy_neg);
 932              $accy_neg+=$this->plots[$j]->coords[0][$i];
 933              if(  $this->plots[$j]->valuepos=='center' ) {
 934              $y = $accyt-($accyt-$yt)/2;
 935              }
 936              elseif( $this->plots[$j]->valuepos=='bottom' ) {
 937              $y = $accyt;
 938              }
 939              else {
 940              $y = $accyt-($accyt-$yt);
 941              }
 942              if(  $this->plots[$j]->valuepos=='center' ) {
 943              $this->plots[$j]->value->SetAlign("center","center");
 944              $this->plots[$j]->value->SetMargin(0);
 945              }
 946              elseif( $this->plots[$j]->valuepos=='bottom' ) {
 947              $this->plots[$j]->value->SetAlign('center',$j==0 ? 'bottom':'top');
 948              $this->plots[$j]->value->SetMargin(-2);
 949              }
 950              else {
 951              $this->plots[$j]->value->SetAlign('center','bottom');
 952              $this->plots[$j]->value->SetMargin(-1);
 953              }
 954          }    
 955          $this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],$x,$y);
 956          }
 957  
 958      }
 959      return true;
 960      }
 961  } // Class
 962  
 963  /* EOF */
 964  ?>


[ Powered by PHPXref - Served by Debian GNU/Linux ]