| [ PHPXref.com ] | [ Generated: Sun Jul 20 20:17:16 2008 ] | [ Simple Spreadsheet 0.3 ] |
| [ Index ] [ Variables ] [ Functions ] [ Classes ] [ Constants ] [ Statistics ] | ||
[Summary view] [Print] [Text view]
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 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| [ Powered by PHPXref - Served by Debian GNU/Linux ] |