diff options
Diffstat (limited to 'html/jpgraph/d2utmpFU7H53')
-rw-r--r-- | html/jpgraph/d2utmpFU7H53 | 1190 |
1 files changed, 1190 insertions, 0 deletions
diff --git a/html/jpgraph/d2utmpFU7H53 b/html/jpgraph/d2utmpFU7H53 new file mode 100644 index 0000000..ee01669 --- /dev/null +++ b/html/jpgraph/d2utmpFU7H53 @@ -0,0 +1,1190 @@ +<?php +/*======================================================================= + // File: JPGRAPH_BAR.PHP + // Description: Bar plot extension for JpGraph + // Created: 2001-01-08 + // Ver: $Id: jpgraph_bar.php 1905 2009-10-06 18:00:21Z ljp $ + // + // Copyright (c) Asial Corporation. All rights reserved. + //======================================================================== + */ + +require_once('jpgraph_plotband.php'); + +// Pattern for Bars +DEFINE('PATTERN_DIAG1',1); +DEFINE('PATTERN_DIAG2',2); +DEFINE('PATTERN_DIAG3',3); +DEFINE('PATTERN_DIAG4',4); +DEFINE('PATTERN_CROSS1',5); +DEFINE('PATTERN_CROSS2',6); +DEFINE('PATTERN_CROSS3',7); +DEFINE('PATTERN_CROSS4',8); +DEFINE('PATTERN_STRIPE1',9); +DEFINE('PATTERN_STRIPE2',10); + +//=================================================== +// CLASS BarPlot +// Description: Main code to produce a bar plot +//=================================================== +class BarPlot extends Plot { + public $fill=false,$fill_color="lightblue"; // Default is to fill with light blue + public $iPattern=-1,$iPatternDensity=80,$iPatternColor='black'; + public $valuepos='top'; + public $grad=false,$grad_style=1; + public $grad_fromcolor=array(50,50,200),$grad_tocolor=array(255,255,255); + public $ymin=0; + protected $width=0.4; // in percent of major ticks + protected $abswidth=-1; // Width in absolute pixels + protected $ybase=0; // Bars start at 0 + protected $align="center"; + protected $bar_shadow=false; + protected $bar_shadow_color="black"; + protected $bar_shadow_hsize=3,$bar_shadow_vsize=3; + protected $bar_3d=false; + protected $bar_3d_hsize=3,$bar_3d_vsize=3; + + //--------------- + // CONSTRUCTOR + function __construct($datay,$datax=false) { + parent::__construct($datay,$datax); + ++$this->numpoints; + } + + //--------------- + // PUBLIC METHODS + + // Set a drop shadow for the bar (or rather an "up-right" shadow) + function SetShadow($aColor="black",$aHSize=3,$aVSize=3,$aShow=true) { + $this->bar_shadow=$aShow; + $this->bar_shadow_color=$aColor; + $this->bar_shadow_vsize=$aVSize; + $this->bar_shadow_hsize=$aHSize; + + // Adjust the value margin to compensate for shadow + $this->value->margin += $aVSize; + } + + function Set3D($aHSize=3,$aVSize=3,$aShow=true) { + $this->bar_3d=$aShow; + $this->bar_3d_vsize=$aVSize; + $this->bar_3d_hsize=$aHSize; + + $this->value->margin += $aVSize; + } + + // DEPRECATED use SetYBase instead + function SetYMin($aYStartValue) { + //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead."); + $this->ybase=$aYStartValue; + } + + // Specify the base value for the bars + function SetYBase($aYStartValue) { + $this->ybase=$aYStartValue; + } + + // The method will take the specified pattern anre + // return a pattern index that corresponds to the original + // patterm being rotated 90 degreees. This is needed when plottin + // Horizontal bars + function RotatePattern($aPat,$aRotate=true) { + $rotate = array(1 => 2, 2 => 1, 3 => 3, 4 => 5, 5 => 4, 6 => 6, 7 => 7, 8 => 8); + if( $aRotate ) { + return $rotate[$aPat]; + } + else { + return $aPat; + } + } + + function Legend($graph) { + if( $this->grad && $this->legend!="" && !$this->fill ) { + $color=array($this->grad_fromcolor,$this->grad_tocolor); + // In order to differentiate between gradients and cooors specified as an RGB triple + $graph->legend->Add($this->legend,$color,"",-$this->grad_style, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + elseif( $this->legend!="" && ($this->iPattern > -1 || is_array($this->iPattern)) ) { + if( is_array($this->iPattern) ) { + $p1 = $this->RotatePattern( $this->iPattern[0], $graph->img->a == 90 ); + $p2 = $this->iPatternColor[0]; + $p3 = $this->iPatternDensity[0]; + } + else { + $p1 = $this->RotatePattern( $this->iPattern, $graph->img->a == 90 ); + $p2 = $this->iPatternColor; + $p3 = $this->iPatternDensity; + } + if( $p3 < 90 ) $p3 += 5; + $color = array($p1,$p2,$p3,$this->fill_color); + // A kludge: Too mark that we add a pattern we use a type value of < 100 + $graph->legend->Add($this->legend,$color,"",-101, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + elseif( $this->fill_color && $this->legend!="" ) { + if( is_array($this->fill_color) ) { + $graph->legend->Add($this->legend,$this->fill_color[0],"",0, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + else { + $graph->legend->Add($this->legend,$this->fill_color,"",0, + $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget); + } + } + } + + // Gets called before any axis are stroked + function PreStrokeAdjust($graph) { + parent::PreStrokeAdjust($graph); + + // If we are using a log Y-scale we want the base to be at the + // minimum Y-value unless the user have specifically set some other + // value than the default. + if( substr($graph->axtype,-3,3)=="log" && $this->ybase==0 ) + $this->ybase = $graph->yaxis->scale->GetMinVal(); + + // For a "text" X-axis scale we will adjust the + // display of the bars a little bit. + if( substr($graph->axtype,0,3)=="tex" ) { + // Position the ticks between the bars + $graph->xaxis->scale->ticks->SetXLabelOffset(0.5,0); + + // Center the bars + if( $this->abswidth > -1 ) { + $graph->SetTextScaleAbsCenterOff($this->abswidth); + } + else { + if( $this->align == "center" ) + $graph->SetTextScaleOff(0.5-$this->width/2); + elseif( $this->align == "right" ) + $graph->SetTextScaleOff(1-$this->width); + } + } + elseif( ($this instanceof AccBarPlot) || ($this instanceof GroupBarPlot) ) { + // We only set an absolute width for linear and int scale + // for text scale the width will be set to a fraction of + // the majstep width. + if( $this->abswidth == -1 ) { + // Not set + // set width to a visuable sensible default + $this->abswidth = $graph->img->plotwidth/(2*$this->numpoints); + } + } + } + + function Min() { + $m = parent::Min(); + if( $m[1] >= $this->ybase ) $m[1] = $this->ybase; + return $m; + } + + function Max() { + $m = parent::Max(); + if( $m[1] <= $this->ybase ) $m[1] = $this->ybase; + return $m; + } + + // Specify width as fractions of the major stepo size + function SetWidth($aWidth) { + if( $aWidth > 1 ) { + // Interpret this as absolute width + $this->abswidth=$aWidth; + } + else { + $this->width=$aWidth; + } + } + + // Specify width in absolute pixels. If specified this + // overrides SetWidth() + function SetAbsWidth($aWidth) { + $this->abswidth=$aWidth; + } + + function SetAlign($aAlign) { + $this->align=$aAlign; + } + + function SetNoFill() { + $this->grad = false; + $this->fill_color=false; + $this->fill=false; + } + + function SetFillColor($aColor) { + // Do an extra error check if the color is specified as an RGB array triple + // In that case convert it to a hex string since it will otherwise be + // interpretated as an array of colors for each individual bar. + + $aColor = RGB::tryHexConversion($aColor); + $this->fill = true ; + $this->fill_color=$aColor; + + } + + function SetFillGradient($aFromColor,$aToColor=null,$aStyle=null) { + $this->grad = true; + $this->grad_fromcolor = $aFromColor; + $this->grad_tocolor = $aToColor; + $this->grad_style = $aStyle; + } + + function SetValuePos($aPos) { + $this->valuepos = $aPos; + } + + function SetPattern($aPattern, $aColor='black'){ + if( is_array($aPattern) ) { + $n = count($aPattern); + $this->iPattern = array(); + $this->iPatternDensity = array(); + if( is_array($aColor) ) { + $this->iPatternColor = array(); + if( count($aColor) != $n ) { + JpGraphError::RaiseL(2001);//('NUmber of colors is not the same as the number of patterns in BarPlot::SetPattern()'); + } + } + else { + $this->iPatternColor = $aColor; + } + for( $i=0; $i < $n; ++$i ) { + $this->_SetPatternHelper($aPattern[$i], $this->iPattern[$i], $this->iPatternDensity[$i]); + if( is_array($aColor) ) { + $this->iPatternColor[$i] = $aColor[$i]; + } + } + } + else { + $this->_SetPatternHelper($aPattern, $this->iPattern, $this->iPatternDensity); + $this->iPatternColor = $aColor; + } + } + + function _SetPatternHelper($aPattern, &$aPatternValue, &$aDensity){ + switch( $aPattern ) { + case PATTERN_DIAG1: + $aPatternValue= 1; + $aDensity = 92; + break; + case PATTERN_DIAG2: + $aPatternValue= 1; + $aDensity = 78; + break; + case PATTERN_DIAG3: + $aPatternValue= 2; + $aDensity = 92; + break; + case PATTERN_DIAG4: + $aPatternValue= 2; + $aDensity = 78; + break; + case PATTERN_CROSS1: + $aPatternValue= 8; + $aDensity = 90; + break; + case PATTERN_CROSS2: + $aPatternValue= 8; + $aDensity = 78; + break; + case PATTERN_CROSS3: + $aPatternValue= 8; + $aDensity = 65; + break; + case PATTERN_CROSS4: + $aPatternValue= 7; + $aDensity = 90; + break; + case PATTERN_STRIPE1: + $aPatternValue= 5; + $aDensity = 94; + break; + case PATTERN_STRIPE2: + $aPatternValue= 5; + $aDensity = 85; + break; + default: + JpGraphError::RaiseL(2002); + //('Unknown pattern specified in call to BarPlot::SetPattern()'); + } + } + + function Stroke($img,$xscale,$yscale) { + + $numpoints = count($this->coords[0]); + if( isset($this->coords[1]) ) { + if( count($this->coords[1])!=$numpoints ) { + JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints); + //"Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])."Number of Y-points:$numpoints"); + } + else { + $exist_x = true; + } + } + else { + $exist_x = false; + } + + + $numbars=count($this->coords[0]); + + // Use GetMinVal() instead of scale[0] directly since in the case + // of log scale we get a correct value. Log scales will have negative + // values for values < 1 while still not representing negative numbers. + if( $yscale->GetMinVal() >= 0 ) + $zp=$yscale->scale_abs[0]; + else { + $zp=$yscale->Translate(0); + } + + if( $this->abswidth > -1 ) { + $abswidth=$this->abswidth; + } + else { + $abswidth=round($this->width*$xscale->scale_factor,0); + } + + // Count pontetial pattern array to avoid doing the count for each iteration + if( is_array($this->iPattern) ) { + $np = count($this->iPattern); + } + + $grad = null; + for($i=0; $i < $numbars; ++$i) { + + // If value is NULL, or 0 then don't draw a bar at all + if ($this->coords[0][$i] === null || $this->coords[0][$i] === '' ) + continue; + + if( $exist_x ) { + $x=$this->coords[1][$i]; + } + else { + $x=$i; + } + + $x=$xscale->Translate($x); + + // Comment Note: This confuses the positioning when using acc together with + // grouped bars. Workaround for fixing #191 + /* + if( !$xscale->textscale ) { + if($this->align=="center") + $x -= $abswidth/2; + elseif($this->align=="right") + $x -= $abswidth; + } + */ + // Stroke fill color and fill gradient + $pts=array( + $x,$zp, + $x,$yscale->Translate($this->coords[0][$i]), + $x+$abswidth,$yscale->Translate($this->coords[0][$i]), + $x+$abswidth,$zp); + if( $this->grad ) { + if( $grad === null ) { + $grad = new Gradient($img); + } + if( is_array($this->grad_fromcolor) ) { + // The first argument (grad_fromcolor) can be either an array or a single color. If it is an array + // then we have two choices. It can either a) be a single color specified as an RGB triple or it can be + // an array to specify both (from, to style) for each individual bar. The way to know the difference is + // to investgate the first element. If this element is an integer [0,255] then we assume it is an RGB + // triple. + $ng = count($this->grad_fromcolor); + if( $ng === 3 ) { + if( is_numeric($this->grad_fromcolor[0]) && $this->grad_fromcolor[0] > 0 && $this->grad_fromcolor[0] < 256 ) { + // RGB Triple + $fromcolor = $this->grad_fromcolor; + $tocolor = $this->grad_tocolor; + $style = $this->grad_style; + } + else { + $fromcolor = $this->grad_fromcolor[$i % $ng][0]; + $tocolor = $this->grad_fromcolor[$i % $ng][1]; + $style = $this->grad_fromcolor[$i % $ng][2]; + } + } + else { + $fromcolor = $this->grad_fromcolor[$i % $ng][0]; + $tocolor = $this->grad_fromcolor[$i % $ng][1]; + $style = $this->grad_fromcolor[$i % $ng][2]; + } + $grad->FilledRectangle($pts[2],$pts[3], + $pts[6],$pts[7], + $fromcolor,$tocolor,$style); + } + else { + $grad->FilledRectangle($pts[2],$pts[3], + $pts[6],$pts[7], + $this->grad_fromcolor,$this->grad_tocolor,$this->grad_style); + } + } + elseif( !empty($this->fill_color) ) { + if(is_array($this->fill_color)) { + $img->PushColor($this->fill_color[$i % count($this->fill_color)]); + } else { + $img->PushColor($this->fill_color); + } + $img->FilledPolygon($pts); + $img->PopColor(); + } + +/////////////////////////kokorahen rectangle polygon////////////////////// + + // Remember value of this bar + $val=$this->coords[0][$i]; + + if( !empty($val) && !is_numeric($val) ) { + JpGraphError::RaiseL(2004,$i,$val); + //'All values for a barplot must be numeric. You have specified value['.$i.'] == \''.$val.'\''); + } + + // Determine the shadow + if( $this->bar_shadow && $val != 0) { + + $ssh = $this->bar_shadow_hsize; + $ssv = $this->bar_shadow_vsize; + // Create points to create a "upper-right" shadow + if( $val > 0 ) { + $sp[0]=$pts[6]; $sp[1]=$pts[7]; + $sp[2]=$pts[4]; $sp[3]=$pts[5]; + $sp[4]=$pts[2]; $sp[5]=$pts[3]; + $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv; + $sp[8]=$pts[4]+$ssh; $sp[9]=$pts[5]-$ssv; + $sp[10]=$pts[6]+$ssh; $sp[11]=$pts[7]-$ssv; + } + elseif( $val < 0 ) { + $sp[0]=$pts[4]; $sp[1]=$pts[5]; + $sp[2]=$pts[6]; $sp[3]=$pts[7]; + $sp[4]=$pts[0]; $sp[5]=$pts[1]; + $sp[6]=$pts[0]+$ssh; $sp[7]=$pts[1]-$ssv; + $sp[8]=$pts[6]+$ssh; $sp[9]=$pts[7]-$ssv; + $sp[10]=$pts[4]+$ssh; $sp[11]=$pts[5]-$ssv; + } + if( is_array($this->bar_shadow_color) ) { + $numcolors = count($this->bar_shadow_color); + if( $numcolors == 0 ) { + JpGraphError::RaiseL(2005);//('You have specified an empty array for shadow colors in the bar plot.'); + } + $img->PushColor($this->bar_shadow_color[$i % $numcolors]); + } + else { + $img->PushColor($this->bar_shadow_color); + } + $img->FilledPolygon($sp); + $img->PopColor(); + + } elseif( $this->bar_3d && $val != 0) { + // Determine the 3D + + $ssh = $this->bar_3d_hsize; + $ssv = $this->bar_3d_vsize; + + // Create points to create a "upper-right" shadow + if( $val > 0 ) { + $sp1[0]=$pts[6]; $sp1[1]=$pts[7]; + $sp1[2]=$pts[4]; $sp1[3]=$pts[5]; + $sp1[4]=$pts[4]+$ssh; $sp1[5]=$pts[5]-$ssv; + $sp1[6]=$pts[6]+$ssh; $sp1[7]=$pts[7]-$ssv; + + $sp2[0]=$pts[4]; $sp2[1]=$pts[5]; + $sp2[2]=$pts[2]; $sp2[3]=$pts[3]; + $sp2[4]=$pts[2]+$ssh; $sp2[5]=$pts[3]-$ssv; + $sp2[6]=$pts[4]+$ssh; $sp2[7]=$pts[5]-$ssv; + + } + elseif( $val < 0 ) { + $sp1[0]=$pts[4]; $sp1[1]=$pts[5]; + $sp1[2]=$pts[6]; $sp1[3]=$pts[7]; + $sp1[4]=$pts[6]+$ssh; $sp1[5]=$pts[7]-$ssv; + $sp1[6]=$pts[4]+$ssh; $sp1[7]=$pts[5]-$ssv; + + $sp2[0]=$pts[6]; $sp2[1]=$pts[7]; + $sp2[2]=$pts[0]; $sp2[3]=$pts[1]; + $sp2[4]=$pts[0]+$ssh; $sp2[5]=$pts[1]-$ssv; + $sp2[6]=$pts[6]+$ssh; $sp2[7]=$pts[7]-$ssv; + } + + $base_color = $this->fill_color; + + $img->PushColor($base_color . ':0.7'); + $img->FilledPolygon($sp1); + $img->PopColor(); + + $img->PushColor($base_color . ':1.1'); + $img->FilledPolygon($sp2); + $img->PopColor(); + } + + // Stroke the pattern + if( is_array($this->iPattern) ) { + $f = new RectPatternFactory(); + if( is_array($this->iPatternColor) ) { + $pcolor = $this->iPatternColor[$i % $np]; + } + else { + $pcolor = $this->iPatternColor; + } + $prect = $f->Create($this->iPattern[$i % $np],$pcolor,1); + $prect->SetDensity($this->iPatternDensity[$i % $np]); + + if( $val < 0 ) { + $rx = $pts[0]; + $ry = $pts[1]; + } + else { + $rx = $pts[2]; + $ry = $pts[3]; + } + $width = abs($pts[4]-$pts[0])+1; + $height = abs($pts[1]-$pts[3])+1; + $prect->SetPos(new Rectangle($rx,$ry,$width,$height)); + $prect->Stroke($img); + } + else { + if( $this->iPattern > -1 ) { + $f = new RectPatternFactory(); + $prect = $f->Create($this->iPattern,$this->iPatternColor,1); + $prect->SetDensity($this->iPatternDensity); + if( $val < 0 ) { + $rx = $pts[0]; + $ry = $pts[1]; + } + else { + $rx = $pts[2]; + $ry = $pts[3]; + } + $width = abs($pts[4]-$pts[0])+1; + $height = abs($pts[1]-$pts[3])+1; + $prect->SetPos(new Rectangle($rx,$ry,$width,$height)); + $prect->Stroke($img); + } + } + + // Stroke the outline of the bar + if( is_array($this->color) ) { + $img->SetColor($this->color[$i % count($this->color)]); + } + else { + $img->SetColor($this->color); + } + + $pts[] = $pts[0]; + $pts[] = $pts[1]; + + if( $this->weight > 0 ) { + $img->SetLineWeight($this->weight); + $img->Polygon($pts); + } + + // Determine how to best position the values of the individual bars + $x=$pts[2]+($pts[4]-$pts[2])/2; + $this->value->SetMargin(5); + + if( $this->valuepos=='top' ) { + $y=$pts[3]; + if( $img->a === 90 ) { + if( $val < 0 ) { + $this->value->SetAlign('right','center'); + } + else { + $this->value->SetAlign('left','center'); + } + + } + else { + if( $val < 0 ) { + $this->value->SetMargin(-5); + $y=$pts[1]; + $this->value->SetAlign('center','bottom'); + } + else { + $this->value->SetAlign('center','bottom'); + } + + } + $this->value->Stroke($img,$val,$x,$y); + } + elseif( $this->valuepos=='max' ) { + $y=$pts[3]; + if( $img->a === 90 ) { + if( $val < 0 ) + $this->value->SetAlign('left','center'); + else + $this->value->SetAlign('right','center'); + } + else { + if( $val < 0 ) { + $this->value->SetAlign('center','bottom'); + } + else { + $this->value->SetAlign('center','top'); + } + } + $this->value->SetMargin(-5); + $this->value->Stroke($img,$val,$x,$y); + } + elseif( $this->valuepos=='center' ) { + $y = ($pts[3] + $pts[1])/2; + $this->value->SetAlign('center','center'); + $this->value->SetMargin(0); + $this->value->Stroke($img,$val,$x,$y); + } + elseif( $this->valuepos=='bottom' || $this->valuepos=='min' ) { + $y=$pts[1]; + if( $img->a === 90 ) { + if( $val < 0 ) + $this->value->SetAlign('right','center'); + else + $this->value->SetAlign('left','center'); + } + $this->value->SetMargin(3); + $this->value->Stroke($img,$val,$x,$y); + } + else { + JpGraphError::RaiseL(2006,$this->valuepos); + //'Unknown position for values on bars :'.$this->valuepos); + } + // Create the client side image map + $rpts = $img->ArrRotate($pts); + $csimcoord=round($rpts[0]).", ".round($rpts[1]); + for( $j=1; $j < 4; ++$j){ + $csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]); + } + if( !empty($this->csimtargets[$i]) ) { + $this->csimareas .= '<area shape="poly" coords="'.$csimcoord.'" '; + $this->csimareas .= " href=\"".htmlentities($this->csimtargets[$i])."\""; + + if( !empty($this->csimwintargets[$i]) ) { + $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" "; + } + + $sval=''; + if( !empty($this->csimalts[$i]) ) { + $sval=sprintf($this->csimalts[$i],$this->coords[0][$i]); + $this->csimareas .= " title=\"$sval\" alt=\"$sval\" "; + } + $this->csimareas .= " />\n"; + } + } + return true; + } +} // Class + +//=================================================== +// CLASS GroupBarPlot +// Description: Produce grouped bar plots +//=================================================== +class GroupBarPlot extends BarPlot { + public $plots; + private $nbrplots=0; + //--------------- + // CONSTRUCTOR + function GroupBarPlot($plots) { + $this->width=0.7; + $this->plots = $plots; + $this->nbrplots = count($plots); + if( $this->nbrplots < 1 ) { + JpGraphError::RaiseL(2007);//('Cannot create GroupBarPlot from empty plot array.'); + } + for($i=0; $i < $this->nbrplots; ++$i ) { + if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) { + JpGraphError::RaiseL(2008,$i);//("Group bar plot element nbr $i is undefined or empty."); + } + } + $this->numpoints = $plots[0]->numpoints; + $this->width=0.7; + } + + //--------------- + // PUBLIC METHODS + function Legend($graph) { + $n = count($this->plots); + for($i=0; $i < $n; ++$i) { + $c = get_class($this->plots[$i]); + if( !($this->plots[$i] instanceof BarPlot) ) { + 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.')'); + } + $this->plots[$i]->DoLegend($graph); + } + } + + function Min() { + list($xmin,$ymin) = $this->plots[0]->Min(); + $n = count($this->plots); + for($i=0; $i < $n; ++$i) { + list($xm,$ym) = $this->plots[$i]->Min(); + $xmin = max($xmin,$xm); + $ymin = min($ymin,$ym); + } + return array($xmin,$ymin); + } + + function Max() { + list($xmax,$ymax) = $this->plots[0]->Max(); + $n = count($this->plots); + for($i=0; $i < $n; ++$i) { + list($xm,$ym) = $this->plots[$i]->Max(); + $xmax = max($xmax,$xm); + $ymax = max($ymax,$ym); + } + return array($xmax,$ymax); + } + + function GetCSIMareas() { + $n = count($this->plots); + $csimareas=''; + for($i=0; $i < $n; ++$i) { + $csimareas .= $this->plots[$i]->csimareas; + } + return $csimareas; + } + + // Stroke all the bars next to each other + function Stroke($img,$xscale,$yscale) { + $tmp=$xscale->off; + $n = count($this->plots); + $subwidth = $this->width/$this->nbrplots ; + + for( $i=0; $i < $n; ++$i ) { + $this->plots[$i]->ymin=$this->ybase; + $this->plots[$i]->SetWidth($subwidth); + + // If the client have used SetTextTickInterval() then + // major_step will be > 1 and the positioning will fail. + // If we assume it is always one the positioning will work + // fine with a text scale but this will not work with + // arbitrary linear scale + $xscale->off = $tmp+$i*round($xscale->scale_factor* $subwidth); + $this->plots[$i]->Stroke($img,$xscale,$yscale); + } + $xscale->off=$tmp; + } +} // Class + +//=================================================== +// CLASS AccBarPlot +// Description: Produce accumulated bar plots +//=================================================== +class AccBarPlot extends BarPlot { + public $plots=null; + private $nbrplots=0; + //--------------- + // CONSTRUCTOR + function __construct($plots) { + $this->plots = $plots; + $this->nbrplots = count($plots); + if( $this->nbrplots < 1 ) { + JpGraphError::RaiseL(2010);//('Cannot create AccBarPlot from empty plot array.'); + } + for($i=0; $i < $this->nbrplots; ++$i ) { + if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) { + JpGraphError::RaiseL(2011,$i);//("Acc bar plot element nbr $i is undefined or empty."); + } + } + + // We can only allow individual plost which do not have specified X-positions + for($i=0; $i < $this->nbrplots; ++$i ) { + if( !empty($this->plots[$i]->coords[1]) ) { + JpGraphError::RaiseL(2015); + //'Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-positions.'); + } + } + + // Use 0 weight by default which means that the individual bar + // weights will be used per part n the accumulated bar + $this->SetWeight(0); + + $this->numpoints = $plots[0]->numpoints; + $this->value = new DisplayValue(); + } + + //--------------- + // PUBLIC METHODS + function Legend($graph) { + $n = count($this->plots); + for( $i=$n-1; $i >= 0; --$i ) { + $c = get_class($this->plots[$i]); + if( !($this->plots[$i] instanceof BarPlot) ) { + 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.')'); + } + $this->plots[$i]->DoLegend($graph); + } + } + + function Max() { + list($xmax) = $this->plots[0]->Max(); + $nmax=0; + for($i=0; $i < count($this->plots); ++$i) { + $n = count($this->plots[$i]->coords[0]); + $nmax = max($nmax,$n); + list($x) = $this->plots[$i]->Max(); + $xmax = max($xmax,$x); + } + for( $i = 0; $i < $nmax; $i++ ) { + // Get y-value for bar $i by adding the + // individual bars from all the plots added. + // It would be wrong to just add the + // individual plots max y-value since that + // would in most cases give to large y-value. + $y=0; + if( !isset($this->plots[0]->coords[0][$i]) ) { + JpGraphError::RaiseL(2014); + } + if( $this->plots[0]->coords[0][$i] > 0 ) + $y=$this->plots[0]->coords[0][$i]; + for( $j = 1; $j < $this->nbrplots; $j++ ) { + if( !isset($this->plots[$j]->coords[0][$i]) ) { + JpGraphError::RaiseL(2014); + } + if( $this->plots[$j]->coords[0][$i] > 0 ) + $y += $this->plots[$j]->coords[0][$i]; + } + $ymax[$i] = $y; + } + $ymax = max($ymax); + + // Bar always start at baseline + if( $ymax <= $this->ybase ) + $ymax = $this->ybase; + return array($xmax,$ymax); + } + + function Min() { + $nmax=0; + list($xmin,$ysetmin) = $this->plots[0]->Min(); + for($i=0; $i < count($this->plots); ++$i) { + $n = count($this->plots[$i]->coords[0]); + $nmax = max($nmax,$n); + list($x,$y) = $this->plots[$i]->Min(); + $xmin = Min($xmin,$x); + $ysetmin = Min($y,$ysetmin); + } + for( $i = 0; $i < $nmax; $i++ ) { + // Get y-value for bar $i by adding the + // individual bars from all the plots added. + // It would be wrong to just add the + // individual plots max y-value since that + // would in most cases give to large y-value. + $y=0; + if( $this->plots[0]->coords[0][$i] < 0 ) + $y=$this->plots[0]->coords[0][$i]; + for( $j = 1; $j < $this->nbrplots; $j++ ) { + if( $this->plots[$j]->coords[0][$i] < 0 ) + $y += $this->plots[ $j ]->coords[0][$i]; + } + $ymin[$i] = $y; + } + $ymin = Min($ysetmin,Min($ymin)); + // Bar always start at baseline + if( $ymin >= $this->ybase ) + $ymin = $this->ybase; + return array($xmin,$ymin); + } + + // Stroke acc bar plot + function Stroke($img,$xscale,$yscale) { + $pattern=NULL; + $img->SetLineWeight($this->weight); + $grad=null; + for($i=0; $i < $this->numpoints-1; $i++) { + $accy = 0; + $accy_neg = 0; + for($j=0; $j < $this->nbrplots; ++$j ) { + $img->SetColor($this->plots[$j]->color); + + if ( $this->plots[$j]->coords[0][$i] >= 0) { + $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy); + $accyt=$yscale->Translate($accy); + $accy+=$this->plots[$j]->coords[0][$i]; + } + else { + //if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) { + $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg); + $accyt=$yscale->Translate($accy_neg); + $accy_neg+=$this->plots[$j]->coords[0][$i]; + } + + $xt=$xscale->Translate($i); + + if( $this->abswidth > -1 ) { + $abswidth=$this->abswidth; + } + else { + $abswidth=round($this->width*$xscale->scale_factor,0); + } + + $pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt); + + if( $this->bar_shadow ) { + $ssh = $this->bar_shadow_hsize; + $ssv = $this->bar_shadow_vsize; + + // We must also differ if we are a positive or negative bar. + if( $j === 0 ) { + // This gets extra complicated since we have to + // see all plots to see if we are negative. It could + // for example be that all plots are 0 until the very + // last one. We therefore need to save the initial setup + // for both the negative and positive case + + // In case the final bar is positive + $sp[0]=$pts[6]+1; $sp[1]=$pts[7]; + $sp[2]=$pts[6]+$ssh; $sp[3]=$pts[7]-$ssv; + + // In case the final bar is negative + $nsp[0]=$pts[0]; $nsp[1]=$pts[1]; + $nsp[2]=$pts[0]+$ssh; $nsp[3]=$pts[1]-$ssv; + $nsp[4]=$pts[6]+$ssh; $nsp[5]=$pts[7]-$ssv; + $nsp[10]=$pts[6]+1; $nsp[11]=$pts[7]; + } + + if( $j === $this->nbrplots-1 ) { + // If this is the last plot of the bar and + // the total value is larger than 0 then we + // add the shadow. + if( is_array($this->bar_shadow_color) ) { + $numcolors = count($this->bar_shadow_color); + if( $numcolors == 0 ) { + JpGraphError::RaiseL(2013);//('You have specified an empty array for shadow colors in the bar plot.'); + } + $img->PushColor($this->bar_shadow_color[$i % $numcolors]); + } + else { + $img->PushColor($this->bar_shadow_color); + } + + if( $accy > 0 ) { + $sp[4]=$pts[4]+$ssh; $sp[5]=$pts[5]-$ssv; + $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv; + $sp[8]=$pts[2]; $sp[9]=$pts[3]-1; + $sp[10]=$pts[4]+1; $sp[11]=$pts[5]; + $img->FilledPolygon($sp,4); + } + elseif( $accy_neg < 0 ) { + $nsp[6]=$pts[4]+$ssh; $nsp[7]=$pts[5]-$ssv; + $nsp[8]=$pts[4]+1; $nsp[9]=$pts[5]; + $img->FilledPolygon($nsp,4); + } + $img->PopColor(); + } + } + + + // If value is NULL or 0, then don't draw a bar at all + if ($this->plots[$j]->coords[0][$i] == 0 ) continue; + + if( $this->plots[$j]->grad ) { + if( $grad === null ) { + $grad = new Gradient($img); + } + if( is_array($this->plots[$j]->grad_fromcolor) ) { + // The first argument (grad_fromcolor) can be either an array or a single color. If it is an array + // then we have two choices. It can either a) be a single color specified as an RGB triple or it can be + // an array to specify both (from, to style) for each individual bar. The way to know the difference is + // to investgate the first element. If this element is an integer [0,255] then we assume it is an RGB + // triple. + $ng = count($this->plots[$j]->grad_fromcolor); + if( $ng === 3 ) { + if( is_numeric($this->plots[$j]->grad_fromcolor[0]) && $this->plots[$j]->grad_fromcolor[0] > 0 && + $this->plots[$j]->grad_fromcolor[0] < 256 ) { + // RGB Triple + $fromcolor = $this->plots[$j]->grad_fromcolor; + $tocolor = $this->plots[$j]->grad_tocolor; + $style = $this->plots[$j]->grad_style; + } + else { + $fromcolor = $this->plots[$j]->grad_fromcolor[$i % $ng][0]; + $tocolor = $this->plots[$j]->grad_fromcolor[$i % $ng][1]; + $style = $this->plots[$j]->grad_fromcolor[$i % $ng][2]; + } + } + else { + $fromcolor = $this->plots[$j]->grad_fromcolor[$i % $ng][0]; + $tocolor = $this->plots[$j]->grad_fromcolor[$i % $ng][1]; + $style = $this->plots[$j]->grad_fromcolor[$i % $ng][2]; + } + $grad->FilledRectangle($pts[2],$pts[3], + $pts[6],$pts[7], + $fromcolor,$tocolor,$style); + } + else { + $grad->FilledRectangle($pts[2],$pts[3], + $pts[6],$pts[7], + $this->plots[$j]->grad_fromcolor, + $this->plots[$j]->grad_tocolor, + $this->plots[$j]->grad_style); + } + } else { + if (is_array($this->plots[$j]->fill_color) ) { + $numcolors = count($this->plots[$j]->fill_color); + $fillcolor = $this->plots[$j]->fill_color[$i % $numcolors]; + // If the bar is specified to be non filled then the fill color is false + if( $fillcolor !== false ) { + $img->SetColor($this->plots[$j]->fill_color[$i % $numcolors]); + } + } + else { + $fillcolor = $this->plots[$j]->fill_color; + if( $fillcolor !== false ) { + $img->SetColor($this->plots[$j]->fill_color); + } + } + if( $fillcolor !== false ) { + $img->FilledPolygon($pts); + } + } + + $img->SetColor($this->plots[$j]->color); + + // Stroke the pattern + if( $this->plots[$j]->iPattern > -1 ) { + if( $pattern===NULL ) { + $pattern = new RectPatternFactory(); + } + + $prect = $pattern->Create($this->plots[$j]->iPattern,$this->plots[$j]->iPatternColor,1); + $prect->SetDensity($this->plots[$j]->iPatternDensity); + if( $this->plots[$j]->coords[0][$i] < 0 ) { + $rx = $pts[0]; + $ry = $pts[1]; + } + else { + $rx = $pts[2]; + $ry = $pts[3]; + } + $width = abs($pts[4]-$pts[0])+1; + $height = abs($pts[1]-$pts[3])+1; + $prect->SetPos(new Rectangle($rx,$ry,$width,$height)); + $prect->Stroke($img); + } + + + // CSIM array + + if( $i < count($this->plots[$j]->csimtargets) ) { + // Create the client side image map + $rpts = $img->ArrRotate($pts); + $csimcoord=round($rpts[0]).", ".round($rpts[1]); + for( $k=1; $k < 4; ++$k){ + $csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]); + } + if( ! empty($this->plots[$j]->csimtargets[$i]) ) { + $this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" '; + $this->csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\" "; + + if( ! empty($this->plots[$j]->csimwintargets[$i]) ) { + $this->csimareas.= " target=\"".$this->plots[$j]->csimwintargets[$i]."\" "; + } + + $sval=''; + if( !empty($this->plots[$j]->csimalts[$i]) ) { + $sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]); + $this->csimareas .= " title=\"$sval\" "; + } + $this->csimareas .= " alt=\"$sval\" />\n"; + } + } + + $pts[] = $pts[0]; + $pts[] = $pts[1]; + $img->SetLineWeight($this->plots[$j]->weight); + $img->Polygon($pts); + $img->SetLineWeight(1); + } + + // Daw potential bar around the entire accbar bar + if( $this->weight > 0 ) { + $y=$yscale->Translate(0); + $img->SetColor($this->color); + $img->SetLineWeight($this->weight); + $img->Rectangle($pts[0],$y,$pts[6],$pts[5]); + } + + // Draw labels for each acc.bar + + $x=$pts[2]+($pts[4]-$pts[2])/2; + if($this->bar_shadow) $x += $ssh; + + // First stroke the accumulated value for the entire bar + // This value is always placed at the top/bottom of the bars + if( $accy_neg < 0 ) { + $y=$yscale->Translate($accy_neg); + $this->value->Stroke($img,$accy_neg,$x,$y); + } + else { + $y=$yscale->Translate($accy); + $this->value->Stroke($img,$accy,$x,$y); + } + + $accy = 0; + $accy_neg = 0; + for($j=0; $j < $this->nbrplots; ++$j ) { + + // We don't print 0 values in an accumulated bar plot + if( $this->plots[$j]->coords[0][$i] == 0 ) continue; + + if ($this->plots[$j]->coords[0][$i] > 0) { + $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy); + $accyt=$yscale->Translate($accy); + if( $this->plots[$j]->valuepos=='center' ) { + $y = $accyt-($accyt-$yt)/2; + } + elseif( $this->plots[$j]->valuepos=='bottom' ) { + $y = $accyt; + } + else { // top or max + $y = $accyt-($accyt-$yt); + } + $accy+=$this->plots[$j]->coords[0][$i]; + if( $this->plots[$j]->valuepos=='center' ) { + $this->plots[$j]->value->SetAlign("center","center"); + $this->plots[$j]->value->SetMargin(0); + } + elseif( $this->plots[$j]->valuepos=='bottom' ) { + $this->plots[$j]->value->SetAlign('center','bottom'); + $this->plots[$j]->value->SetMargin(2); + } + else { + $this->plots[$j]->value->SetAlign('center','top'); + $this->plots[$j]->value->SetMargin(1); + } + } else { + $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg); + $accyt=$yscale->Translate($accy_neg); + $accy_neg+=$this->plots[$j]->coords[0][$i]; + if( $this->plots[$j]->valuepos=='center' ) { + $y = $accyt-($accyt-$yt)/2; + } + elseif( $this->plots[$j]->valuepos=='bottom' ) { + $y = $accyt; + } + else { + $y = $accyt-($accyt-$yt); + } + if( $this->plots[$j]->valuepos=='center' ) { + $this->plots[$j]->value->SetAlign("center","center"); + $this->plots[$j]->value->SetMargin(0); + } + elseif( $this->plots[$j]->valuepos=='bottom' ) { + $this->plots[$j]->value->SetAlign('center',$j==0 ? 'bottom':'top'); + $this->plots[$j]->value->SetMargin(-2); + } + else { + $this->plots[$j]->value->SetAlign('center','bottom'); + $this->plots[$j]->value->SetMargin(-1); + } + } + $this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],$x,$y); + } + + } + return true; + } +} // Class + +/* EOF */ +?> |