Ignore:
Timestamp:
Apr 13, 2019, 8:05:15 PM (5 years ago)
Author:
roby
Message:
 
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/client/modules/Elezioni/grafici/jpgraph_bar.php

    r2 r265  
    11<?php
    22/*=======================================================================
    3 // File:        JPGRAPH_BAR.PHP
    4 // Description: Bar plot extension for JpGraph
    5 // Created:     2001-01-08
    6 // Ver:         $Id: jpgraph_bar.php 1017 2008-07-08 06:09:28Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. All rights reserved.
    9 //========================================================================
    10 */
     3 // File:        JPGRAPH_BAR.PHP
     4 // Description: Bar plot extension for JpGraph
     5 // Created:     2001-01-08
     6 // Ver:         $Id: jpgraph_bar.php 1905 2009-10-06 18:00:21Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. All rights reserved.
     9 //========================================================================
     10 */
    1111
    1212require_once('jpgraph_plotband.php');
     
    2626//===================================================
    2727// CLASS BarPlot
    28 // Description: Main code to produce a bar plot 
     28// Description: Main code to produce a bar plot
    2929//===================================================
    3030class BarPlot extends Plot {
     
    3737    protected $width=0.4; // in percent of major ticks
    3838    protected $abswidth=-1; // Width in absolute pixels
    39     protected $ybase=0; // Bars start at 0 
     39    protected $ybase=0; // Bars start at 0
    4040    protected $align="center";
    4141    protected $bar_shadow=false;
    4242    protected $bar_shadow_color="black";
    43     protected $bar_shadow_hsize=3,$bar_shadow_vsize=3; 
    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        
     43    protected $bar_shadow_hsize=3,$bar_shadow_vsize=3;
     44    protected $bar_3d=false;
     45    protected $bar_3d_hsize=3,$bar_3d_vsize=3;
     46
     47    //---------------
     48    // CONSTRUCTOR
     49    function __construct($datay,$datax=false) {
     50        parent::__construct($datay,$datax);
     51        ++$this->numpoints;
     52    }
     53
     54    //---------------
     55    // PUBLIC METHODS
     56
    5557    // 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                
     58    function SetShadow($aColor="black",$aHSize=3,$aVSize=3,$aShow=true) {
     59        $this->bar_shadow=$aShow;
     60        $this->bar_shadow_color=$aColor;
     61        $this->bar_shadow_vsize=$aVSize;
     62        $this->bar_shadow_hsize=$aHSize;
     63
     64        // Adjust the value margin to compensate for shadow
     65        $this->value->margin += $aVSize;
     66    }
     67
     68    function Set3D($aHSize=3,$aVSize=3,$aShow=true) {
     69        $this->bar_3d=$aShow;
     70        $this->bar_3d_vsize=$aVSize;
     71        $this->bar_3d_hsize=$aHSize;
     72
     73        $this->value->margin += $aVSize;
     74    }
     75
    6676    // DEPRECATED use SetYBase instead
    6777    function SetYMin($aYStartValue) {
    68         //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead.");           
    69         $this->ybase=$aYStartValue;
     78        //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead.");
     79        $this->ybase=$aYStartValue;
    7080    }
    7181
    7282    // Specify the base value for the bars
    7383    function SetYBase($aYStartValue) {
    74         $this->ybase=$aYStartValue;
    75     }
    76        
     84        $this->ybase=$aYStartValue;
     85    }
     86
     87    // The method will take the specified pattern anre
     88    // return a pattern index that corresponds to the original
     89    // patterm being rotated 90 degreees. This is needed when plottin
     90    // Horizontal bars
     91    function RotatePattern($aPat,$aRotate=true) {
     92        $rotate = array(1 => 2, 2 => 1, 3 => 3, 4 => 5, 5 => 4, 6 => 6, 7 => 7, 8 => 8);
     93        if( $aRotate ) {
     94            return $rotate[$aPat];
     95        }
     96        else {
     97            return $aPat;
     98        }
     99    }
     100
    77101    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,$this->legendcsimwintarget);
    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,$this->legendcsimwintarget);
    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,$this->legendcsimwintarget);
    104             }
    105             else {
    106                 $graph->legend->Add($this->legend,$this->fill_color,"",0,
    107                                     $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);   
    108             }
    109         }
     102        if( $this->grad && $this->legend!="" && !$this->fill ) {
     103            $color=array($this->grad_fromcolor,$this->grad_tocolor);
     104            // In order to differentiate between gradients and cooors specified as an RGB triple
     105            $graph->legend->Add($this->legend,$color,"",-$this->grad_style,
     106            $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
     107        }
     108        elseif( $this->legend!="" && ($this->iPattern > -1 || is_array($this->iPattern)) ) {
     109            if( is_array($this->iPattern) ) {
     110                $p1 = $this->RotatePattern( $this->iPattern[0], $graph->img->a == 90 );
     111                $p2 = $this->iPatternColor[0];
     112                $p3 = $this->iPatternDensity[0];
     113            }
     114            else {
     115                $p1 = $this->RotatePattern( $this->iPattern, $graph->img->a == 90 );
     116                $p2 = $this->iPatternColor;
     117                $p3 = $this->iPatternDensity;
     118            }
     119            if( $p3 < 90 ) $p3 += 5;
     120            $color = array($p1,$p2,$p3,$this->fill_color);
     121            // A kludge: Too mark that we add a pattern we use a type value of < 100
     122            $graph->legend->Add($this->legend,$color,"",-101,
     123                                $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
     124        }
     125        elseif( $this->fill_color && $this->legend!="" ) {
     126            if( is_array($this->fill_color) ) {
     127                $graph->legend->Add($this->legend,$this->fill_color[0],"",0,
     128                $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
     129            }
     130            else {
     131                $graph->legend->Add($this->legend,$this->fill_color,"",0,
     132                $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
     133            }
     134        }
    110135    }
    111136
    112137    // Gets called before any axis are stroked
    113138    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         elseif( ($this instanceof AccBarPlot) || ($this instanceof GroupBarPlot) ) {
    140             // We only set an absolute width for linear and int scale
    141             // for text scale the width will be set to a fraction of
    142             // the majstep width.
    143             if( $this->abswidth == -1 ) {
     139        parent::PreStrokeAdjust($graph);
     140
     141        // If we are using a log Y-scale we want the base to be at the
     142        // minimum Y-value unless the user have specifically set some other
     143        // value than the default.
     144        if( substr($graph->axtype,-3,3)=="log" && $this->ybase==0 )
     145        $this->ybase = $graph->yaxis->scale->GetMinVal();
     146
     147        // For a "text" X-axis scale we will adjust the
     148        // display of the bars a little bit.
     149        if( substr($graph->axtype,0,3)=="tex" ) {
     150            // Position the ticks between the bars
     151            $graph->xaxis->scale->ticks->SetXLabelOffset(0.5,0);
     152
     153            // Center the bars
     154            if( $this->abswidth > -1 ) {
     155                $graph->SetTextScaleAbsCenterOff($this->abswidth);
     156            }
     157            else {
     158                if( $this->align == "center" )
     159                $graph->SetTextScaleOff(0.5-$this->width/2);
     160                elseif( $this->align == "right" )
     161                $graph->SetTextScaleOff(1-$this->width);
     162            }
     163        }
     164        elseif( ($this instanceof AccBarPlot) || ($this instanceof GroupBarPlot) ) {
     165            // We only set an absolute width for linear and int scale
     166            // for text scale the width will be set to a fraction of
     167            // the majstep width.
     168            if( $this->abswidth == -1 ) {
    144169                // Not set
    145                 // set width to a visuable sensible default
    146                 $this->abswidth = $graph->img->plotwidth/(2*$this->numpoints);
    147             }
    148         }
     170                // set width to a visuable sensible default
     171                $this->abswidth = $graph->img->plotwidth/(2*$this->numpoints);
     172            }
     173        }
    149174    }
    150175
    151176    function Min() {
    152         $m = parent::Min();
    153         if( $m[1] >= $this->ybase )
    154             $m[1] = $this->ybase;
    155         return $m;     
     177        $m = parent::Min();
     178        if( $m[1] >= $this->ybase ) $m[1] = $this->ybase;
     179        return $m;
    156180    }
    157181
    158182    function Max() {
    159         $m = parent::Max();
    160         if( $m[1] <= $this->ybase )
    161             $m[1] = $this->ybase;
    162         return $m;     
    163     }   
    164        
     183        $m = parent::Max();
     184        if( $m[1] <= $this->ybase ) $m[1] = $this->ybase;
     185        return $m;
     186    }
     187
    165188    // Specify width as fractions of the major stepo size
    166189    function SetWidth($aWidth) {
    167         if( $aWidth > 1 ) {
    168             // Interpret this as absolute width
    169             $this->abswidth=$aWidth;
    170         }
    171         else
    172             $this->width=$aWidth;
    173     }
    174        
     190        if( $aWidth > 1 ) {
     191            // Interpret this as absolute width
     192            $this->abswidth=$aWidth;
     193        }
     194        else {
     195            $this->width=$aWidth;
     196        }
     197    }
     198
    175199    // Specify width in absolute pixels. If specified this
    176200    // overrides SetWidth()
    177201    function SetAbsWidth($aWidth) {
    178         $this->abswidth=$aWidth;
    179     }
    180                
     202        $this->abswidth=$aWidth;
     203    }
     204
    181205    function SetAlign($aAlign) {
    182         $this->align=$aAlign;
    183     }
    184        
     206        $this->align=$aAlign;
     207    }
     208
    185209    function SetNoFill() {
    186         $this->grad = false;
    187         $this->fill_color=false;
    188         $this->fill=false;
    189     }
    190                
     210        $this->grad = false;
     211        $this->fill_color=false;
     212        $this->fill=false;
     213    }
     214
    191215    function SetFillColor($aColor) {
    192         $this->fill = true ;
    193         $this->fill_color=$aColor;
    194     }
    195        
     216        // Do an extra error check if the color is specified as an RGB array triple
     217        // In that case convert it to a hex string since it will otherwise be
     218        // interpretated as an array of colors for each individual bar.
     219
     220        $aColor = RGB::tryHexConversion($aColor);
     221        $this->fill = true ;
     222        $this->fill_color=$aColor;
     223
     224    }
     225
    196226    function SetFillGradient($aFromColor,$aToColor=null,$aStyle=null) {
    197         $this->grad = true;
    198         $this->grad_fromcolor = $aFromColor;
    199         $this->grad_tocolor   = $aToColor;
    200         $this->grad_style     = $aStyle;
    201     }
    202        
     227        $this->grad = true;
     228        $this->grad_fromcolor = $aFromColor;
     229        $this->grad_tocolor   = $aToColor;
     230        $this->grad_style     = $aStyle;
     231    }
     232
    203233    function SetValuePos($aPos) {
    204         $this->valuepos = $aPos;
     234        $this->valuepos = $aPos;
    205235    }
    206236
    207237    function SetPattern($aPattern, $aColor='black'){
    208         if( is_array($aPattern) ) {
    209             $n = count($aPattern);
    210             $this->iPattern = array();
    211             $this->iPatternDensity = array();
    212             if( is_array($aColor) ) {
    213                 $this->iPatternColor = array();
    214                 if( count($aColor) != $n ) {
    215                     JpGraphError::RaiseL(2001);//('NUmber of colors is not the same as the number of patterns in BarPlot::SetPattern()');
    216                 }
    217             }
    218             else
    219                 $this->iPatternColor = $aColor;
    220             for( $i=0; $i < $n; ++$i ) {
    221                 $this->_SetPatternHelper($aPattern[$i], $this->iPattern[$i], $this->iPatternDensity[$i]);
    222                 if( is_array($aColor) ) {
    223                     $this->iPatternColor[$i] = $aColor[$i];
    224                 }
    225             }
    226         }
    227         else {
    228             $this->_SetPatternHelper($aPattern, $this->iPattern, $this->iPatternDensity);
    229             $this->iPatternColor = $aColor;
    230         }
     238        if( is_array($aPattern) ) {
     239            $n = count($aPattern);
     240            $this->iPattern = array();
     241            $this->iPatternDensity = array();
     242            if( is_array($aColor) ) {
     243                $this->iPatternColor = array();
     244                if( count($aColor) != $n ) {
     245                    JpGraphError::RaiseL(2001);//('NUmber of colors is not the same as the number of patterns in BarPlot::SetPattern()');
     246                }
     247            }
     248            else {
     249                $this->iPatternColor = $aColor;
     250            }
     251            for( $i=0; $i < $n; ++$i ) {
     252                $this->_SetPatternHelper($aPattern[$i], $this->iPattern[$i], $this->iPatternDensity[$i]);
     253                if( is_array($aColor) ) {
     254                    $this->iPatternColor[$i] = $aColor[$i];
     255                }
     256            }
     257        }
     258        else {
     259            $this->_SetPatternHelper($aPattern, $this->iPattern, $this->iPatternDensity);
     260            $this->iPatternColor = $aColor;
     261        }
    231262    }
    232263
    233264    function _SetPatternHelper($aPattern, &$aPatternValue, &$aDensity){
    234         switch( $aPattern ) {
    235             case PATTERN_DIAG1:
    236                 $aPatternValue= 1;
    237                 $aDensity = 90;
    238                 break;
    239             case PATTERN_DIAG2:
    240                 $aPatternValue= 1;
    241                 $aDensity = 75;
    242                 break;
    243             case PATTERN_DIAG3:
    244                 $aPatternValue= 2;
    245                 $aDensity = 90;
    246                 break;
    247             case PATTERN_DIAG4:
    248                 $aPatternValue= 2;
    249                 $aDensity = 75;
    250                 break;
    251             case PATTERN_CROSS1:
    252                 $aPatternValue= 8;
    253                 $aDensity = 90;
    254                 break;
    255             case PATTERN_CROSS2:
    256                 $aPatternValue= 8;
    257                 $aDensity = 78;
    258                 break;
    259             case PATTERN_CROSS3:
    260                 $aPatternValue= 8;
    261                 $aDensity = 65;
    262                 break;
    263             case PATTERN_CROSS4:
    264                 $aPatternValue= 7;
    265                 $aDensity = 90;
    266                 break;
    267             case PATTERN_STRIPE1:
    268                 $aPatternValue= 5;
    269                 $aDensity = 90;
    270                 break;
    271             case PATTERN_STRIPE2:
    272                 $aPatternValue= 5;
    273                 $aDensity = 75;
    274                 break;
    275             default:
    276                 JpGraphError::RaiseL(2002);
    277 //('Unknown pattern specified in call to BarPlot::SetPattern()');
    278         }
    279     }
    280 
    281     function Stroke($img,$xscale,$yscale) {
    282                
    283         $numpoints = count($this->coords[0]);
    284         if( isset($this->coords[1]) ) {
    285             if( count($this->coords[1])!=$numpoints )
    286                 JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints);
    287 //"Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])."Number of Y-points:$numpoints");
    288             else
    289                 $exist_x = true;
    290         }
    291         else
    292             $exist_x = false;
    293                
    294                
    295         $numbars=count($this->coords[0]);
    296 
    297         // Use GetMinVal() instead of scale[0] directly since in the case
    298         // of log scale we get a correct value. Log scales will have negative
    299         // values for values < 1 while still not representing negative numbers.
    300         if( $yscale->GetMinVal() >= 0 )
    301             $zp=$yscale->scale_abs[0];
    302         else {
    303             $zp=$yscale->Translate(0);
    304         }
    305 
    306         if( $this->abswidth > -1 ) {
    307             $abswidth=$this->abswidth;
    308         }
    309         else
    310             $abswidth=round($this->width*$xscale->scale_factor,0);
    311 
    312         // Count pontetial pattern array to avoid doing the count for each iteration
    313         if( is_array($this->iPattern) ) {
    314             $np = count($this->iPattern);
    315         }
    316                        
    317         $grad = null;
    318         for($i=0; $i < $numbars; ++$i) {
    319 
    320             // If value is NULL, or 0 then don't draw a bar at all
    321             if ($this->coords[0][$i] === null || $this->coords[0][$i] === '' )
    322                 continue;   
    323 
    324             if( $exist_x ) $x=$this->coords[1][$i];
    325             else $x=$i;
    326                        
    327             $x=$xscale->Translate($x);
    328 
    329 // Comment Note: This confuses the positioning when using acc together with
    330 // grouped bars. Workaround for fixing #191
    331 /*
    332             if( !$xscale->textscale ) {
    333                 if($this->align=="center")
    334                     $x -= $abswidth/2;
    335                 elseif($this->align=="right")
    336                     $x -= $abswidth;                   
    337             }
    338 */
    339             // Stroke fill color and fill gradient
    340             $pts=array(
    341                 $x,$zp,
    342                 $x,$yscale->Translate($this->coords[0][$i]),
    343                 $x+$abswidth,$yscale->Translate($this->coords[0][$i]),
    344                 $x+$abswidth,$zp);
    345             if( $this->grad ) {
    346                 if( $grad === null )
    347                     $grad = new Gradient($img);
    348                 if( is_array($this->grad_fromcolor) ) {
    349                     // The first argument (grad_fromcolor) can be either an array or a single color. If it is an array
    350                     // then we have two choices. It can either a) be a single color specified as an RGB triple or it can be
    351                     // an array to specify both (from, to style) for each individual bar. The way to know the difference is
    352                     // to investgate the first element. If this element is an integer [0,255] then we assume it is an RGB
    353                     // triple.
    354                     $ng = count($this->grad_fromcolor);
    355                     if( $ng === 3 ) {
    356                         if( is_numeric($this->grad_fromcolor[0]) && $this->grad_fromcolor[0] > 0 && $this->grad_fromcolor[0] < 256 ) {
    357                             // RGB Triple
    358                             $fromcolor = $this->grad_fromcolor;
    359                             $tocolor = $this->grad_tocolor;
    360                             $style = $this->grad_style;
    361                         }
    362                     }
    363                     else {
    364                         $fromcolor = $this->grad_fromcolor[$i % $ng][0];
    365                         $tocolor = $this->grad_fromcolor[$i % $ng][1];
    366                         $style = $this->grad_fromcolor[$i % $ng][2];
    367                     }
    368                     $grad->FilledRectangle($pts[2],$pts[3],
    369                                            $pts[6],$pts[7],
    370                                            $fromcolor,$tocolor,$style);
    371                 }
    372                 else {
    373                     $grad->FilledRectangle($pts[2],$pts[3],
    374                                            $pts[6],$pts[7],
    375                                            $this->grad_fromcolor,$this->grad_tocolor,$this->grad_style);
    376                 }
    377             }
    378             elseif( !empty($this->fill_color) ) {
    379                 if(is_array($this->fill_color)) {
    380                     $img->PushColor($this->fill_color[$i % count($this->fill_color)]);
    381                 } else {
    382                     $img->PushColor($this->fill_color);
    383                 }
    384                 $img->FilledPolygon($pts);
    385                 $img->PopColor();
    386             }
    387  
    388                        
    389             // Remember value of this bar
    390             $val=$this->coords[0][$i];
    391 
    392             if( !empty($val) && !is_numeric($val) ) {
    393                 JpGraphError::RaiseL(2004,$i,$val);
    394                 //'All values for a barplot must be numeric. You have specified value['.$i.'] == \''.$val.'\'');
    395             }
    396 
    397             // Determine the shadow
    398             if( $this->bar_shadow && $val != 0) {
    399 
    400                 $ssh = $this->bar_shadow_hsize;
    401                 $ssv = $this->bar_shadow_vsize;
    402                 // Create points to create a "upper-right" shadow
    403                 if( $val > 0 ) {
    404                     $sp[0]=$pts[6];             $sp[1]=$pts[7];
    405                     $sp[2]=$pts[4];             $sp[3]=$pts[5];
    406                     $sp[4]=$pts[2];             $sp[5]=$pts[3];
    407                     $sp[6]=$pts[2]+$ssh;        $sp[7]=$pts[3]-$ssv;
    408                     $sp[8]=$pts[4]+$ssh;        $sp[9]=$pts[5]-$ssv;
    409                     $sp[10]=$pts[6]+$ssh;       $sp[11]=$pts[7]-$ssv;
    410                 }
    411                 elseif( $val < 0 ) {
    412                     $sp[0]=$pts[4];             $sp[1]=$pts[5];
    413                     $sp[2]=$pts[6];             $sp[3]=$pts[7];
    414                     $sp[4]=$pts[0];             $sp[5]=$pts[1];
    415                     $sp[6]=$pts[0]+$ssh;        $sp[7]=$pts[1]-$ssv;
    416                     $sp[8]=$pts[6]+$ssh;        $sp[9]=$pts[7]-$ssv;
    417                     $sp[10]=$pts[4]+$ssh;       $sp[11]=$pts[5]-$ssv;
    418                 }
    419                 if( is_array($this->bar_shadow_color) ) {
    420                     $numcolors = count($this->bar_shadow_color);
    421                     if( $numcolors == 0 ) {
    422                         JpGraphError::RaiseL(2005);//('You have specified an empty array for shadow colors in the bar plot.');
    423                     }
    424                     $img->PushColor($this->bar_shadow_color[$i % $numcolors]);
    425                 }
    426                 else {
    427                     $img->PushColor($this->bar_shadow_color);
    428                 }
    429                 $img->FilledPolygon($sp);
    430                 $img->PopColor();
    431             }
    432                        
    433             // Stroke the pattern
    434             if( is_array($this->iPattern) ) {
    435                 $f = new RectPatternFactory();
    436                 if( is_array($this->iPatternColor) ) {
    437                     $pcolor = $this->iPatternColor[$i % $np];
    438                 }
    439                 else
    440                     $pcolor = $this->iPatternColor;
    441                 $prect = $f->Create($this->iPattern[$i % $np],$pcolor,1);
    442                 $prect->SetDensity($this->iPatternDensity[$i % $np]);
    443 
    444                 if( $val < 0 ) {
    445                     $rx = $pts[0];
    446                     $ry = $pts[1];
    447                 }
    448                 else {
    449                     $rx = $pts[2];
    450                     $ry = $pts[3];
    451                 }
    452                 $width = abs($pts[4]-$pts[0])+1;
    453                 $height = abs($pts[1]-$pts[3])+1;
    454                 $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
    455                 $prect->Stroke($img);
    456             }
    457             else {
    458                 if( $this->iPattern > -1 ) {
    459                     $f = new RectPatternFactory();
    460                     $prect = $f->Create($this->iPattern,$this->iPatternColor,1);
    461                     $prect->SetDensity($this->iPatternDensity);
    462                     if( $val < 0 ) {
    463                         $rx = $pts[0];
    464                         $ry = $pts[1];
    465                     }
    466                     else {
    467                         $rx = $pts[2];
    468                         $ry = $pts[3];
    469                     }
    470                     $width = abs($pts[4]-$pts[0])+1;
    471                     $height = abs($pts[1]-$pts[3])+1;
    472                     $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
    473                     $prect->Stroke($img);
    474                 }
    475             }
    476             // Stroke the outline of the bar
    477             if( is_array($this->color) )
    478                 $img->SetColor($this->color[$i % count($this->color)]);
    479             else
    480                 $img->SetColor($this->color);
    481 
    482             $pts[] = $pts[0];
    483             $pts[] = $pts[1];
    484 
    485             if( $this->weight > 0 ) {
    486                 $img->SetLineWeight($this->weight);
    487                 $img->Polygon($pts);
    488             }
    489                        
    490             // Determine how to best position the values of the individual bars
    491             $x=$pts[2]+($pts[4]-$pts[2])/2;
    492             $this->value->SetMargin(5);
    493 
    494             if( $this->valuepos=='top' ) {
    495                 $y=$pts[3];
    496                 if( $img->a === 90 ) {
    497                     if( $val < 0 )
    498                         $this->value->SetAlign('right','center');                       
    499                     else
    500                         $this->value->SetAlign('left','center');
    501                        
    502                 }
    503                 else {
    504                     if( $val < 0 ) {
    505                         $this->value->SetMargin(-5);
    506                         $y=$pts[1];
    507                         $this->value->SetAlign('center','bottom');
    508                     }
    509                     else {
    510                         $this->value->SetAlign('center','bottom');                     
    511                     }
    512 
    513                 }
    514                 $this->value->Stroke($img,$val,$x,$y);
    515             }
    516             elseif( $this->valuepos=='max' ) {
    517                 $y=$pts[3];
    518                 if( $img->a === 90 ) {
    519                     if( $val < 0 )
    520                         $this->value->SetAlign('left','center');
    521                     else
    522                         $this->value->SetAlign('right','center');                   
    523                 }
    524                 else {
    525                     if( $val < 0 ) {
    526                         $this->value->SetAlign('center','bottom');
    527                     }
    528                     else {
    529                         $this->value->SetAlign('center','top');
    530                     }
    531                 }
    532                 $this->value->SetMargin(-5);
    533                 $this->value->Stroke($img,$val,$x,$y);
    534             }
    535             elseif( $this->valuepos=='center' ) {
    536                 $y = ($pts[3] + $pts[1])/2;
    537                 $this->value->SetAlign('center','center');
    538                 $this->value->SetMargin(0);
    539                 $this->value->Stroke($img,$val,$x,$y);
    540             }
    541             elseif( $this->valuepos=='bottom' || $this->valuepos=='min' ) {
    542                 $y=$pts[1];
    543                 if( $img->a === 90 ) {
    544                     if( $val < 0 )
    545                         $this->value->SetAlign('right','center');
    546                     else
    547                         $this->value->SetAlign('left','center');                                   
    548                 }
    549                 $this->value->SetMargin(3);
    550                 $this->value->Stroke($img,$val,$x,$y);
    551             }
    552             else {
    553                 JpGraphError::RaiseL(2006,$this->valuepos);
    554                 //'Unknown position for values on bars :'.$this->valuepos);
    555             }
    556             // Create the client side image map
    557             $rpts = $img->ArrRotate($pts);             
    558             $csimcoord=round($rpts[0]).", ".round($rpts[1]);
    559             for( $j=1; $j < 4; ++$j){
    560                 $csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]);
    561             }               
    562             if( !empty($this->csimtargets[$i]) ) {
    563                 $this->csimareas .= '<area shape="poly" coords="'.$csimcoord.'" ';         
    564                 $this->csimareas .= " href=\"".htmlentities($this->csimtargets[$i])."\"";
    565 
    566                 if( !empty($this->csimwintargets[$i]) ) {
    567                     $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
    568                 }
    569 
    570                 $sval='';
    571                 if( !empty($this->csimalts[$i]) ) {
    572                     $sval=sprintf($this->csimalts[$i],$this->coords[0][$i]);
    573                     $this->csimareas .= " title=\"$sval\" alt=\"$sval\" ";
    574                 }
    575                 $this->csimareas .= " />\n";
    576             }
    577         }
    578         return true;
     265        switch( $aPattern ) {
     266            case PATTERN_DIAG1:
     267                $aPatternValue= 1;
     268                $aDensity = 92;
     269                break;
     270            case PATTERN_DIAG2:
     271                $aPatternValue= 1;
     272                $aDensity = 78;
     273                break;
     274            case PATTERN_DIAG3:
     275                $aPatternValue= 2;
     276                $aDensity = 92;
     277                break;
     278            case PATTERN_DIAG4:
     279                $aPatternValue= 2;
     280                $aDensity = 78;
     281                break;
     282            case PATTERN_CROSS1:
     283                $aPatternValue= 8;
     284                $aDensity = 90;
     285                break;
     286            case PATTERN_CROSS2:
     287                $aPatternValue= 8;
     288                $aDensity = 78;
     289                break;
     290            case PATTERN_CROSS3:
     291                $aPatternValue= 8;
     292                $aDensity = 65;
     293                break;
     294            case PATTERN_CROSS4:
     295                $aPatternValue= 7;
     296                $aDensity = 90;
     297                break;
     298            case PATTERN_STRIPE1:
     299                $aPatternValue= 5;
     300                $aDensity = 94;
     301                break;
     302            case PATTERN_STRIPE2:
     303                $aPatternValue= 5;
     304                $aDensity = 85;
     305                break;
     306            default:
     307                JpGraphError::RaiseL(2002);
     308                //('Unknown pattern specified in call to BarPlot::SetPattern()');
     309        }
     310    }
     311
     312    function Stroke($img,$xscale,$yscale) {
     313
     314        $numpoints = count($this->coords[0]);
     315        if( isset($this->coords[1]) ) {
     316            if( count($this->coords[1])!=$numpoints ) {
     317                JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints);
     318            //"Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])."Number of Y-points:$numpoints");
     319            }
     320            else {
     321                $exist_x = true;
     322            }
     323        }
     324        else {
     325            $exist_x = false;
     326        }
     327
     328
     329        $numbars=count($this->coords[0]);
     330
     331        // Use GetMinVal() instead of scale[0] directly since in the case
     332        // of log scale we get a correct value. Log scales will have negative
     333        // values for values < 1 while still not representing negative numbers.
     334        if( $yscale->GetMinVal() >= 0 )
     335        $zp=$yscale->scale_abs[0];
     336        else {
     337            $zp=$yscale->Translate(0);
     338        }
     339
     340        if( $this->abswidth > -1 ) {
     341            $abswidth=$this->abswidth;
     342        }
     343        else {
     344            $abswidth=round($this->width*$xscale->scale_factor,0);
     345        }
     346
     347        // Count pontetial pattern array to avoid doing the count for each iteration
     348        if( is_array($this->iPattern) ) {
     349            $np = count($this->iPattern);
     350        }
     351
     352        $grad = null;
     353        for($i=0; $i < $numbars; ++$i) {
     354
     355            // If value is NULL, or 0 then don't draw a bar at all
     356            if ($this->coords[0][$i] === null || $this->coords[0][$i] === '' )
     357            continue;
     358
     359            if( $exist_x ) {
     360                $x=$this->coords[1][$i];
     361            }
     362            else {
     363                $x=$i;
     364            }
     365
     366            $x=$xscale->Translate($x);
     367
     368            // Comment Note: This confuses the positioning when using acc together with
     369            // grouped bars. Workaround for fixing #191
     370            /*
     371            if( !$xscale->textscale ) {
     372            if($this->align=="center")
     373            $x -= $abswidth/2;
     374            elseif($this->align=="right")
     375            $x -= $abswidth;
     376            }
     377            */
     378            // Stroke fill color and fill gradient
     379            $pts=array(
     380            $x,$zp,
     381            $x,$yscale->Translate($this->coords[0][$i]),
     382            $x+$abswidth,$yscale->Translate($this->coords[0][$i]),
     383            $x+$abswidth,$zp);
     384            if( $this->grad ) {
     385                if( $grad === null ) {
     386                    $grad = new Gradient($img);
     387                }
     388                if( is_array($this->grad_fromcolor) ) {
     389                    // The first argument (grad_fromcolor) can be either an array or a single color. If it is an array
     390                    // then we have two choices. It can either a) be a single color specified as an RGB triple or it can be
     391                    // an array to specify both (from, to style) for each individual bar. The way to know the difference is
     392                    // to investgate the first element. If this element is an integer [0,255] then we assume it is an RGB
     393                    // triple.
     394                    $ng = count($this->grad_fromcolor);
     395                    if( $ng === 3 ) {
     396                        if( is_numeric($this->grad_fromcolor[0]) && $this->grad_fromcolor[0] > 0 && $this->grad_fromcolor[0] < 256 ) {
     397                            // RGB Triple
     398                            $fromcolor = $this->grad_fromcolor;
     399                            $tocolor = $this->grad_tocolor;
     400                            $style = $this->grad_style;
     401                        }
     402                        else {
     403                            $fromcolor = $this->grad_fromcolor[$i % $ng][0];
     404                            $tocolor = $this->grad_fromcolor[$i % $ng][1];
     405                            $style = $this->grad_fromcolor[$i % $ng][2];
     406                        }
     407                    }
     408                    else {
     409                        $fromcolor = $this->grad_fromcolor[$i % $ng][0];
     410                        $tocolor = $this->grad_fromcolor[$i % $ng][1];
     411                        $style = $this->grad_fromcolor[$i % $ng][2];
     412                    }
     413                    $grad->FilledRectangle($pts[2],$pts[3],
     414                                           $pts[6],$pts[7],
     415                                           $fromcolor,$tocolor,$style);
     416                }
     417                else {
     418                    $grad->FilledRectangle($pts[2],$pts[3],
     419                    $pts[6],$pts[7],
     420                    $this->grad_fromcolor,$this->grad_tocolor,$this->grad_style);
     421                }
     422            }
     423            elseif( !empty($this->fill_color) ) {
     424                if(is_array($this->fill_color)) {
     425                    $img->PushColor($this->fill_color[$i % count($this->fill_color)]);
     426                } else {
     427                    $img->PushColor($this->fill_color);
     428                }
     429                $img->FilledPolygon($pts);
     430                $img->PopColor();
     431            }
     432
     433/////////////////////////kokorahen rectangle polygon//////////////////////
     434
     435            // Remember value of this bar
     436            $val=$this->coords[0][$i];
     437
     438            if( !empty($val) && !is_numeric($val) ) {
     439                JpGraphError::RaiseL(2004,$i,$val);
     440                //'All values for a barplot must be numeric. You have specified value['.$i.'] == \''.$val.'\'');
     441            }
     442
     443            // Determine the shadow
     444            if( $this->bar_shadow && $val != 0) {
     445
     446                $ssh = $this->bar_shadow_hsize;
     447                $ssv = $this->bar_shadow_vsize;
     448                // Create points to create a "upper-right" shadow
     449                if( $val > 0 ) {
     450                    $sp[0]=$pts[6];  $sp[1]=$pts[7];
     451                    $sp[2]=$pts[4];  $sp[3]=$pts[5];
     452                    $sp[4]=$pts[2];  $sp[5]=$pts[3];
     453                    $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv;
     454                    $sp[8]=$pts[4]+$ssh; $sp[9]=$pts[5]-$ssv;
     455                    $sp[10]=$pts[6]+$ssh; $sp[11]=$pts[7]-$ssv;
     456                }
     457                elseif( $val < 0 ) {
     458                    $sp[0]=$pts[4];  $sp[1]=$pts[5];
     459                    $sp[2]=$pts[6];  $sp[3]=$pts[7];
     460                    $sp[4]=$pts[0];  $sp[5]=$pts[1];
     461                    $sp[6]=$pts[0]+$ssh; $sp[7]=$pts[1]-$ssv;
     462                    $sp[8]=$pts[6]+$ssh; $sp[9]=$pts[7]-$ssv;
     463                    $sp[10]=$pts[4]+$ssh; $sp[11]=$pts[5]-$ssv;
     464                }
     465                if( is_array($this->bar_shadow_color) ) {
     466                    $numcolors = count($this->bar_shadow_color);
     467                    if( $numcolors == 0 ) {
     468                        JpGraphError::RaiseL(2005);//('You have specified an empty array for shadow colors in the bar plot.');
     469                    }
     470                    $img->PushColor($this->bar_shadow_color[$i % $numcolors]);
     471                }
     472                else {
     473                    $img->PushColor($this->bar_shadow_color);
     474                }
     475                $img->FilledPolygon($sp);
     476                $img->PopColor();
     477
     478            } elseif( $this->bar_3d && $val != 0) {
     479              // Determine the 3D
     480
     481                $ssh = $this->bar_3d_hsize;
     482                $ssv = $this->bar_3d_vsize;
     483
     484                // Create points to create a "upper-right" shadow
     485                if( $val > 0 ) {
     486                    $sp1[0]=$pts[6];  $sp1[1]=$pts[7];
     487                    $sp1[2]=$pts[4];  $sp1[3]=$pts[5];
     488                    $sp1[4]=$pts[4]+$ssh; $sp1[5]=$pts[5]-$ssv;
     489                    $sp1[6]=$pts[6]+$ssh; $sp1[7]=$pts[7]-$ssv;
     490
     491                    $sp2[0]=$pts[4];  $sp2[1]=$pts[5];
     492                    $sp2[2]=$pts[2];  $sp2[3]=$pts[3];
     493                    $sp2[4]=$pts[2]+$ssh; $sp2[5]=$pts[3]-$ssv;
     494                    $sp2[6]=$pts[4]+$ssh; $sp2[7]=$pts[5]-$ssv;
     495
     496                }
     497                elseif( $val < 0 ) {
     498                    $sp1[0]=$pts[4];  $sp1[1]=$pts[5];
     499                    $sp1[2]=$pts[6];  $sp1[3]=$pts[7];
     500                    $sp1[4]=$pts[6]+$ssh; $sp1[5]=$pts[7]-$ssv;
     501                    $sp1[6]=$pts[4]+$ssh; $sp1[7]=$pts[5]-$ssv;
     502
     503                    $sp2[0]=$pts[6];  $sp2[1]=$pts[7];
     504                    $sp2[2]=$pts[0];  $sp2[3]=$pts[1];
     505                    $sp2[4]=$pts[0]+$ssh; $sp2[5]=$pts[1]-$ssv;
     506                    $sp2[6]=$pts[6]+$ssh; $sp2[7]=$pts[7]-$ssv;
     507                }
     508
     509                $base_color = $this->fill_color;
     510
     511                $img->PushColor($base_color . ':0.7');
     512                $img->FilledPolygon($sp1);
     513                $img->PopColor();
     514
     515                $img->PushColor($base_color . ':1.1');
     516                $img->FilledPolygon($sp2);
     517                $img->PopColor();
     518            }
     519
     520            // Stroke the pattern
     521            if( is_array($this->iPattern) ) {
     522                $f = new RectPatternFactory();
     523                if( is_array($this->iPatternColor) ) {
     524                    $pcolor = $this->iPatternColor[$i % $np];
     525                }
     526                else {
     527                    $pcolor = $this->iPatternColor;
     528                }
     529                $prect = $f->Create($this->iPattern[$i % $np],$pcolor,1);
     530                $prect->SetDensity($this->iPatternDensity[$i % $np]);
     531
     532                if( $val < 0 ) {
     533                    $rx = $pts[0];
     534                    $ry = $pts[1];
     535                }
     536                else {
     537                    $rx = $pts[2];
     538                    $ry = $pts[3];
     539                }
     540                $width = abs($pts[4]-$pts[0])+1;
     541                $height = abs($pts[1]-$pts[3])+1;
     542                $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
     543                $prect->Stroke($img);
     544            }
     545            else {
     546                if( $this->iPattern > -1 ) {
     547                    $f = new RectPatternFactory();
     548                    $prect = $f->Create($this->iPattern,$this->iPatternColor,1);
     549                    $prect->SetDensity($this->iPatternDensity);
     550                    if( $val < 0 ) {
     551                        $rx = $pts[0];
     552                        $ry = $pts[1];
     553                    }
     554                    else {
     555                        $rx = $pts[2];
     556                        $ry = $pts[3];
     557                    }
     558                    $width = abs($pts[4]-$pts[0])+1;
     559                    $height = abs($pts[1]-$pts[3])+1;
     560                    $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
     561                    $prect->Stroke($img);
     562                }
     563            }
     564
     565            // Stroke the outline of the bar
     566            if( is_array($this->color) ) {
     567                $img->SetColor($this->color[$i % count($this->color)]);
     568            }
     569            else {
     570                $img->SetColor($this->color);
     571            }
     572
     573            $pts[] = $pts[0];
     574            $pts[] = $pts[1];
     575
     576            if( $this->weight > 0 ) {
     577                $img->SetLineWeight($this->weight);
     578                $img->Polygon($pts);
     579            }
     580
     581            // Determine how to best position the values of the individual bars
     582            $x=$pts[2]+($pts[4]-$pts[2])/2;
     583            $this->value->SetMargin(5);
     584
     585            if( $this->valuepos=='top' ) {
     586                $y=$pts[3];
     587                if( $img->a === 90 ) {
     588                    if( $val < 0 ) {
     589                        $this->value->SetAlign('right','center');
     590                    }
     591                    else {
     592                        $this->value->SetAlign('left','center');
     593                    }
     594
     595                }
     596                else {
     597                    if( $val < 0 ) {
     598                        $this->value->SetMargin(-5);
     599                        $y=$pts[1];
     600                        $this->value->SetAlign('center','bottom');
     601                    }
     602                    else {
     603                        $this->value->SetAlign('center','bottom');
     604                    }
     605
     606                }
     607                $this->value->Stroke($img,$val,$x,$y);
     608            }
     609            elseif( $this->valuepos=='max' ) {
     610                $y=$pts[3];
     611                if( $img->a === 90 ) {
     612                    if( $val < 0 )
     613                    $this->value->SetAlign('left','center');
     614                    else
     615                    $this->value->SetAlign('right','center');
     616                }
     617                else {
     618                    if( $val < 0 ) {
     619                        $this->value->SetAlign('center','bottom');
     620                    }
     621                    else {
     622                        $this->value->SetAlign('center','top');
     623                    }
     624                }
     625                $this->value->SetMargin(-5);
     626                $this->value->Stroke($img,$val,$x,$y);
     627            }
     628            elseif( $this->valuepos=='center' ) {
     629                $y = ($pts[3] + $pts[1])/2;
     630                $this->value->SetAlign('center','center');
     631                $this->value->SetMargin(0);
     632                $this->value->Stroke($img,$val,$x,$y);
     633            }
     634            elseif( $this->valuepos=='bottom' || $this->valuepos=='min' ) {
     635                $y=$pts[1];
     636                if( $img->a === 90 ) {
     637                    if( $val < 0 )
     638                    $this->value->SetAlign('right','center');
     639                    else
     640                    $this->value->SetAlign('left','center');
     641                }
     642                $this->value->SetMargin(3);
     643                $this->value->Stroke($img,$val,$x,$y);
     644            }
     645            else {
     646                JpGraphError::RaiseL(2006,$this->valuepos);
     647                //'Unknown position for values on bars :'.$this->valuepos);
     648            }
     649            // Create the client side image map
     650            $rpts = $img->ArrRotate($pts);
     651            $csimcoord=round($rpts[0]).", ".round($rpts[1]);
     652            for( $j=1; $j < 4; ++$j){
     653                $csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]);
     654            }
     655            if( !empty($this->csimtargets[$i]) ) {
     656                $this->csimareas .= '<area shape="poly" coords="'.$csimcoord.'" ';
     657                $this->csimareas .= " href=\"".htmlentities($this->csimtargets[$i])."\"";
     658
     659                if( !empty($this->csimwintargets[$i]) ) {
     660                    $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
     661                }
     662
     663                $sval='';
     664                if( !empty($this->csimalts[$i]) ) {
     665                    $sval=sprintf($this->csimalts[$i],$this->coords[0][$i]);
     666                    $this->csimareas .= " title=\"$sval\" alt=\"$sval\" ";
     667                }
     668                $this->csimareas .= " />\n";
     669            }
     670        }
     671        return true;
    579672    }
    580673} // Class
     
    585678//===================================================
    586679class GroupBarPlot extends BarPlot {
    587     private $plots, $nbrplots=0;
    588 //---------------
    589 // CONSTRUCTOR
    590     function GroupBarPlot($plots) {
    591         $this->width=0.7;
    592         $this->plots = $plots;
    593         $this->nbrplots = count($plots);
    594         if( $this->nbrplots < 1 ) {
    595             JpGraphError::RaiseL(2007);//('Cannot create GroupBarPlot from empty plot array.');
    596         }
    597         for($i=0; $i < $this->nbrplots; ++$i ) {
    598             if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) {
    599                 JpGraphError::RaiseL(2008,$i);//("Group bar plot element nbr $i is undefined or empty.");
    600             }
    601         }
    602         $this->numpoints = $plots[0]->numpoints;
    603         $this->width=0.7;
    604     }
    605 
    606 //---------------
    607 // PUBLIC METHODS       
     680    public $plots;
     681    private $nbrplots=0;
     682    //---------------
     683    // CONSTRUCTOR
     684    function __construct($plots) {
     685        $this->width=0.7;
     686        $this->plots = $plots;
     687        $this->nbrplots = count($plots);
     688        if( $this->nbrplots < 1 ) {
     689            JpGraphError::RaiseL(2007);//('Cannot create GroupBarPlot from empty plot array.');
     690        }
     691        for($i=0; $i < $this->nbrplots; ++$i ) {
     692            if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) {
     693                JpGraphError::RaiseL(2008,$i);//("Group bar plot element nbr $i is undefined or empty.");
     694            }
     695        }
     696        $this->numpoints = $plots[0]->numpoints;
     697        $this->width=0.7;
     698    }
     699
     700    //---------------
     701    // PUBLIC METHODS
    608702    function Legend($graph) {
    609         $n = count($this->plots);
    610         for($i=0; $i < $n; ++$i) {
    611             $c = get_class($this->plots[$i]);
    612             if( !($this->plots[$i] instanceof BarPlot) ) {
    613                 JpGraphError::RaiseL(2009,$c);
    614 //('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.')');
    615             }
    616             $this->plots[$i]->DoLegend($graph);
    617         }
    618     }
    619        
     703        $n = count($this->plots);
     704        for($i=0; $i < $n; ++$i) {
     705            $c = get_class($this->plots[$i]);
     706            if( !($this->plots[$i] instanceof BarPlot) ) {
     707                JpGraphError::RaiseL(2009,$c);
     708                //('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.')');
     709            }
     710            $this->plots[$i]->DoLegend($graph);
     711        }
     712    }
     713
    620714    function Min() {
    621         list($xmin,$ymin) = $this->plots[0]->Min();
    622         $n = count($this->plots);
    623         for($i=0; $i < $n; ++$i) {
    624             list($xm,$ym) = $this->plots[$i]->Min();
    625             $xmin = max($xmin,$xm);
    626             $ymin = min($ymin,$ym);
    627         }
    628         return array($xmin,$ymin);             
    629     }
    630        
     715        list($xmin,$ymin) = $this->plots[0]->Min();
     716        $n = count($this->plots);
     717        for($i=0; $i < $n; ++$i) {
     718            list($xm,$ym) = $this->plots[$i]->Min();
     719            $xmin = max($xmin,$xm);
     720            $ymin = min($ymin,$ym);
     721        }
     722        return array($xmin,$ymin);
     723    }
     724
    631725    function Max() {
    632         list($xmax,$ymax) = $this->plots[0]->Max();
    633         $n = count($this->plots);
    634         for($i=0; $i < $n; ++$i) {
    635             list($xm,$ym) = $this->plots[$i]->Max();
    636             $xmax = max($xmax,$xm);
    637             $ymax = max($ymax,$ym);
    638         }
    639         return array($xmax,$ymax);
    640     }
    641        
     726        list($xmax,$ymax) = $this->plots[0]->Max();
     727        $n = count($this->plots);
     728        for($i=0; $i < $n; ++$i) {
     729            list($xm,$ym) = $this->plots[$i]->Max();
     730            $xmax = max($xmax,$xm);
     731            $ymax = max($ymax,$ym);
     732        }
     733        return array($xmax,$ymax);
     734    }
     735
    642736    function GetCSIMareas() {
    643         $n = count($this->plots);
    644         $csimareas='';
    645         for($i=0; $i < $n; ++$i) {
    646             $csimareas .= $this->plots[$i]->csimareas;
    647         }
    648         return $csimareas;
    649     }
    650        
     737        $n = count($this->plots);
     738        $csimareas='';
     739        for($i=0; $i < $n; ++$i) {
     740            $csimareas .= $this->plots[$i]->csimareas;
     741        }
     742        return $csimareas;
     743    }
     744
    651745    // Stroke all the bars next to each other
    652     function Stroke($img,$xscale,$yscale) { 
    653         $tmp=$xscale->off;
    654         $n = count($this->plots);
    655         $subwidth = $this->width/$this->nbrplots ;
    656 
    657         for( $i=0; $i < $n; ++$i ) {
    658             $this->plots[$i]->ymin=$this->ybase;
    659             $this->plots[$i]->SetWidth($subwidth);
    660            
    661             // If the client have used SetTextTickInterval() then
    662             // major_step will be > 1 and the positioning will fail.
    663             // If we assume it is always one the positioning will work
    664             // fine with a text scale but this will not work with
    665             // arbitrary linear scale
    666             $xscale->off = $tmp+$i*round($xscale->scale_factor* $subwidth);
    667             $this->plots[$i]->Stroke($img,$xscale,$yscale);
    668         }
    669         $xscale->off=$tmp;
     746    function Stroke($img,$xscale,$yscale) {
     747        $tmp=$xscale->off;
     748        $n = count($this->plots);
     749        $subwidth = $this->width/$this->nbrplots ;
     750
     751        for( $i=0; $i < $n; ++$i ) {
     752            $this->plots[$i]->ymin=$this->ybase;
     753            $this->plots[$i]->SetWidth($subwidth);
     754
     755            // If the client have used SetTextTickInterval() then
     756            // major_step will be > 1 and the positioning will fail.
     757            // If we assume it is always one the positioning will work
     758            // fine with a text scale but this will not work with
     759            // arbitrary linear scale
     760            $xscale->off = $tmp+$i*round($xscale->scale_factor* $subwidth);
     761            $this->plots[$i]->Stroke($img,$xscale,$yscale);
     762        }
     763        $xscale->off=$tmp;
    670764    }
    671765} // Class
     
    676770//===================================================
    677771class AccBarPlot extends BarPlot {
    678     private $plots=null,$nbrplots=0;
    679 //---------------
    680 // CONSTRUCTOR
    681     function AccBarPlot($plots) {
    682         $this->plots = $plots;
    683         $this->nbrplots = count($plots);
    684         if( $this->nbrplots < 1 ) {
    685             JpGraphError::RaiseL(2010);//('Cannot create AccBarPlot from empty plot array.');
    686         }
    687         for($i=0; $i < $this->nbrplots; ++$i ) {
    688             if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) {
    689                 JpGraphError::RaiseL(2011,$i);//("Acc bar plot element nbr $i is undefined or empty.");
    690             }
    691         }
    692 
    693 // We can only allow individual plost which do not have specified X-positions
    694         for($i=0; $i < $this->nbrplots; ++$i ) {
    695             if( !empty($this->plots[$i]->coords[1]) ) {
    696                 JpGraphError::RaiseL(2015);
    697                 //'Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-positions.');
    698             }
    699         }
    700        
    701         $this->numpoints = $plots[0]->numpoints;               
    702         $this->value = new DisplayValue();
    703     }
    704 
    705 //---------------
    706 // PUBLIC METHODS       
     772    public $plots=null;
     773    private $nbrplots=0;
     774    //---------------
     775    // CONSTRUCTOR
     776    function __construct($plots) {
     777        $this->plots = $plots;
     778        $this->nbrplots = count($plots);
     779        if( $this->nbrplots < 1 ) {
     780            JpGraphError::RaiseL(2010);//('Cannot create AccBarPlot from empty plot array.');
     781        }
     782        for($i=0; $i < $this->nbrplots; ++$i ) {
     783            if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) {
     784                JpGraphError::RaiseL(2011,$i);//("Acc bar plot element nbr $i is undefined or empty.");
     785            }
     786        }
     787
     788        // We can only allow individual plost which do not have specified X-positions
     789        for($i=0; $i < $this->nbrplots; ++$i ) {
     790            if( !empty($this->plots[$i]->coords[1]) ) {
     791                JpGraphError::RaiseL(2015);
     792                //'Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-positions.');
     793            }
     794        }
     795
     796        // Use 0 weight by default which means that the individual bar
     797        // weights will be used per part n the accumulated bar
     798        $this->SetWeight(0);
     799
     800        $this->numpoints = $plots[0]->numpoints;
     801        $this->value = new DisplayValue();
     802    }
     803
     804    //---------------
     805    // PUBLIC METHODS
    707806    function Legend($graph) {
    708         $n = count($this->plots);
    709         for( $i=$n-1; $i >= 0; --$i ) {
    710             $c = get_class($this->plots[$i]);
    711             if( !($this->plots[$i] instanceof BarPlot) ) {
    712                 JpGraphError::RaiseL(2012,$c);
    713 //('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.')');
    714             }       
    715             $this->plots[$i]->DoLegend($graph);
    716         }
     807        $n = count($this->plots);
     808        for( $i=$n-1; $i >= 0; --$i ) {
     809            $c = get_class($this->plots[$i]);
     810            if( !($this->plots[$i] instanceof BarPlot) ) {
     811                JpGraphError::RaiseL(2012,$c);
     812                //('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.')');
     813            }
     814            $this->plots[$i]->DoLegend($graph);
     815        }
    717816    }
    718817
    719818    function Max() {
    720         list($xmax) = $this->plots[0]->Max();
    721         $nmax=0;
    722         for($i=0; $i < count($this->plots); ++$i) {
    723             $n = count($this->plots[$i]->coords[0]);
    724             $nmax = max($nmax,$n);
    725             list($x) = $this->plots[$i]->Max();
    726             $xmax = max($xmax,$x);
    727         }
    728         for( $i = 0; $i < $nmax; $i++ ) {
    729             // Get y-value for bar $i by adding the
    730             // individual bars from all the plots added.
    731             // It would be wrong to just add the
    732             // individual plots max y-value since that
    733             // would in most cases give to large y-value.
    734             $y=0;
    735             if( !isset($this->plots[0]->coords[0][$i]) ) {
    736                 JpGraphError::RaiseL(2014);
    737             }
    738             if( $this->plots[0]->coords[0][$i] > 0 )
    739                 $y=$this->plots[0]->coords[0][$i];
    740             for( $j = 1; $j < $this->nbrplots; $j++ ) {
    741                 if( !isset($this->plots[$j]->coords[0][$i]) ) {
    742                     JpGraphError::RaiseL(2014);
    743                 }
    744                 if( $this->plots[$j]->coords[0][$i] > 0 )
    745                     $y += $this->plots[$j]->coords[0][$i];
    746             }
    747             $ymax[$i] = $y;
    748         }
    749         $ymax = max($ymax);
    750 
    751         // Bar always start at baseline
    752         if( $ymax <= $this->ybase )
    753             $ymax = $this->ybase;
    754         return array($xmax,$ymax);
     819        list($xmax) = $this->plots[0]->Max();
     820        $nmax=0;
     821        for($i=0; $i < count($this->plots); ++$i) {
     822            $n = count($this->plots[$i]->coords[0]);
     823            $nmax = max($nmax,$n);
     824            list($x) = $this->plots[$i]->Max();
     825            $xmax = max($xmax,$x);
     826        }
     827        for( $i = 0; $i < $nmax; $i++ ) {
     828            // Get y-value for bar $i by adding the
     829            // individual bars from all the plots added.
     830            // It would be wrong to just add the
     831            // individual plots max y-value since that
     832            // would in most cases give to large y-value.
     833            $y=0;
     834            if( !isset($this->plots[0]->coords[0][$i]) ) {
     835                JpGraphError::RaiseL(2014);
     836            }
     837            if( $this->plots[0]->coords[0][$i] > 0 )
     838            $y=$this->plots[0]->coords[0][$i];
     839            for( $j = 1; $j < $this->nbrplots; $j++ ) {
     840                if( !isset($this->plots[$j]->coords[0][$i]) ) {
     841                    JpGraphError::RaiseL(2014);
     842                }
     843                if( $this->plots[$j]->coords[0][$i] > 0 )
     844                $y += $this->plots[$j]->coords[0][$i];
     845            }
     846            $ymax[$i] = $y;
     847        }
     848        $ymax = max($ymax);
     849
     850        // Bar always start at baseline
     851        if( $ymax <= $this->ybase )
     852        $ymax = $this->ybase;
     853        return array($xmax,$ymax);
    755854    }
    756855
    757856    function Min() {
    758         $nmax=0;
    759         list($xmin,$ysetmin) = $this->plots[0]->Min();
    760         for($i=0; $i < count($this->plots); ++$i) {
    761             $n = count($this->plots[$i]->coords[0]);
    762             $nmax = max($nmax,$n);
    763             list($x,$y) = $this->plots[$i]->Min();
    764             $xmin = Min($xmin,$x);
    765             $ysetmin = Min($y,$ysetmin);
    766         }
    767         for( $i = 0; $i < $nmax; $i++ ) {
    768             // Get y-value for bar $i by adding the
    769             // individual bars from all the plots added.
    770             // It would be wrong to just add the
    771             // individual plots max y-value since that
    772             // would in most cases give to large y-value.
    773             $y=0;
    774             if( $this->plots[0]->coords[0][$i] < 0 )
    775                 $y=$this->plots[0]->coords[0][$i];
    776             for( $j = 1; $j < $this->nbrplots; $j++ ) {
    777                 if( $this->plots[$j]->coords[0][$i] < 0 )
    778                     $y += $this->plots[ $j ]->coords[0][$i];
    779             }
    780             $ymin[$i] = $y;
    781         }
    782         $ymin = Min($ysetmin,Min($ymin));
    783         // Bar always start at baseline
    784         if( $ymin >= $this->ybase )
    785             $ymin = $this->ybase;
    786         return array($xmin,$ymin);
     857        $nmax=0;
     858        list($xmin,$ysetmin) = $this->plots[0]->Min();
     859        for($i=0; $i < count($this->plots); ++$i) {
     860            $n = count($this->plots[$i]->coords[0]);
     861            $nmax = max($nmax,$n);
     862            list($x,$y) = $this->plots[$i]->Min();
     863            $xmin = Min($xmin,$x);
     864            $ysetmin = Min($y,$ysetmin);
     865        }
     866        for( $i = 0; $i < $nmax; $i++ ) {
     867            // Get y-value for bar $i by adding the
     868            // individual bars from all the plots added.
     869            // It would be wrong to just add the
     870            // individual plots max y-value since that
     871            // would in most cases give to large y-value.
     872            $y=0;
     873            if( $this->plots[0]->coords[0][$i] < 0 )
     874            $y=$this->plots[0]->coords[0][$i];
     875            for( $j = 1; $j < $this->nbrplots; $j++ ) {
     876                if( $this->plots[$j]->coords[0][$i] < 0 )
     877                $y += $this->plots[ $j ]->coords[0][$i];
     878            }
     879            $ymin[$i] = $y;
     880        }
     881        $ymin = Min($ysetmin,Min($ymin));
     882        // Bar always start at baseline
     883        if( $ymin >= $this->ybase )
     884        $ymin = $this->ybase;
     885        return array($xmin,$ymin);
    787886    }
    788887
    789888    // Stroke acc bar plot
    790889    function Stroke($img,$xscale,$yscale) {
    791         $pattern=NULL;
    792         $img->SetLineWeight($this->weight);
    793         for($i=0; $i < $this->numpoints-1; $i++) {
    794             $accy = 0;
    795             $accy_neg = 0;
    796             for($j=0; $j < $this->nbrplots; ++$j ) {                           
    797                 $img->SetColor($this->plots[$j]->color);
    798 
    799                 if ( $this->plots[$j]->coords[0][$i] >= 0) {
    800                     $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
    801                     $accyt=$yscale->Translate($accy);
    802                     $accy+=$this->plots[$j]->coords[0][$i];
    803                 }
    804                 else {
    805                     //if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) {
    806                     $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
    807                     $accyt=$yscale->Translate($accy_neg);
    808                     $accy_neg+=$this->plots[$j]->coords[0][$i];
    809                 }                               
    810                                
    811                 $xt=$xscale->Translate($i);
    812 
    813                 if( $this->abswidth > -1 )
    814                     $abswidth=$this->abswidth;
    815                 else
    816                     $abswidth=round($this->width*$xscale->scale_factor,0);
    817                
    818                 $pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt);
    819 
    820                 if( $this->bar_shadow ) {
    821                     $ssh = $this->bar_shadow_hsize;
    822                     $ssv = $this->bar_shadow_vsize;
    823                    
    824                     // We must also differ if we are a positive or negative bar.
    825                     if( $j === 0 ) {
    826                         // This gets extra complicated since we have to
    827                         // see all plots to see if we are negative. It could
    828                         // for example be that all plots are 0 until the very
    829                         // last one. We therefore need to save the initial setup
    830                         // for both the negative and positive case
    831 
    832                         // In case the final bar is positive
    833                         $sp[0]=$pts[6]+1; $sp[1]=$pts[7];
    834                         $sp[2]=$pts[6]+$ssh; $sp[3]=$pts[7]-$ssv;
    835 
    836                         // In case the final bar is negative
    837                         $nsp[0]=$pts[0]; $nsp[1]=$pts[1];
    838                         $nsp[2]=$pts[0]+$ssh; $nsp[3]=$pts[1]-$ssv;
    839                         $nsp[4]=$pts[6]+$ssh; $nsp[5]=$pts[7]-$ssv;
    840                         $nsp[10]=$pts[6]+1; $nsp[11]=$pts[7];
    841                     }
    842 
    843                     if( $j === $this->nbrplots-1 ) {
    844                         // If this is the last plot of the bar and
    845                         // the total value is larger than 0 then we
    846                         // add the shadow.
    847                         if( is_array($this->bar_shadow_color) ) {
    848                             $numcolors = count($this->bar_shadow_color);
    849                             if( $numcolors == 0 ) {
    850                                 JpGraphError::RaiseL(2013);//('You have specified an empty array for shadow colors in the bar plot.');
    851                             }
    852                             $img->PushColor($this->bar_shadow_color[$i % $numcolors]);
    853                         }
    854                         else {
    855                             $img->PushColor($this->bar_shadow_color);
    856                         }
    857 
    858                         if( $accy > 0 ) {
    859                             $sp[4]=$pts[4]+$ssh; $sp[5]=$pts[5]-$ssv;
    860                             $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv;
    861                             $sp[8]=$pts[2]; $sp[9]=$pts[3]-1;
    862                             $sp[10]=$pts[4]+1; $sp[11]=$pts[5];
    863                             $img->FilledPolygon($sp,4);
    864                         }
    865                         elseif( $accy_neg < 0 ) {
    866                             $nsp[6]=$pts[4]+$ssh; $nsp[7]=$pts[5]-$ssv;
    867                             $nsp[8]=$pts[4]+1; $nsp[9]=$pts[5];
    868                             $img->FilledPolygon($nsp,4);
    869                         }
    870                         $img->PopColor();
    871                     }
    872                 }
    873 
    874 
    875                 // If value is NULL or 0, then don't draw a bar at all
    876                 if ($this->plots[$j]->coords[0][$i] == 0 ) continue;
    877 
    878                 if( $this->plots[$j]->grad ) {
    879                     $grad = new Gradient($img);
    880                     $grad->FilledRectangle(
    881                         $pts[2],$pts[3],
    882                         $pts[6],$pts[7],
    883                         $this->plots[$j]->grad_fromcolor,
    884                         $this->plots[$j]->grad_tocolor,
    885                         $this->plots[$j]->grad_style);                         
    886                 } else {
    887                     if (is_array($this->plots[$j]->fill_color) ) {
    888                         $numcolors = count($this->plots[$j]->fill_color);
    889                         $fillcolor = $this->plots[$j]->fill_color[$i % $numcolors];
    890                         // If the bar is specified to be non filled then the fill color is false
    891                         if( $fillcolor !== false )
    892                             $img->SetColor($this->plots[$j]->fill_color[$i % $numcolors]);
    893                     }
    894                     else {
    895                         $fillcolor = $this->plots[$j]->fill_color;
    896                         if( $fillcolor !== false )
    897                             $img->SetColor($this->plots[$j]->fill_color);
    898                     }
    899                     if( $fillcolor !== false )
    900                         $img->FilledPolygon($pts);
    901                     $img->SetColor($this->plots[$j]->color);
    902                 }                                 
    903 
    904                 // Stroke the pattern
    905                 if( $this->plots[$j]->iPattern > -1 ) {
    906                     if( $pattern===NULL )
    907                         $pattern = new RectPatternFactory();
    908                
    909                     $prect = $pattern->Create($this->plots[$j]->iPattern,$this->plots[$j]->iPatternColor,1);
    910                     $prect->SetDensity($this->plots[$j]->iPatternDensity);
    911                     if( $this->plots[$j]->coords[0][$i] < 0 ) {
    912                         $rx = $pts[0];
    913                         $ry = $pts[1];
    914                     }
    915                     else {
    916                         $rx = $pts[2];
    917                         $ry = $pts[3];
    918                     }
    919                     $width = abs($pts[4]-$pts[0])+1;
    920                     $height = abs($pts[1]-$pts[3])+1;
    921                     $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
    922                     $prect->Stroke($img);
    923                 }
    924 
    925 
    926                 // CSIM array
    927 
    928                 if( $i < count($this->plots[$j]->csimtargets) ) {
    929                     // Create the client side image map
    930                     $rpts = $img->ArrRotate($pts);             
    931                     $csimcoord=round($rpts[0]).", ".round($rpts[1]);
    932                     for( $k=1; $k < 4; ++$k){
    933                         $csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]);
    934                     }               
    935                     if( ! empty($this->plots[$j]->csimtargets[$i]) ) {
    936                         $this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" ';
    937                         $this->csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\" ";
    938 
    939                         if( ! empty($this->plots[$j]->csimwintargets[$i]) ) {
    940                             $this->csimareas.= " target=\"".$this->plots[$j]->csimwintargets[$i]."\" ";
    941                         }
    942 
    943                         $sval='';
    944                         if( !empty($this->plots[$j]->csimalts[$i]) ) {
    945                             $sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]);
    946                             $this->csimareas .= " title=\"$sval\" ";
    947                         }
    948                         $this->csimareas .= " alt=\"$sval\" />\n";                             
    949                     }
    950                 }
    951 
    952                 $pts[] = $pts[0];
    953                 $pts[] = $pts[1];
    954                 $img->SetLineWeight($this->plots[$j]->line_weight);
    955                 $img->Polygon($pts);
    956                 $img->SetLineWeight(1);
    957             }
    958                
    959             // Draw labels for each acc.bar
    960        
    961             $x=$pts[2]+($pts[4]-$pts[2])/2;
    962             if($this->bar_shadow) $x += $ssh;
    963 
    964             // First stroke the accumulated value for the entire bar
    965             // This value is always placed at the top/bottom of the bars
    966             if( $accy_neg < 0 ) {
    967                 $y=$yscale->Translate($accy_neg);                       
    968                 $this->value->Stroke($img,$accy_neg,$x,$y);
    969             }
    970             else {
    971                 $y=$yscale->Translate($accy);                   
    972                 $this->value->Stroke($img,$accy,$x,$y);
    973             }
    974 
    975             $accy = 0;
    976             $accy_neg = 0;
    977             for($j=0; $j < $this->nbrplots; ++$j ) {   
    978 
    979                 // We don't print 0 values in an accumulated bar plot
    980                 if( $this->plots[$j]->coords[0][$i] == 0 ) continue;
    981                        
    982                 if ($this->plots[$j]->coords[0][$i] > 0) {
    983                     $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
    984                     $accyt=$yscale->Translate($accy);
    985                     if(  $this->plots[$j]->valuepos=='center' ) {
    986                         $y = $accyt-($accyt-$yt)/2;
    987                     }
    988                     elseif( $this->plots[$j]->valuepos=='bottom' ) {
    989                         $y = $accyt;
    990                     }
    991                     else { // top or max
    992                         $y = $accyt-($accyt-$yt);
    993                     }
    994                     $accy+=$this->plots[$j]->coords[0][$i];
    995                     if(  $this->plots[$j]->valuepos=='center' ) {
    996                         $this->plots[$j]->value->SetAlign("center","center");
    997                         $this->plots[$j]->value->SetMargin(0);
    998                     }
    999                     elseif( $this->plots[$j]->valuepos=='bottom' ) {
    1000                         $this->plots[$j]->value->SetAlign('center','bottom');
    1001                         $this->plots[$j]->value->SetMargin(2);
    1002                     }
    1003                     else {
    1004                         $this->plots[$j]->value->SetAlign('center','top');
    1005                         $this->plots[$j]->value->SetMargin(1);
    1006                     }
    1007                 } else {
    1008                     $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
    1009                     $accyt=$yscale->Translate($accy_neg);
    1010                     $accy_neg+=$this->plots[$j]->coords[0][$i];
    1011                     if(  $this->plots[$j]->valuepos=='center' ) {
    1012                         $y = $accyt-($accyt-$yt)/2;
    1013                     }
    1014                     elseif( $this->plots[$j]->valuepos=='bottom' ) {
    1015                         $y = $accyt;
    1016                     }
    1017                     else {
    1018                         $y = $accyt-($accyt-$yt);
    1019                     }
    1020                     if(  $this->plots[$j]->valuepos=='center' ) {
    1021                         $this->plots[$j]->value->SetAlign("center","center");
    1022                         $this->plots[$j]->value->SetMargin(0);
    1023                     }
    1024                     elseif( $this->plots[$j]->valuepos=='bottom' ) {
    1025                         $this->plots[$j]->value->SetAlign('center',$j==0 ? 'bottom':'top');
    1026                         $this->plots[$j]->value->SetMargin(-2);
    1027                     }
    1028                     else {
    1029                         $this->plots[$j]->value->SetAlign('center','bottom');
    1030                         $this->plots[$j]->value->SetMargin(-1);
    1031                     }
    1032                 }       
    1033                 $this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],$x,$y);
    1034             }
    1035 
    1036         }
    1037         return true;
     890        $pattern=NULL;
     891        $img->SetLineWeight($this->weight);
     892        $grad=null;
     893        for($i=0; $i < $this->numpoints-1; $i++) {
     894            $accy = 0;
     895            $accy_neg = 0;
     896            for($j=0; $j < $this->nbrplots; ++$j ) {
     897                $img->SetColor($this->plots[$j]->color);
     898
     899                if ( $this->plots[$j]->coords[0][$i] >= 0) {
     900                    $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
     901                    $accyt=$yscale->Translate($accy);
     902                    $accy+=$this->plots[$j]->coords[0][$i];
     903                }
     904                else {
     905                    //if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) {
     906                    $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
     907                    $accyt=$yscale->Translate($accy_neg);
     908                    $accy_neg+=$this->plots[$j]->coords[0][$i];
     909                }
     910
     911                $xt=$xscale->Translate($i);
     912
     913                if( $this->abswidth > -1 ) {
     914                    $abswidth=$this->abswidth;
     915                }
     916                else {
     917                    $abswidth=round($this->width*$xscale->scale_factor,0);
     918                }
     919
     920                $pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt);
     921
     922                if( $this->bar_shadow ) {
     923                    $ssh = $this->bar_shadow_hsize;
     924                    $ssv = $this->bar_shadow_vsize;
     925
     926                    // We must also differ if we are a positive or negative bar.
     927                    if( $j === 0 ) {
     928                        // This gets extra complicated since we have to
     929                        // see all plots to see if we are negative. It could
     930                        // for example be that all plots are 0 until the very
     931                        // last one. We therefore need to save the initial setup
     932                        // for both the negative and positive case
     933
     934                        // In case the final bar is positive
     935                        $sp[0]=$pts[6]+1; $sp[1]=$pts[7];
     936                        $sp[2]=$pts[6]+$ssh; $sp[3]=$pts[7]-$ssv;
     937
     938                        // In case the final bar is negative
     939                        $nsp[0]=$pts[0]; $nsp[1]=$pts[1];
     940                        $nsp[2]=$pts[0]+$ssh; $nsp[3]=$pts[1]-$ssv;
     941                        $nsp[4]=$pts[6]+$ssh; $nsp[5]=$pts[7]-$ssv;
     942                        $nsp[10]=$pts[6]+1; $nsp[11]=$pts[7];
     943                    }
     944
     945                    if( $j === $this->nbrplots-1 ) {
     946                        // If this is the last plot of the bar and
     947                        // the total value is larger than 0 then we
     948                        // add the shadow.
     949                        if( is_array($this->bar_shadow_color) ) {
     950                            $numcolors = count($this->bar_shadow_color);
     951                            if( $numcolors == 0 ) {
     952                                JpGraphError::RaiseL(2013);//('You have specified an empty array for shadow colors in the bar plot.');
     953                            }
     954                            $img->PushColor($this->bar_shadow_color[$i % $numcolors]);
     955                        }
     956                        else {
     957                            $img->PushColor($this->bar_shadow_color);
     958                        }
     959
     960                        if( $accy > 0 ) {
     961                            $sp[4]=$pts[4]+$ssh; $sp[5]=$pts[5]-$ssv;
     962                            $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv;
     963                            $sp[8]=$pts[2]; $sp[9]=$pts[3]-1;
     964                            $sp[10]=$pts[4]+1; $sp[11]=$pts[5];
     965                            $img->FilledPolygon($sp,4);
     966                        }
     967                        elseif( $accy_neg < 0 ) {
     968                            $nsp[6]=$pts[4]+$ssh; $nsp[7]=$pts[5]-$ssv;
     969                            $nsp[8]=$pts[4]+1; $nsp[9]=$pts[5];
     970                            $img->FilledPolygon($nsp,4);
     971                        }
     972                        $img->PopColor();
     973                    }
     974                }
     975
     976
     977                // If value is NULL or 0, then don't draw a bar at all
     978                if ($this->plots[$j]->coords[0][$i] == 0 ) continue;
     979
     980                if( $this->plots[$j]->grad ) {
     981                    if( $grad === null ) {
     982                        $grad = new Gradient($img);
     983                    }
     984                    if( is_array($this->plots[$j]->grad_fromcolor) ) {
     985                        // The first argument (grad_fromcolor) can be either an array or a single color. If it is an array
     986                        // then we have two choices. It can either a) be a single color specified as an RGB triple or it can be
     987                        // an array to specify both (from, to style) for each individual bar. The way to know the difference is
     988                        // to investgate the first element. If this element is an integer [0,255] then we assume it is an RGB
     989                        // triple.
     990                        $ng = count($this->plots[$j]->grad_fromcolor);
     991                        if( $ng === 3 ) {
     992                            if( is_numeric($this->plots[$j]->grad_fromcolor[0]) && $this->plots[$j]->grad_fromcolor[0] > 0 &&
     993                                 $this->plots[$j]->grad_fromcolor[0] < 256 ) {
     994                                // RGB Triple
     995                                $fromcolor = $this->plots[$j]->grad_fromcolor;
     996                                $tocolor = $this->plots[$j]->grad_tocolor;
     997                                $style = $this->plots[$j]->grad_style;
     998                            }
     999                            else {
     1000                                $fromcolor = $this->plots[$j]->grad_fromcolor[$i % $ng][0];
     1001                                $tocolor = $this->plots[$j]->grad_fromcolor[$i % $ng][1];
     1002                                $style = $this->plots[$j]->grad_fromcolor[$i % $ng][2];
     1003                            }
     1004                        }
     1005                        else {
     1006                            $fromcolor = $this->plots[$j]->grad_fromcolor[$i % $ng][0];
     1007                            $tocolor = $this->plots[$j]->grad_fromcolor[$i % $ng][1];
     1008                            $style = $this->plots[$j]->grad_fromcolor[$i % $ng][2];
     1009                        }
     1010                        $grad->FilledRectangle($pts[2],$pts[3],
     1011                                               $pts[6],$pts[7],
     1012                                               $fromcolor,$tocolor,$style);
     1013                    }
     1014                    else {
     1015                        $grad->FilledRectangle($pts[2],$pts[3],
     1016                                               $pts[6],$pts[7],
     1017                                               $this->plots[$j]->grad_fromcolor,
     1018                                               $this->plots[$j]->grad_tocolor,
     1019                                               $this->plots[$j]->grad_style);
     1020                    }
     1021                } else {
     1022                    if (is_array($this->plots[$j]->fill_color) ) {
     1023                        $numcolors = count($this->plots[$j]->fill_color);
     1024                        $fillcolor = $this->plots[$j]->fill_color[$i % $numcolors];
     1025                        // If the bar is specified to be non filled then the fill color is false
     1026                        if( $fillcolor !== false ) {
     1027                            $img->SetColor($this->plots[$j]->fill_color[$i % $numcolors]);
     1028                        }
     1029                    }
     1030                    else {
     1031                        $fillcolor = $this->plots[$j]->fill_color;
     1032                        if( $fillcolor !== false ) {
     1033                            $img->SetColor($this->plots[$j]->fill_color);
     1034                        }
     1035                    }
     1036                    if( $fillcolor !== false ) {
     1037                        $img->FilledPolygon($pts);
     1038                    }
     1039                }
     1040
     1041                $img->SetColor($this->plots[$j]->color);
     1042
     1043                // Stroke the pattern
     1044                if( $this->plots[$j]->iPattern > -1 ) {
     1045                    if( $pattern===NULL ) {
     1046                        $pattern = new RectPatternFactory();
     1047                    }
     1048
     1049                    $prect = $pattern->Create($this->plots[$j]->iPattern,$this->plots[$j]->iPatternColor,1);
     1050                    $prect->SetDensity($this->plots[$j]->iPatternDensity);
     1051                    if( $this->plots[$j]->coords[0][$i] < 0 ) {
     1052                        $rx = $pts[0];
     1053                        $ry = $pts[1];
     1054                    }
     1055                    else {
     1056                        $rx = $pts[2];
     1057                        $ry = $pts[3];
     1058                    }
     1059                    $width = abs($pts[4]-$pts[0])+1;
     1060                    $height = abs($pts[1]-$pts[3])+1;
     1061                    $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
     1062                    $prect->Stroke($img);
     1063                }
     1064
     1065
     1066                // CSIM array
     1067
     1068                if( $i < count($this->plots[$j]->csimtargets) ) {
     1069                    // Create the client side image map
     1070                    $rpts = $img->ArrRotate($pts);
     1071                    $csimcoord=round($rpts[0]).", ".round($rpts[1]);
     1072                    for( $k=1; $k < 4; ++$k){
     1073                        $csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]);
     1074                    }
     1075                    if( ! empty($this->plots[$j]->csimtargets[$i]) ) {
     1076                        $this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" ';
     1077                        $this->csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\" ";
     1078
     1079                        if( ! empty($this->plots[$j]->csimwintargets[$i]) ) {
     1080                            $this->csimareas.= " target=\"".$this->plots[$j]->csimwintargets[$i]."\" ";
     1081                        }
     1082
     1083                        $sval='';
     1084                        if( !empty($this->plots[$j]->csimalts[$i]) ) {
     1085                            $sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]);
     1086                            $this->csimareas .= " title=\"$sval\" ";
     1087                        }
     1088                        $this->csimareas .= " alt=\"$sval\" />\n";
     1089                    }
     1090                }
     1091
     1092                $pts[] = $pts[0];
     1093                $pts[] = $pts[1];
     1094                $img->SetLineWeight($this->plots[$j]->weight);
     1095                $img->Polygon($pts);
     1096                $img->SetLineWeight(1);
     1097            }
     1098
     1099            // Daw potential bar around the entire accbar bar
     1100            if( $this->weight > 0 ) {
     1101                $y=$yscale->Translate(0);
     1102                $img->SetColor($this->color);
     1103                $img->SetLineWeight($this->weight);
     1104                $img->Rectangle($pts[0],$y,$pts[6],$pts[5]);
     1105            }
     1106
     1107            // Draw labels for each acc.bar
     1108
     1109            $x=$pts[2]+($pts[4]-$pts[2])/2;
     1110            if($this->bar_shadow) $x += $ssh;
     1111
     1112            // First stroke the accumulated value for the entire bar
     1113            // This value is always placed at the top/bottom of the bars
     1114            if( $accy + $accy_neg < 0 ) {
     1115                $y=$yscale->Translate($accy_neg);
     1116            }
     1117            else {
     1118                $y=$yscale->Translate($accy);
     1119            }
     1120            $this->value->Stroke($img,$accy + $accy_neg,$x,$y);
     1121
     1122            $accy = 0;
     1123            $accy_neg = 0;
     1124            for($j=0; $j < $this->nbrplots; ++$j ) {
     1125
     1126                // We don't print 0 values in an accumulated bar plot
     1127                if( $this->plots[$j]->coords[0][$i] == 0 ) continue;
     1128
     1129                if ($this->plots[$j]->coords[0][$i] > 0) {
     1130                    $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
     1131                    $accyt=$yscale->Translate($accy);
     1132                    if(  $this->plots[$j]->valuepos=='center' ) {
     1133                        $y = $accyt-($accyt-$yt)/2;
     1134                    }
     1135                    elseif( $this->plots[$j]->valuepos=='bottom' ) {
     1136                        $y = $accyt;
     1137                    }
     1138                    else { // top or max
     1139                        $y = $accyt-($accyt-$yt);
     1140                    }
     1141                    $accy+=$this->plots[$j]->coords[0][$i];
     1142                    if(  $this->plots[$j]->valuepos=='center' ) {
     1143                        $this->plots[$j]->value->SetAlign("center","center");
     1144                        $this->plots[$j]->value->SetMargin(0);
     1145                    }
     1146                    elseif( $this->plots[$j]->valuepos=='bottom' ) {
     1147                        $this->plots[$j]->value->SetAlign('center','bottom');
     1148                        $this->plots[$j]->value->SetMargin(2);
     1149                    }
     1150                    else {
     1151                        $this->plots[$j]->value->SetAlign('center','top');
     1152                        $this->plots[$j]->value->SetMargin(1);
     1153                    }
     1154                } else {
     1155                    $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
     1156                    $accyt=$yscale->Translate($accy_neg);
     1157                    $accy_neg+=$this->plots[$j]->coords[0][$i];
     1158                    if(  $this->plots[$j]->valuepos=='center' ) {
     1159                        $y = $accyt-($accyt-$yt)/2;
     1160                    }
     1161                    elseif( $this->plots[$j]->valuepos=='bottom' ) {
     1162                        $y = $accyt;
     1163                    }
     1164                    else {
     1165                        $y = $accyt-($accyt-$yt);
     1166                    }
     1167                    if(  $this->plots[$j]->valuepos=='center' ) {
     1168                        $this->plots[$j]->value->SetAlign("center","center");
     1169                        $this->plots[$j]->value->SetMargin(0);
     1170                    }
     1171                    elseif( $this->plots[$j]->valuepos=='bottom' ) {
     1172                        $this->plots[$j]->value->SetAlign('center',$j==0 ? 'bottom':'top');
     1173                        $this->plots[$j]->value->SetMargin(-2);
     1174                    }
     1175                    else {
     1176                        $this->plots[$j]->value->SetAlign('center','bottom');
     1177                        $this->plots[$j]->value->SetMargin(-1);
     1178                    }
     1179                }
     1180                $this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],round($x),round($y));
     1181            }
     1182
     1183        }
     1184        return true;
    10381185    }
    10391186} // Class
Note: See TracChangeset for help on using the changeset viewer.