source: trunk/client/modules/Elezioni/grafici-old/jpgraph_bar.php@ 11

Last change on this file since 11 was 2, checked in by root, 15 years ago

importo il progetto

File size: 18.2 KB
Line 
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 2003/05/12 19:54:53 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//===================================================
18class 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 ) {
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=='center' ) {
286 $y = ($pts[3] + $pts[1])/2;
287 $this->value->SetAlign('center','center');
288 $this->value->SetMargin(0);
289 $this->value->Stroke($img,$val,$x,$y);
290 }
291 elseif( $this->valuepos=='bottom' ) {
292 $y=$pts[1];
293 $this->value->SetMargin(0);
294 $this->value->Stroke($img,$val,$x,$y);
295 }
296 else {
297 JpGraphError::Raise('Unknown position for values on bars :'.$this->valuepos);
298 die();
299 }
300 // Create the client side image map
301 $rpts = $img->ArrRotate($pts);
302 $csimcoord=round($rpts[0]).", ".round($rpts[1]);
303 for( $j=1; $j < 4; ++$j){
304 $csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]);
305 }
306 $this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" ';
307 if( !empty($this->csimtargets[$i]) )
308 $this->csimareas .= " href=\"".$this->csimtargets[$i]."\"";
309 if( !empty($this->csimalts[$i]) ) {
310 $sval=sprintf($this->csimalts[$i],$this->coords[0][$i]);
311 $this->csimareas .= " alt=\"$sval\" title=\"$sval\" ";
312 }
313 $this->csimareas .= ">\n";
314 }
315 return true;
316 }
317} // Class
318
319//===================================================
320// CLASS GroupBarPlot
321// Description: Produce grouped bar plots
322//===================================================
323class GroupBarPlot extends BarPlot {
324 var $plots;
325 var $width=0.7;
326 var $nbrplots=0;
327 var $numpoints;
328//---------------
329// CONSTRUCTOR
330 function GroupBarPlot($plots) {
331 $this->plots = $plots;
332 $this->nbrplots = count($plots);
333 $this->numpoints = $plots[0]->numpoints;
334 }
335
336//---------------
337// PUBLIC METHODS
338 function Legend(&$graph) {
339 $n = count($this->plots);
340 for($i=0; $i<$n; ++$i)
341 $this->plots[$i]->DoLegend($graph);
342 }
343
344 function Min() {
345 list($xmin,$ymin) = $this->plots[0]->Min();
346 $n = count($this->plots);
347 for($i=0; $i<$n; ++$i) {
348 list($xm,$ym) = $this->plots[$i]->Min();
349 $xmin = max($xmin,$xm);
350 $ymin = min($ymin,$ym);
351 }
352 return array($xmin,$ymin);
353 }
354
355 function Max() {
356 list($xmax,$ymax) = $this->plots[0]->Max();
357 $n = count($this->plots);
358 for($i=0; $i<$n; ++$i) {
359 list($xm,$ym) = $this->plots[$i]->Max();
360 $xmax = max($xmax,$xm);
361 $ymax = max($ymax,$ym);
362 }
363 return array($xmax,$ymax);
364 }
365
366 function GetCSIMareas() {
367 $n = count($this->plots);
368 $csimareas='';
369 for($i=0; $i < $n; ++$i) {
370 $csimareas .= $this->plots[$i]->csimareas;
371 }
372 return $csimareas;
373 }
374
375 // Stroke all the bars next to each other
376 function Stroke(&$img,&$xscale,&$yscale) {
377 $tmp=$xscale->off;
378 $n = count($this->plots);
379 $subwidth = $this->width/$this->nbrplots ;
380 for( $i=0; $i < $n; ++$i ) {
381 $this->plots[$i]->ymin=$this->ybase;
382 $this->plots[$i]->SetWidth($subwidth);
383
384 // If the client have used SetTextTickInterval() then
385 // major_step will be > 1 and the positioning will fail.
386 // If we assume it is always one the positioning will work
387 // fine with a text scale but this will not work with
388 // arbitrary linear scale
389 $xscale->off = $tmp+$i*round(/*$xscale->ticks->major_step* */
390 $xscale->scale_factor*$subwidth);
391 $this->plots[$i]->Stroke($img,$xscale,$yscale);
392 }
393 $xscale->off=$tmp;
394 }
395} // Class
396
397//===================================================
398// CLASS AccBarPlot
399// Description: Produce accumulated bar plots
400//===================================================
401class AccBarPlot extends BarPlot {
402 var $plots=null,$nbrplots=0,$numpoints=0;
403//---------------
404// CONSTRUCTOR
405 function AccBarPlot($plots) {
406 $this->plots = $plots;
407 $this->nbrplots = count($plots);
408 $this->numpoints = $plots[0]->numpoints;
409 $this->value = new DisplayValue();
410 }
411
412//---------------
413// PUBLIC METHODS
414 function Legend(&$graph) {
415 $n = count($this->plots);
416 for( $i=$n-1; $i>=0; --$i )
417 $this->plots[$i]->DoLegend($graph);
418 }
419
420 function Max() {
421 list($xmax) = $this->plots[0]->Max();
422 $nmax=0;
423 for($i=0; $i<count($this->plots); ++$i) {
424 $n = count($this->plots[$i]->coords[0]);
425 $nmax = max($nmax,$n);
426 list($x) = $this->plots[$i]->Max();
427 $xmax = max($xmax,$x);
428 }
429 for( $i = 0; $i < $nmax; $i++ ) {
430 // Get y-value for bar $i by adding the
431 // individual bars from all the plots added.
432 // It would be wrong to just add the
433 // individual plots max y-value since that
434 // would in most cases give to large y-value.
435 $y=$this->plots[0]->coords[0][$i];
436 for( $j = 1; $j < $this->nbrplots; $j++ ) {
437 $y += $this->plots[ $j ]->coords[0][$i];
438 }
439 $ymax[$i] = $y;
440 }
441 $ymax = max($ymax);
442
443 // Bar always start at baseline
444 if( $ymax <= $this->ybase )
445 $ymax = $this->ybase;
446 return array($xmax,$ymax);
447 }
448
449 function Min() {
450 $nmax=0;
451 list($xmin,$ysetmin) = $this->plots[0]->Min();
452 for($i=0; $i<count($this->plots); ++$i) {
453 $n = count($this->plots[$i]->coords[0]);
454 $nmax = max($nmax,$n);
455 list($x,$y) = $this->plots[$i]->Min();
456 $xmin = Min($xmin,$x);
457 $ysetmin = Min($y,$ysetmin);
458 }
459 for( $i = 0; $i < $nmax; $i++ ) {
460 // Get y-value for bar $i by adding the
461 // individual bars from all the plots added.
462 // It would be wrong to just add the
463 // individual plots max y-value since that
464 // would in most cases give to large y-value.
465 $y=$this->plots[0]->coords[0][$i];
466 for( $j = 1; $j < $this->nbrplots; $j++ ) {
467 $y += $this->plots[ $j ]->coords[0][$i];
468 }
469 $ymin[$i] = $y;
470 }
471 $ymin = Min($ysetmin,Min($ymin));
472 // Bar always start at baseline
473 if( $ymin >= $this->ybase )
474 $ymin = $this->ybase;
475 return array($xmin,$ymin);
476 }
477
478 // Stroke acc bar plot
479 function Stroke(&$img,&$xscale,&$yscale) {
480 $img->SetLineWeight($this->weight);
481 for($i=0; $i<$this->numpoints-1; $i++) {
482
483
484 $accy = 0;
485 $accy_neg = 0;
486 for($j=0; $j < $this->nbrplots; ++$j ) {
487
488 $img->SetColor($this->plots[$j]->color);
489
490 if ( $this->plots[$j]->coords[0][$i] >= 0) {
491 $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
492 $accyt=$yscale->Translate($accy);
493 $accy+=$this->plots[$j]->coords[0][$i];
494 }
495 if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) {
496 $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
497 $accyt=$yscale->Translate($accy_neg);
498 $accy_neg+=$this->plots[$j]->coords[0][$i];
499 }
500
501 $xt=$xscale->Translate($i);
502
503 if( $this->abswidth > -1 )
504 $abswidth=$this->abswidth;
505 else
506 $abswidth=round($this->width*$xscale->scale_factor,0);
507
508 $pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt);
509
510 if( $this->bar_shadow ) {
511 $ssh = $this->bar_shadow_hsize;
512 $ssv = $this->bar_shadow_vsize;
513
514 // We must also differ if we are a positive or negative bar.
515 if( $j === 0 ) {
516 // This gets extra complicated since we have to
517 // see all plots to see if we are negative. It could
518 // for example be that all plots are 0 until the very
519 // last one. We therefore need to save the initial setup
520 // for both the negative and positive case
521
522 // In case the final bar is positive
523 $sp[0]=$pts[6]+1; $sp[1]=$pts[7];
524 $sp[2]=$pts[6]+$ssh; $sp[3]=$pts[7]-$ssv;
525
526 // In case the final bar is negative
527 $nsp[0]=$pts[0]; $nsp[1]=$pts[1];
528 $nsp[2]=$pts[0]+$ssh; $nsp[3]=$pts[1]-$ssv;
529 $nsp[4]=$pts[6]+$ssh; $nsp[5]=$pts[7]-$ssv;
530 $nsp[10]=$pts[6]+1; $nsp[11]=$pts[7];
531 }
532
533 if( $j === $this->nbrplots-1 ) {
534 // If this is the last plot of the bar and
535 // the total value is larger than 0 then we
536 // add the shadow.
537 if( $accy > 0 ) {
538 $sp[4]=$pts[4]+$ssh; $sp[5]=$pts[5]-$ssv;
539 $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv;
540 $sp[8]=$pts[2]; $sp[9]=$pts[3]-1;
541 $sp[10]=$pts[4]+1; $sp[11]=$pts[5];
542 $img->PushColor($this->bar_shadow_color);
543 $img->FilledPolygon($sp,4);
544 $img->PopColor();
545 }
546 elseif( $accy_neg < 0 ) {
547 $nsp[6]=$pts[4]+$ssh; $nsp[7]=$pts[5]-$ssv;
548 $nsp[8]=$pts[4]+1; $nsp[9]=$pts[5];
549 $img->PushColor($this->bar_shadow_color);
550 $img->FilledPolygon($nsp,4);
551 $img->PopColor();
552 }
553 }
554 }
555
556 // If value is NULL or 0, then don't draw a bar at all
557 if ($this->plots[$j]->coords[0][$i] == 0 ) continue;
558
559 if( $this->plots[$j]->grad ) {
560 $grad = new Gradient($img);
561 $grad->FilledRectangle(
562 $pts[2],$pts[3],
563 $pts[6],$pts[7],
564 $this->plots[$j]->grad_fromcolor,
565 $this->plots[$j]->grad_tocolor,
566 $this->plots[$j]->grad_style);
567 } elseif ($this->plots[$j]->fill_color ) {
568 $img->SetColor($this->plots[$j]->fill_color);
569 $img->FilledPolygon($pts);
570 $img->SetColor($this->plots[$j]->color);
571 }
572
573
574 // CSIM array
575
576 if( $i < count($this->plots[$j]->csimtargets) ) {
577 // Create the client side image map
578 $rpts = $img->ArrRotate($pts);
579 $csimcoord=round($rpts[0]).", ".round($rpts[1]);
580 for( $k=1; $k < 4; ++$k){
581 $csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]);
582 }
583 $this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" ';
584 $this->csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\"";
585 if( !empty($this->plots[$j]->csimalts[$i]) ) {
586 $sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]);
587 $this->csimareas .= " alt=\"$sval\" title=\"$sval\" ";
588 }
589 $this->csimareas .= ">\n";
590 }
591
592 $pts[] = $pts[0];
593 $pts[] = $pts[1];
594 $img->Polygon($pts);
595 }
596
597 // Draw labels for each acc.bar
598
599 $x=$pts[2]+($pts[4]-$pts[2])/2;
600 $y=$yscale->Translate($accy);
601 if($this->bar_shadow) $x += $ssh;
602 $this->value->Stroke($img,$accy,$x,$y);
603
604 $accy = 0;
605 $accy_neg = 0;
606 for($j=0; $j<$this->nbrplots; ++$j ) {
607 if ($this->plots[$j]->coords[0][$i] > 0) {
608 $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
609 $accyt=$yscale->Translate($accy);
610 $y = $accyt-($accyt-$yt)/2;
611 $accy+=$this->plots[$j]->coords[0][$i];
612 } else {
613 $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
614 $accyt=$yscale->Translate($accy_neg);
615 $y=0;
616 $accy_neg+=$this->plots[$j]->coords[0][$i];
617 }
618 $this->plots[$j]->value->SetAlign("center","center");
619 $this->plots[$j]->value->SetMargin(0);
620 $this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],$x,$y);
621 }
622
623 }
624 return true;
625 }
626} // Class
627
628/* EOF */
629?>
Note: See TracBrowser for help on using the repository browser.