]> git.llucax.com Git - mecon/meconlib.git/blob - lib/MECON/Graph/external/jpgraph/src/jpgraph_bar.php
Bugfixes.
[mecon/meconlib.git] / lib / MECON / Graph / external / jpgraph / src / jpgraph_bar.php
1 <?php
2 /*=======================================================================
3 // File:        JPGRAPH_BAR.PHP
4 // Description: Bar plot extension for JpGraph
5 // Created:     2001-01-08
6 // Author:      Johan Persson (johanp@aditus.nu)
7 // Ver:         $Id: jpgraph_bar.php,v 1.54.2.5 2003/08/15 19:06:15 aditus Exp $
8 //
9 // License:     This code is released under QPL
10 // Copyright (C) 2001,2002 Johan Persson
11 //========================================================================
12 */
13
14 //===================================================
15 // CLASS BarPlot
16 // Description: Main code to produce a bar plot 
17 //===================================================
18 class BarPlot extends Plot {
19     var $width=0.4; // in percent of major ticks
20     var $abswidth=-1; // Width in absolute pixels
21     var $fill=false,$fill_color="lightblue"; // Default is to fill with light blue
22     var $ybase=0; // Bars start at 0 
23     var $align="center";
24     var $grad=false,$grad_style=1;
25     var $grad_fromcolor=array(50,50,200),$grad_tocolor=array(255,255,255);
26     var $bar_shadow=false;
27     var $bar_shadow_color="black";
28     var $bar_shadow_hsize=3,$bar_shadow_vsize=3;        
29     var $valuepos='top';
30         
31 //---------------
32 // CONSTRUCTOR
33     function BarPlot(&$datay,$datax=false) {
34         $this->Plot($datay,$datax);             
35         ++$this->numpoints;
36     }
37
38 //---------------
39 // PUBLIC METHODS       
40         
41     // Set a drop shadow for the bar (or rather an "up-right" shadow)
42     function SetShadow($color="black",$hsize=3,$vsize=3) {
43         $this->bar_shadow=true;
44         $this->bar_shadow_color=$color;
45         $this->bar_shadow_vsize=$vsize;
46         $this->bar_shadow_hsize=$hsize;
47                 
48         // Adjust the value margin to compensate for shadow
49         $this->value->margin += $vsize;
50     }
51                 
52     // DEPRECATED use SetYBase instead
53     function SetYMin($aYStartValue) {
54         //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead.");           
55         $this->ybase=$aYStartValue;
56     }
57
58     // Specify the base value for the bars
59     function SetYBase($aYStartValue) {
60         $this->ybase=$aYStartValue;
61     }
62         
63     function Legend(&$graph) {
64         if( $this->grad && $this->legend!="" && !$this->fill ) {
65             $color=array($this->grad_fromcolor,$this->grad_tocolor,$this->grad_style);
66             $graph->legend->Add($this->legend,$color,"",0,
67                                 $this->legendcsimtarget,$this->legendcsimalt);
68         }
69         elseif( $this->fill_color && $this->legend!="" ) {
70             if( is_array($this->fill_color) )
71                 $graph->legend->Add($this->legend,$this->fill_color[0],"",0,
72                                     $this->legendcsimtarget,$this->legendcsimalt);
73             else
74                 $graph->legend->Add($this->legend,$this->fill_color,"",0,
75                                     $this->legendcsimtarget,$this->legendcsimalt);      
76         }
77     }
78
79     // Gets called before any axis are stroked
80     function PreStrokeAdjust(&$graph) {
81         parent::PreStrokeAdjust($graph);
82
83         // If we are using a log Y-scale we want the base to be at the
84         // minimum Y-value unless the user have specifically set some other
85         // value than the default.
86         if( substr($graph->axtype,-3,3)=="log" && $this->ybase==0 )
87             $this->ybase = $graph->yaxis->scale->GetMinVal();
88                 
89         // For a "text" X-axis scale we will adjust the
90         // display of the bars a little bit.
91         if( substr($graph->axtype,0,3)=="tex" ) {
92             // Position the ticks between the bars
93             $graph->xaxis->scale->ticks->SetXLabelOffset(0.5,0);
94
95             // Center the bars 
96             if( $this->align == "center" )
97                 $graph->SetTextScaleOff(0.5-$this->width/2);                                    
98             elseif( $this->align == "right" )
99                 $graph->SetTextScaleOff(1-$this->width);                        
100
101         }
102         else {
103             // We only set an absolute width for linear and int scale
104             // for text scale the width will be set to a fraction of
105             // the majstep width.
106             if( $this->abswidth == -1 ) {
107                 // Not set
108                 // set width to a visuable sensible default
109                 $this->abswidth = $graph->img->plotwidth/(2*count($this->coords[0]));
110             }
111         }
112     }
113
114     function Min() {
115         $m = parent::Min();
116         if( $m[1] >= $this->ybase )
117             $m[1] = $this->ybase;
118         return $m;      
119     }
120
121     function Max() {
122         $m = parent::Max();
123         if( $m[1] <= $this->ybase )
124             $m[1] = $this->ybase;
125         return $m;      
126     }   
127         
128     // Specify width as fractions of the major stepo size
129     function SetWidth($aFractionWidth) {
130         $this->width=$aFractionWidth;
131     }
132         
133     // Specify width in absolute pixels. If specified this
134     // overrides SetWidth()
135     function SetAbsWidth($aWidth) {
136         $this->abswidth=$aWidth;
137     }
138                 
139     function SetAlign($aAlign) {
140         $this->align=$aAlign;
141     }
142         
143     function SetNoFill() {
144         $this->grad = false;
145         $this->fill_color=false;
146         $this->fill=false;
147     }
148                 
149     function SetFillColor($aColor) {
150         $this->fill = true ;
151         $this->fill_color=$aColor;
152     }
153         
154     function SetFillGradient($from_color,$to_color,$style) {
155         $this->grad=true;
156         $this->grad_fromcolor=$from_color;
157         $this->grad_tocolor=$to_color;
158         $this->grad_style=$style;
159     }
160         
161     function SetValuePos($aPos) {
162         $this->valuepos = $aPos;
163     }
164
165     function Stroke(&$img,&$xscale,&$yscale) { 
166                 
167         $numpoints = count($this->coords[0]);
168         if( isset($this->coords[1]) ) {
169             if( count($this->coords[1])!=$numpoints )
170                 die("JpGraph Error: Number of X and Y points are not equal.<br>
171                                         Number of X-points:".count($this->coords[1])."<br>
172                                         Number of Y-points:$numpoints");
173             else
174                 $exist_x = true;
175         }
176         else 
177             $exist_x = false;
178                 
179                 
180         $numbars=count($this->coords[0]);
181
182         // Use GetMinVal() instead of scale[0] directly since in the case
183         // of log scale we get a correct value. Log scales will have negative
184         // values for values < 1 while still not representing negative numbers.
185         if( $yscale->GetMinVal() >= 0 ) 
186             $zp=$yscale->scale_abs[0]; 
187         else {
188             $zp=$yscale->Translate(0);
189         }
190
191         if( $this->abswidth > -1 ) {
192             $abswidth=$this->abswidth;
193         }
194         else
195             $abswidth=round($this->width*$xscale->scale_factor,0);
196                                         
197         for($i=0; $i<$numbars; $i++) {
198
199             // If value is NULL, or 0 then don't draw a bar at all
200             if ($this->coords[0][$i] === null ||
201                 $this->coords[0][$i] === '' ||
202                 $this->coords[0][$i] === 0 ) continue;    
203
204             if( $exist_x ) $x=$this->coords[1][$i];
205             else $x=$i;
206                         
207             $x=$xscale->Translate($x);
208
209             if( !$xscale->textscale ) {
210                 if($this->align=="center")
211                     $x -= $abswidth/2;
212                 elseif($this->align=="right")
213                     $x -= $abswidth;                    
214             }
215
216             $pts=array(
217                 $x,$zp,
218                 $x,$yscale->Translate($this->coords[0][$i]),
219                 $x+$abswidth,$yscale->Translate($this->coords[0][$i]),
220                 $x+$abswidth,$zp);
221             if( $this->grad ) {
222                 $grad = new Gradient($img);
223                 $grad->FilledRectangle($pts[2],$pts[3],
224                                        $pts[6],$pts[7],
225                                        $this->grad_fromcolor,$this->grad_tocolor,$this->grad_style); 
226             }
227             elseif( !empty($this->fill_color) ) {
228                 if(is_array($this->fill_color)) {
229                     $img->PushColor($this->fill_color[$i % count($this->fill_color)]);
230                 } else {
231                     $img->PushColor($this->fill_color);
232                 }
233                 $img->FilledPolygon($pts);
234                 $img->PopColor();
235             }
236                         
237             // Remember value of this bar
238             $val=$this->coords[0][$i];
239                         
240             if( $this->bar_shadow && $val !== 0 && $val !== 0.0 ) {
241                 $ssh = $this->bar_shadow_hsize;
242                 $ssv = $this->bar_shadow_vsize;
243                 // Create points to create a "upper-right" shadow
244                 if( $val > 0 ) {
245                     $sp[0]=$pts[6];             $sp[1]=$pts[7];
246                     $sp[2]=$pts[4];             $sp[3]=$pts[5];
247                     $sp[4]=$pts[2];             $sp[5]=$pts[3];
248                     $sp[6]=$pts[2]+$ssh;        $sp[7]=$pts[3]-$ssv;
249                     $sp[8]=$pts[4]+$ssh;        $sp[9]=$pts[5]-$ssv;
250                     $sp[10]=$pts[6]+$ssh;       $sp[11]=$pts[7]-$ssv;
251                 } 
252                 elseif( $val < 0 ) {
253                     $sp[0]=$pts[4];             $sp[1]=$pts[5];
254                     $sp[2]=$pts[6];             $sp[3]=$pts[7];
255                     $sp[4]=$pts[0];     $sp[5]=$pts[1];
256                     $sp[6]=$pts[0]+$ssh;        $sp[7]=$pts[1]-$ssv;
257                     $sp[8]=$pts[6]+$ssh;        $sp[9]=$pts[7]-$ssv;
258                     $sp[10]=$pts[4]+$ssh;       $sp[11]=$pts[5]-$ssv;
259                 }
260                                 
261                 $img->PushColor($this->bar_shadow_color);
262                 $img->FilledPolygon($sp);
263                 $img->PopColor();
264             }
265                         
266             // Stroke the outline of the bar
267             if( is_array($this->color) )
268                 $img->SetColor($this->color[$i % count($this->color)]);
269             else
270                 $img->SetColor($this->color);
271
272             $pts[] = $pts[0];
273             $pts[] = $pts[1];
274
275             if( $this->weight > 0 ) {
276                 $img->SetLineWeight($this->weight);
277                 $img->Polygon($pts);
278             }
279                                 
280             $x=$pts[2]+($pts[4]-$pts[2])/2;
281             if( $this->valuepos=='top' ) {
282                 $y=$pts[3];
283                 $this->value->Stroke($img,$val,$x,$y);
284             }
285             elseif( $this->valuepos=='max' ) {
286                 $y=$pts[3];
287                 if( $img->a === 90 ) {
288                     $this->value->SetAlign('right','center');
289                 }
290                 else {
291                     $this->value->SetAlign('center','top');
292                 }
293                 $this->value->SetMargin(-2);
294                 $this->value->Stroke($img,$val,$x,$y);
295             }
296             elseif( $this->valuepos=='center' ) {
297                 $y = ($pts[3] + $pts[1])/2;
298                 $this->value->SetAlign('center','center');
299                 $this->value->SetMargin(0);
300                 $this->value->Stroke($img,$val,$x,$y);
301             }
302             elseif( $this->valuepos=='bottom' || $this->valuepos=='min' ) {
303                 $y=$pts[1];
304                 $this->value->SetMargin(0);
305                 $this->value->Stroke($img,$val,$x,$y);
306             }
307             else {
308                 JpGraphError::Raise('Unknown position for values on bars :'.$this->valuepos);
309                 die();
310             }
311             // Create the client side image map
312             $rpts = $img->ArrRotate($pts);              
313             $csimcoord=round($rpts[0]).", ".round($rpts[1]);
314             for( $j=1; $j < 4; ++$j){
315                 $csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]);
316             }               
317             if( !empty($this->csimtargets[$i]) ) {
318                 $this->csimareas .= '<area shape="poly" coords="'.$csimcoord.'" ';          
319                 $this->csimareas .= " href=\"".$this->csimtargets[$i]."\"";
320                 if( !empty($this->csimalts[$i]) ) {
321                     $sval=sprintf($this->csimalts[$i],$this->coords[0][$i]);
322                     $this->csimareas .= " alt=\"$sval\" title=\"$sval\" ";
323                 }
324                 $this->csimareas .= ">\n";
325             }
326         }
327         return true;
328     }
329 } // Class
330
331 //===================================================
332 // CLASS GroupBarPlot
333 // Description: Produce grouped bar plots
334 //===================================================
335 class GroupBarPlot extends BarPlot {
336     var $plots;
337     var $width=0.7;
338     var $nbrplots=0;
339     var $numpoints;
340 //---------------
341 // CONSTRUCTOR
342     function GroupBarPlot($plots) {
343         $this->plots = $plots;
344         $this->nbrplots = count($plots);
345         $this->numpoints = $plots[0]->numpoints;
346     }
347
348 //---------------
349 // PUBLIC METHODS       
350     function Legend(&$graph) {
351         $n = count($this->plots);
352         for($i=0; $i<$n; ++$i)
353             $this->plots[$i]->DoLegend($graph);
354     }
355         
356     function Min() {
357         list($xmin,$ymin) = $this->plots[0]->Min();
358         $n = count($this->plots);
359         for($i=0; $i<$n; ++$i) {
360             list($xm,$ym) = $this->plots[$i]->Min();
361             $xmin = max($xmin,$xm);
362             $ymin = min($ymin,$ym);
363         }
364         return array($xmin,$ymin);              
365     }
366         
367     function Max() {
368         list($xmax,$ymax) = $this->plots[0]->Max();
369         $n = count($this->plots);
370         for($i=0; $i<$n; ++$i) {
371             list($xm,$ym) = $this->plots[$i]->Max();
372             $xmax = max($xmax,$xm);
373             $ymax = max($ymax,$ym);
374         }
375         return array($xmax,$ymax);
376     }
377         
378     function GetCSIMareas() {
379         $n = count($this->plots);
380         $csimareas='';
381         for($i=0; $i < $n; ++$i) {
382             $csimareas .= $this->plots[$i]->csimareas;
383         }
384         return $csimareas;
385     }
386         
387     // Stroke all the bars next to each other
388     function Stroke(&$img,&$xscale,&$yscale) { 
389         $tmp=$xscale->off;
390         $n = count($this->plots);
391         $subwidth = $this->width/$this->nbrplots ; 
392         for( $i=0; $i < $n; ++$i ) {
393             $this->plots[$i]->ymin=$this->ybase;
394             $this->plots[$i]->SetWidth($subwidth);
395             
396             // If the client have used SetTextTickInterval() then
397             // major_step will be > 1 and the positioning will fail.
398             // If we assume it is always one the positioning will work
399             // fine with a text scale but this will not work with
400             // arbitrary linear scale
401             $xscale->off = $tmp+$i*round(/*$xscale->ticks->major_step* */
402                                          $xscale->scale_factor*$subwidth);
403             $this->plots[$i]->Stroke($img,$xscale,$yscale);
404         }
405         $xscale->off=$tmp;
406     }
407 } // Class
408
409 //===================================================
410 // CLASS AccBarPlot
411 // Description: Produce accumulated bar plots
412 //===================================================
413 class AccBarPlot extends BarPlot {
414     var $plots=null,$nbrplots=0,$numpoints=0;
415 //---------------
416 // CONSTRUCTOR
417     function AccBarPlot($plots) {
418         $this->plots = $plots;
419         $this->nbrplots = count($plots);
420         $this->numpoints = $plots[0]->numpoints;                
421         $this->value = new DisplayValue();
422     }
423
424 //---------------
425 // PUBLIC METHODS       
426     function Legend(&$graph) {
427         $n = count($this->plots);
428         for( $i=$n-1; $i>=0; --$i ) 
429             $this->plots[$i]->DoLegend($graph);
430     }
431
432     function Max() {
433         list($xmax) = $this->plots[0]->Max();
434         $nmax=0;
435         for($i=0; $i<count($this->plots); ++$i) {
436             $n = count($this->plots[$i]->coords[0]);
437             $nmax = max($nmax,$n);
438             list($x) = $this->plots[$i]->Max();
439             $xmax = max($xmax,$x);
440         }
441         for( $i = 0; $i < $nmax; $i++ ) {
442             // Get y-value for bar $i by adding the
443             // individual bars from all the plots added.
444             // It would be wrong to just add the
445             // individual plots max y-value since that
446             // would in most cases give to large y-value.
447             $y=0;
448             if( $this->plots[0]->coords[0][$i] > 0 )
449                 $y=$this->plots[0]->coords[0][$i];
450             for( $j = 1; $j < $this->nbrplots; $j++ ) {
451                 if( $this->plots[$j]->coords[0][$i] > 0 )
452                     $y += $this->plots[$j]->coords[0][$i];
453             }
454             $ymax[$i] = $y;
455         }
456         $ymax = max($ymax);
457
458         // Bar always start at baseline
459         if( $ymax <= $this->ybase ) 
460             $ymax = $this->ybase;
461         return array($xmax,$ymax);
462     }
463
464     function Min() {
465         $nmax=0;
466         list($xmin,$ysetmin) = $this->plots[0]->Min();
467         for($i=0; $i<count($this->plots); ++$i) {
468             $n = count($this->plots[$i]->coords[0]);
469             $nmax = max($nmax,$n);
470             list($x,$y) = $this->plots[$i]->Min();
471             $xmin = Min($xmin,$x);
472             $ysetmin = Min($y,$ysetmin);
473         }
474         for( $i = 0; $i < $nmax; $i++ ) {
475             // Get y-value for bar $i by adding the
476             // individual bars from all the plots added.
477             // It would be wrong to just add the
478             // individual plots max y-value since that
479             // would in most cases give to large y-value.
480             $y=$this->plots[0]->coords[0][$i];
481             for( $j = 1; $j < $this->nbrplots; $j++ ) {
482                 $y += $this->plots[ $j ]->coords[0][$i];
483             }
484             $ymin[$i] = $y;
485         }
486         $ymin = Min($ysetmin,Min($ymin));
487         // Bar always start at baseline
488         if( $ymin >= $this->ybase )
489             $ymin = $this->ybase;
490         return array($xmin,$ymin);
491     }
492
493     // Stroke acc bar plot
494     function Stroke(&$img,&$xscale,&$yscale) {
495         $img->SetLineWeight($this->weight);
496         for($i=0; $i<$this->numpoints-1; $i++) {
497             $accy = 0;
498             $accy_neg = 0; 
499             for($j=0; $j < $this->nbrplots; ++$j ) {                            
500             
501                 $img->SetColor($this->plots[$j]->color);
502
503                 if ( $this->plots[$j]->coords[0][$i] >= 0) {
504                     $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
505                     $accyt=$yscale->Translate($accy);
506                     $accy+=$this->plots[$j]->coords[0][$i];
507                 }
508                 else {
509                     //if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) {
510                     $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
511                     $accyt=$yscale->Translate($accy_neg);
512                     $accy_neg+=$this->plots[$j]->coords[0][$i];
513                 }                               
514                                 
515                 $xt=$xscale->Translate($i);
516
517                 if( $this->abswidth > -1 )
518                     $abswidth=$this->abswidth;
519                 else
520                     $abswidth=round($this->width*$xscale->scale_factor,0);
521                 
522                 $pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt);
523
524                 if( $this->bar_shadow ) {
525                     $ssh = $this->bar_shadow_hsize;
526                     $ssv = $this->bar_shadow_vsize;
527                     
528                     // We must also differ if we are a positive or negative bar. 
529                     if( $j === 0 ) {
530                         // This gets extra complicated since we have to
531                         // see all plots to see if we are negative. It could
532                         // for example be that all plots are 0 until the very
533                         // last one. We therefore need to save the initial setup
534                         // for both the negative and positive case
535
536                         // In case the final bar is positive
537                         $sp[0]=$pts[6]+1; $sp[1]=$pts[7];
538                         $sp[2]=$pts[6]+$ssh; $sp[3]=$pts[7]-$ssv;
539
540                         // In case the final bar is negative
541                         $nsp[0]=$pts[0]; $nsp[1]=$pts[1];
542                         $nsp[2]=$pts[0]+$ssh; $nsp[3]=$pts[1]-$ssv;
543                         $nsp[4]=$pts[6]+$ssh; $nsp[5]=$pts[7]-$ssv;
544                         $nsp[10]=$pts[6]+1; $nsp[11]=$pts[7];
545                     }
546
547                     if( $j === $this->nbrplots-1 ) {
548                         // If this is the last plot of the bar and
549                         // the total value is larger than 0 then we
550                         // add the shadow.
551                         if( $accy > 0 ) {
552                             $sp[4]=$pts[4]+$ssh; $sp[5]=$pts[5]-$ssv;
553                             $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv;
554                             $sp[8]=$pts[2]; $sp[9]=$pts[3]-1;
555                             $sp[10]=$pts[4]+1; $sp[11]=$pts[5];
556                             $img->PushColor($this->bar_shadow_color);
557                             $img->FilledPolygon($sp,4);
558                             $img->PopColor();
559                         }
560                         elseif( $accy_neg < 0 ) {
561                             $nsp[6]=$pts[4]+$ssh; $nsp[7]=$pts[5]-$ssv;
562                             $nsp[8]=$pts[4]+1; $nsp[9]=$pts[5];
563                             $img->PushColor($this->bar_shadow_color);
564                             $img->FilledPolygon($nsp,4);
565                             $img->PopColor();
566                         }
567                     }
568                 }
569
570                 // If value is NULL or 0, then don't draw a bar at all
571                 if ($this->plots[$j]->coords[0][$i] == 0 ) continue;
572
573                 if( $this->plots[$j]->grad ) {
574                     $grad = new Gradient($img);
575                     $grad->FilledRectangle(
576                         $pts[2],$pts[3],
577                         $pts[6],$pts[7],
578                         $this->plots[$j]->grad_fromcolor,
579                         $this->plots[$j]->grad_tocolor,
580                         $this->plots[$j]->grad_style);                          
581                 } else {
582                     if (is_array($this->plots[$j]->fill_color) ) {
583                         $numcolors = count($this->plots[$j]->fill_color);
584                         $img->SetColor($this->plots[$j]->fill_color[$i % $numcolors]);
585                     }
586                     else {
587                         $img->SetColor($this->plots[$j]->fill_color);
588                     }
589                     $img->FilledPolygon($pts);
590                     $img->SetColor($this->plots[$j]->color);
591                 }                                 
592
593
594                 // CSIM array
595
596                 if( $i < count($this->plots[$j]->csimtargets) ) {
597                     // Create the client side image map
598                     $rpts = $img->ArrRotate($pts);              
599                     $csimcoord=round($rpts[0]).", ".round($rpts[1]);
600                     for( $k=1; $k < 4; ++$k){
601                         $csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]);
602                     }               
603                     if( ! empty($this->plots[$j]->csimtargets[$i]) ) {
604                         $this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" '; 
605                         $this->csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\"";
606                         if( !empty($this->plots[$j]->csimalts[$i]) ) {
607                             $sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]);
608                             $this->csimareas .= " alt=\"$sval\" title=\"$sval\" ";
609                         }
610                         $this->csimareas .= ">\n";                              
611                     }
612                 }
613
614                 $pts[] = $pts[0];
615                 $pts[] = $pts[1];
616                 $img->Polygon($pts);
617             }
618                 
619             // Draw labels for each acc.bar
620         
621             $x=$pts[2]+($pts[4]-$pts[2])/2;
622             $y=$yscale->Translate($accy);                       
623             if($this->bar_shadow) $x += $ssh;
624             $this->value->Stroke($img,$accy,$x,$y);
625
626             $accy = 0;
627             $accy_neg = 0; 
628             for($j=0; $j<$this->nbrplots; ++$j ) {                              
629                 if ($this->plots[$j]->coords[0][$i] > 0) {
630                     $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
631                     $accyt=$yscale->Translate($accy);
632                     $y = $accyt-($accyt-$yt)/2;
633                     $accy+=$this->plots[$j]->coords[0][$i];
634                 } else {
635                     $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
636                     $accyt=$yscale->Translate($accy_neg);
637                     //$y=0;
638                     $accy_neg+=$this->plots[$j]->coords[0][$i];
639                     $y = $accyt-($accyt-$yt)/2; // TODO : Check this fix
640                 }       
641                 $this->plots[$j]->value->SetAlign("center","center");
642                 $this->plots[$j]->value->SetMargin(0);
643                 $this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],$x,$y);
644             }
645
646         }
647         return true;
648     }
649 } // Class
650
651 /* EOF */
652 ?>