3 pChart - a PHP class to build charts!
\r
4 Copyright (C) 2008 Jean-Damien POGOLOTTI
\r
5 Version 1.27b last updated on 08/21/08
\r
7 http://pchart.sourceforge.net
\r
9 This program is free software: you can redistribute it and/or modify
\r
10 it under the terms of the GNU General Public License as published by
\r
11 the Free Software Foundation, either version 1,2,3 of the License, or
\r
12 (at your option) any later version.
\r
14 This program is distributed in the hope that it will be useful,
\r
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 GNU General Public License for more details.
\r
19 You should have received a copy of the GNU General Public License
\r
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
\r
22 Class initialisation :
\r
23 pChart($XSize,$YSize)
\r
25 drawBackground($R,$G,$B)
\r
26 drawRectangle($X1,$Y1,$X2,$Y2,$R,$G,$B)
\r
27 drawFilledRectangle($X1,$Y1,$X2,$Y2,$R,$G,$B,$DrawBorder=TRUE,$Alpha=100)
\r
28 drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$R,$G,$B)
\r
29 drawFilledRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$R,$G,$B)
\r
30 drawCircle($Xc,$Yc,$Height,$R,$G,$B,$Width=0)
\r
31 drawFilledCircle($Xc,$Yc,$Height,$R,$G,$B,$Width=0)
\r
32 drawEllipse($Xc,$Yc,$Height,$Width,$R,$G,$B)
\r
33 drawFilledEllipse($Xc,$Yc,$Height,$Width,$R,$G,$B)
\r
34 drawLine($X1,$Y1,$X2,$Y2,$R,$G,$B,$GraphFunction=FALSE)
\r
35 drawDottedLine($X1,$Y1,$X2,$Y2,$DotSize,$R,$G,$B)
\r
36 drawAlphaPixel($X,$Y,$Alpha,$R,$G,$B)
\r
37 drawFromPNG($FileName,$X,$Y,$Alpha=100)
\r
38 drawFromGIF($FileName,$X,$Y,$Alpha=100)
\r
39 drawFromJPG($FileName,$X,$Y,$Alpha=100)
\r
40 Graph setup methods :
\r
41 addBorder($Width=3,$R=0,$G=0,$B=0)
\r
42 drawGraphArea($R,$G,$B,$Stripe=FALSE)
\r
43 drawScale(&$Data,&$DataDescription,$ScaleMode,$R,$G,$B,$DrawTicks=TRUE,$Angle=0,$Decimals=1,$WithMargin=FALSE,$SkipLabels=1)
\r
44 drawGrid($LineWidth,$Mosaic=TRUE,$R=220,$G=220,$B=220,$Alpha=100)
\r
45 drawLegend($XPos,$YPos,&$DataDescription,$R,$G,$B,$Rs=-1,$Gs=-1,$Bs=-1)
\r
46 drawPieLegend($XPos,$YPos,$Data,$DataDescription,$R,$G,$B)
\r
47 drawTitle($XPos,$YPos,$Value,$R,$G,$B,$XPos2=-1,$YPos2=-1)
\r
48 drawTreshold($Value,$R,$G,$B,$ShowLabel=FALSE,$ShowOnRight=FALSE,$TickWidth=4,$FreeText=NULL)
\r
49 drawArea(&$Data,$Serie1,$Serie2,$R,$G,$B,$Alpha = 50)
\r
50 drawRadarAxis(&$Data,&$DataDescription,$Mosaic=TRUE,$BorderOffset=10,$A_R=60,$A_G=60,$A_B=60,$S_R=200,$S_G=200,$S_B=200,$MaxValue=-1)
\r
51 drawGraphAreaGradient($R,$G,$B,$Decay,$Target=TARGET_GRAPHAREA)
\r
52 drawTextBox($X1,$Y1,$X2,$Y2,$Text,$Angle=0,$R=255,$G=255,$B=255,$Align=ALIGN_LEFT,$Shadow=TRUE,$BgR=-1,$BgG=-1,$BgB=-1,$Alpha=100)
\r
53 getLegendBoxSize($DataDescription)
\r
54 loadColorPalette($FileName,$Delimiter=",")
\r
55 reportWarnings($Interface="CLI")
\r
56 setGraphArea($X1,$Y1,$X2,$Y2)
\r
57 setFixedScale($VMin,$VMax)
\r
58 setLabel(&$Data,&$DataDescription,$SerieName,$ValueName,$Caption,$R=210,$G=210,$B=210)
\r
59 setColorPalette($ID,$R,$G,$B)
\r
60 setDateFormat($Format)
\r
61 setFontProperties($FontName,$FontSize)
\r
62 setLineStyle($Width=1,$DotSize=0)
\r
63 setFixedScale($VMin,$VMax,$Divisions=5)
\r
64 writeValues(&$Data,&$DataDescription,$Series)
\r
66 drawPlotGraph(&$Data,&$DataDescription,$BigRadius=5,$SmallRadius=2,$R2=-1,$G2=-1,$B2=-1)
\r
67 drawLineGraph(&$Data,&$DataDescription,$SerieName="")
\r
68 drawFilledLineGraph(&$Data,&$DataDescription,$Alpha=100,$AroundZero=FALSE)
\r
69 drawCubicCurve(&$Data,&$DataDescription,$Accuracy=.1,$SerieName="")
\r
70 drawFilledCubicCurve(&$Data,&$DataDescription,$Accuracy=.1,$Alpha=100,$AroundZero=FALSE)
\r
71 drawOverlayBarGraph(&$Data,&$DataDescription,$Alpha=50)
\r
72 drawBarGraph(&$Data,&$DataDescription,$Shadow=FALSE)
\r
73 drawStackedBarGraph(&$Data,&$DataDescription,$Alpha=50)
\r
74 drawLimitsGraph(&$Data,&$DataDescription,$R=0,$G=0,$B=0)
\r
75 drawRadar(&$Data,&$DataDescription,$BorderOffset=10,$MaxValue=-1)
\r
76 drawFilledRadar(&$Data,&$DataDescription,$Alpha=50,$BorderOffset=10,$MaxValue=-1)
\r
77 drawBasicPieGraph(&$Data,&$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$R=255,$G=255,$B=255,$Decimals=0)
\r
78 drawFlatPieGraph(&$Data,&$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$SpliceDistance=0,$Decimals = 0)
\r
79 drawPieGraph(&$Data,&$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$EnhanceColors=TRUE,$Skew=60,$SpliceHeight=20,$SpliceDistance=0,$Decimals=0)
\r
81 setImageMap($Mode=TRUE,$GraphID="MyGraph")
\r
82 getImageMap($MapName,$Flush=TRUE)
\r
87 /* Andrew@DeFaria.com: Empty array for imageftbbox call
\r
88 See http://bugs.php.net/bug.php?id=26309
\r
90 /* Declare some script wide constants */
\r
91 define("SCALE_NORMAL",1);
\r
92 define("SCALE_ADDALL",2);
\r
93 define("SCALE_START0",3);
\r
94 define("SCALE_ADDALLSTART0",4);
\r
95 define("PIE_PERCENTAGE", 1);
\r
96 define("PIE_LABELS",2);
\r
97 define("PIE_NOLABEL",3);
\r
98 define("TARGET_GRAPHAREA",1);
\r
99 define("TARGET_BACKGROUND",2);
\r
100 define("ALIGN_TOP_LEFT",1);
\r
101 define("ALIGN_TOP_CENTER",2);
\r
102 define("ALIGN_TOP_RIGHT",3);
\r
103 define("ALIGN_LEFT",4);
\r
104 define("ALIGN_CENTER",5);
\r
105 define("ALIGN_RIGHT",6);
\r
106 define("ALIGN_BOTTOM_LEFT",7);
\r
107 define("ALIGN_BOTTOM_CENTER",8);
\r
108 define("ALIGN_BOTTOM_RIGHT",9);
\r
110 /* pChart class definition */
\r
113 /* Palettes definition */
\r
114 var $Palette = array("0"=>array("R"=>188,"G"=>224,"B"=>46),
\r
115 "1"=>array("R"=>224,"G"=>100,"B"=>46),
\r
116 "2"=>array("R"=>224,"G"=>214,"B"=>46),
\r
117 "3"=>array("R"=>46,"G"=>151,"B"=>224),
\r
118 "4"=>array("R"=>176,"G"=>46,"B"=>224),
\r
119 "5"=>array("R"=>224,"G"=>46,"B"=>117),
\r
120 "6"=>array("R"=>92,"G"=>224,"B"=>46),
\r
121 "7"=>array("R"=>224,"G"=>176,"B"=>46));
\r
123 /* Some static vars used in the class */
\r
126 var $Picture = NULL;
\r
127 var $ImageMap = NULL;
\r
129 /* Error management */
\r
130 var $ErrorReporting = FALSE;
\r
131 var $ErrorInterface = "CLI";
\r
132 var $Errors = NULL;
\r
133 var $ErrorFontName = "Fonts/pf_arma_five.ttf";
\r
134 var $ErrorFontSize = 6;
\r
136 /* vars related to the graphing area */
\r
137 var $GArea_X1 = NULL;
\r
138 var $GArea_Y1 = NULL;
\r
139 var $GArea_X2 = NULL;
\r
140 var $GArea_Y2 = NULL;
\r
141 var $GAreaXOffset = NULL;
\r
144 var $Divisions = NULL;
\r
145 var $DivisionHeight = NULL;
\r
146 var $DivisionCount = NULL;
\r
147 var $DivisionRatio = NULL;
\r
148 var $DivisionWidth = NULL;
\r
149 var $DataCount = NULL;
\r
151 /* Text format related vars */
\r
152 var $FontName = NULL;
\r
153 var $FontSize = NULL;
\r
154 var $DateFormat = "d/m/Y";
\r
156 /* Lines format related vars */
\r
157 var $LineWidth = 1;
\r
158 var $LineDotSize = 0;
\r
160 /* Layer related vars */
\r
161 var $Layers = NULL;
\r
163 /* Set antialias quality : 0 is maximum, 100 minimum*/
\r
164 var $AntialiasQuality = 10;
\r
166 /* Image Map settings */
\r
167 var $BuildMap = FALSE;
\r
168 var $MapFunction = NULL;
\r
169 var $tmpFolder = "tmp/";
\r
172 /* This function create the background picture */
\r
173 function pChart($XSize,$YSize)
\r
175 $this->XSize = $XSize;
\r
176 $this->YSize = $YSize;
\r
177 $this->Picture = imagecreatetruecolor($XSize,$YSize);
\r
179 $C_White = imagecolorallocate($this->Picture,255,255,255);
\r
180 imagefilledrectangle($this->Picture,0,0,$XSize,$YSize,$C_White);
\r
181 imagecolortransparent($this->Picture,$C_White);
\r
183 $this->setFontProperties("tahoma.ttf",8);
\r
186 /* Set if warnings should be reported */
\r
187 function reportWarnings($Interface="CLI")
\r
189 $this->ErrorReporting = TRUE;
\r
190 $this->ErrorInterface = $Interface;
\r
193 /* Set the font properties */
\r
194 function setFontProperties($FontName,$FontSize)
\r
196 $this->FontName = $FontName;
\r
197 $this->FontSize = $FontSize;
\r
200 /* Set Palette color */
\r
201 function setColorPalette($ID,$R,$G,$B)
\r
203 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
204 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
205 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
207 $this->Palette[$ID]["R"] = $R;
\r
208 $this->Palette[$ID]["G"] = $G;
\r
209 $this->Palette[$ID]["B"] = $B;
\r
212 /* Load Color Palette from file */
\r
213 function loadColorPalette($FileName,$Delimiter=",")
\r
215 $handle = @fopen($FileName,"r");
\r
219 while (!feof($handle))
\r
221 $buffer = fgets($handle, 4096);
\r
222 $buffer = str_replace(chr(10),"",$buffer);
\r
223 $buffer = str_replace(chr(13),"",$buffer);
\r
224 $Values = split($Delimiter,$buffer);
\r
225 if ( count($Values) == 3 )
\r
227 $this->Palette[$ColorID]["R"] = $Values[0];
\r
228 $this->Palette[$ColorID]["G"] = $Values[1];
\r
229 $this->Palette[$ColorID]["B"] = $Values[2];
\r
236 /* Set line style */
\r
237 function setLineStyle($Width=1,$DotSize=0)
\r
239 $this->LineWidth = $Width;
\r
240 $this->LineDotSize = $DotSize;
\r
243 /* Set the graph area location */
\r
244 function setGraphArea($X1,$Y1,$X2,$Y2)
\r
246 $this->GArea_X1 = $X1;
\r
247 $this->GArea_Y1 = $Y1;
\r
248 $this->GArea_X2 = $X2;
\r
249 $this->GArea_Y2 = $Y2;
\r
252 /* Prepare the graph area */
\r
253 function drawGraphArea($R,$G,$B,$Stripe=FALSE)
\r
255 $this->drawFilledRectangle($this->GArea_X1,$this->GArea_Y1,$this->GArea_X2,$this->GArea_Y2,$R,$G,$B,FALSE);
\r
256 $this->drawRectangle($this->GArea_X1,$this->GArea_Y1,$this->GArea_X2,$this->GArea_Y2,$R-40,$G-40,$B-40);
\r
260 $R2 = $R-15; if ( $R2 < 0 ) { $R2 = 0; }
\r
261 $G2 = $R-15; if ( $G2 < 0 ) { $G2 = 0; }
\r
262 $B2 = $R-15; if ( $B2 < 0 ) { $B2 = 0; }
\r
264 $LineColor = imagecolorallocate($this->Picture,$R2,$G2,$B2);
\r
265 $SkewWidth = $this->GArea_Y2-$this->GArea_Y1-1;
\r
267 for($i=$this->GArea_X1-$SkewWidth;$i<=$this->GArea_X2;$i=$i+4)
\r
269 $X1 = $i; $Y1 = $this->GArea_Y2;
\r
270 $X2 = $i+$SkewWidth; $Y2 = $this->GArea_Y1;
\r
273 if ( $X1 < $this->GArea_X1 )
\r
274 { $X1 = $this->GArea_X1; $Y1 = $this->GArea_Y1 + $X2 - $this->GArea_X1 + 1; }
\r
276 if ( $X2 >= $this->GArea_X2 )
\r
277 { $Y2 = $this->GArea_Y1 + $X2 - $this->GArea_X2 +1; $X2 = $this->GArea_X2 - 1; }
\r
278 // * Fixed in 1.27 * { $X2 = $this->GArea_X2 - 1; $Y2 = $this->GArea_Y2 - ($this->GArea_X2 - $X1); }
\r
280 imageline($this->Picture,$X1,$Y1,$X2,$Y2+1,$LineColor);
\r
285 /* Allow you to fix the scale, use this to bypass the automatic scaling */
\r
286 function setFixedScale($VMin,$VMax,$Divisions=5)
\r
288 $this->VMin = $VMin;
\r
289 $this->VMax = $VMax;
\r
290 $this->Divisions = $Divisions;
\r
293 /* Compute and draw the scale */
\r
294 function drawScale(&$Data,&$DataDescription,$ScaleMode,$R,$G,$B,$DrawTicks=TRUE,$Angle=0,$Decimals=1,$WithMargin=FALSE,$SkipLabels=1)
\r
296 /* Validate the Data and DataDescription array */
\r
297 $this->validateData("drawScale",$Data);
\r
299 $C_TextColor = imagecolorallocate($this->Picture,$R,$G,$B);
\r
301 $this->drawLine($this->GArea_X1,$this->GArea_Y1,$this->GArea_X1,$this->GArea_Y2,$R,$G,$B);
\r
302 $this->drawLine($this->GArea_X1,$this->GArea_Y2,$this->GArea_X2,$this->GArea_Y2,$R,$G,$B);
\r
304 if ( $this->VMin == NULL && $this->VMax == NULL)
\r
306 if (isset($DataDescription["Values"][0]))
\r
308 $this->VMin = $Data[0][$DataDescription["Values"][0]];
\r
309 $this->VMax = $Data[0][$DataDescription["Values"][0]];
\r
311 else { $this->VMin = 2147483647; $this->VMax = -2147483647; }
\r
313 /* Compute Min and Max values */
\r
314 if ( $ScaleMode == SCALE_NORMAL || $ScaleMode == SCALE_START0 )
\r
316 if ( $ScaleMode == SCALE_START0 ) { $this->VMin = 0; }
\r
318 foreach ( $Data as $Key => $Values )
\r
320 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
322 if (isset($Data[$Key][$ColName]))
\r
324 $Value = $Data[$Key][$ColName];
\r
326 if ( is_numeric($Value) )
\r
328 if ( $this->VMax < $Value) { $this->VMax = $Value; }
\r
329 if ( $this->VMin > $Value) { $this->VMin = $Value; }
\r
335 elseif ( $ScaleMode == SCALE_ADDALL || $ScaleMode == SCALE_ADDALLSTART0 ) /* Experimental */
\r
337 if ( $ScaleMode == SCALE_ADDALLSTART0 ) { $this->VMin = 0; }
\r
339 foreach ( $Data as $Key => $Values )
\r
342 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
344 if (isset($Data[$Key][$ColName]))
\r
346 $Value = $Data[$Key][$ColName];
\r
347 if ( is_numeric($Value) )
\r
351 if ( $this->VMax < $Sum) { $this->VMax = $Sum; }
\r
352 if ( $this->VMin > $Sum) { $this->VMin = $Sum; }
\r
356 $DataRange = $this->VMax - $this->VMin;
\r
357 if ( $DataRange == 0 ) { $DataRange = .1; }
\r
359 /* Compute automatic scaling */
\r
360 $ScaleOk = FALSE; $Factor = 1;
\r
361 $MinDivHeight = 25; $MaxDivs = ($this->GArea_Y2 - $this->GArea_Y1) / $MinDivHeight;
\r
366 $Scale1 = ( $this->VMax - $this->VMin ) / $Factor;
\r
367 $Scale2 = ( $this->VMax - $this->VMin ) / $Factor / 2;
\r
368 $Scale4 = ( $this->VMax - $this->VMin ) / $Factor / 4;
\r
370 if ( $Scale1 > 1 && $Scale1 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $Divisions = floor($Scale1); $Scale = 1;}
\r
371 if ( $Scale2 > 1 && $Scale2 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $Divisions = floor($Scale2); $Scale = 2;}
\r
374 if ( $Scale2 > 1 ) { $Factor = $Factor * 10; }
\r
375 if ( $Scale2 < 1 ) { $Factor = $Factor / 10; }
\r
379 if ( floor($this->VMax / $Scale / $Factor) != $this->VMax / $Scale / $Factor)
\r
381 $GridID = floor ( $this->VMax / $Scale / $Factor) + 1;
\r
382 $this->VMax = $GridID * $Scale * $Factor;
\r
386 if ( floor($this->VMin / $Scale / $Factor) != $this->VMin / $Scale / $Factor)
\r
388 $GridID = floor( $this->VMin / $Scale / $Factor);
\r
389 $this->VMin = $GridID * $Scale * $Factor;
\r
393 else /* Can occurs for small graphs */
\r
396 if ( !isset($Divisions) )
\r
399 if ($Scale == 1 && $Divisions%2 == 1)
\r
403 $Divisions = $this->Divisions;
\r
405 $this->DivisionCount = $Divisions;
\r
407 $DataRange = $this->VMax - $this->VMin;
\r
408 if ( $DataRange == 0 ) { $DataRange = .1; }
\r
410 $this->DivisionHeight = ( $this->GArea_Y2 - $this->GArea_Y1 ) / $Divisions;
\r
411 $this->DivisionRatio = ( $this->GArea_Y2 - $this->GArea_Y1 ) / $DataRange;
\r
413 $this->GAreaXOffset = 0;
\r
414 if ( count($Data) > 1 )
\r
416 if ( $WithMargin == FALSE )
\r
417 $this->DivisionWidth = ( $this->GArea_X2 - $this->GArea_X1 ) / (count($Data)-1);
\r
420 $this->DivisionWidth = ( $this->GArea_X2 - $this->GArea_X1 ) / (count($Data));
\r
421 $this->GAreaXOffset = $this->DivisionWidth / 2;
\r
426 $this->DivisionWidth = $this->GArea_X2 - $this->GArea_X1;
\r
427 $this->GAreaXOffset = $this->DivisionWidth / 2;
\r
430 $this->DataCount = count($Data);
\r
432 if ( $DrawTicks == FALSE )
\r
435 $YPos = $this->GArea_Y2; $XMin = NULL;
\r
436 for($i=1;$i<=$Divisions+1;$i++)
\r
438 $this->drawLine($this->GArea_X1,$YPos,$this->GArea_X1-5,$YPos,$R,$G,$B);
\r
439 $Value = $this->VMin + ($i-1) * (( $this->VMax - $this->VMin ) / $Divisions);
\r
440 $Value = round($Value * pow(10,$Decimals)) / pow(10,$Decimals);
\r
441 if ( $DataDescription["Format"]["Y"] == "number" )
\r
442 $Value = $Value.$DataDescription["Unit"]["Y"];
\r
443 if ( $DataDescription["Format"]["Y"] == "time" )
\r
444 $Value = $this->ToTime($Value);
\r
445 if ( $DataDescription["Format"]["Y"] == "date" )
\r
446 $Value = $this->ToDate($Value);
\r
447 if ( $DataDescription["Format"]["Y"] == "metric" )
\r
448 $Value = $this->ToMetric($Value);
\r
450 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value,$bogus);
\r
451 $TextWidth = $Position[2]-$Position[0];
\r
452 imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X1-10-$TextWidth,$YPos+($this->FontSize/2),$C_TextColor,$this->FontName,$Value);
\r
454 if ( $XMin > $this->GArea_X1-10-$TextWidth || $XMin == NULL ) { $XMin = $this->GArea_X1-10-$TextWidth; }
\r
456 $YPos = $YPos - $this->DivisionHeight;
\r
459 /* Write the Y Axis caption if set */
\r
460 if ( isset($DataDescription["Axis"]["Y"]) )
\r
462 $Position = imageftbbox($this->FontSize,90,$this->FontName,$DataDescription["Axis"]["Y"],$bogus);
\r
463 $TextHeight = abs($Position[1])+abs($Position[3]);
\r
464 $TextTop = (($this->GArea_Y2 - $this->GArea_Y1) / 2) + $this->GArea_Y1 + ($TextHeight/2);
\r
465 imagettftext($this->Picture,$this->FontSize,90,$XMin-$this->FontSize,$TextTop,$C_TextColor,$this->FontName,$DataDescription["Axis"]["Y"]);
\r
468 /* Horizontal Axis */
\r
469 $XPos = $this->GArea_X1 + $this->GAreaXOffset;
\r
470 $ID = 1; $YMax = NULL;
\r
471 foreach ( $Data as $Key => $Values )
\r
473 if ( $ID % $SkipLabels == 0 )
\r
475 $this->drawLine(floor($XPos),$this->GArea_Y2,floor($XPos),$this->GArea_Y2+5,$R,$G,$B);
\r
476 $Value = $Data[$Key][$DataDescription["Position"]];
\r
477 if ( $DataDescription["Format"]["X"] == "number" )
\r
478 $Value = $Value.$DataDescription["Unit"]["X"];
\r
479 if ( $DataDescription["Format"]["X"] == "time" )
\r
480 $Value = $this->ToTime($Value);
\r
481 if ( $DataDescription["Format"]["X"] == "date" )
\r
482 $Value = $this->ToDate($Value);
\r
483 if ( $DataDescription["Format"]["X"] == "metric" )
\r
484 $Value = $this->ToMetric($Value);
\r
486 $Position = imageftbbox($this->FontSize,$Angle,$this->FontName,$Value,$bogus);
\r
487 $TextWidth = abs($Position[2])+abs($Position[0]);
\r
488 $TextHeight = abs($Position[1])+abs($Position[3]);
\r
492 $YPos = $this->GArea_Y2+18;
\r
493 imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)-floor($TextWidth/2),$YPos,$C_TextColor,$this->FontName,$Value);
\r
497 $YPos = $this->GArea_Y2+10+$TextHeight;
\r
498 if ( $Angle <= 90 )
\r
499 imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)-$TextWidth+5,$YPos,$C_TextColor,$this->FontName,$Value);
\r
501 imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)+$TextWidth+5,$YPos,$C_TextColor,$this->FontName,$Value);
\r
503 if ( $YMax < $YPos || $YMax == NULL ) { $YMax = $YPos; }
\r
506 $XPos = $XPos + $this->DivisionWidth;
\r
510 /* Write the X Axis caption if set */
\r
511 if ( isset($DataDescription["Axis"]["X"]) )
\r
513 $Position = imageftbbox($this->FontSize,90,$this->FontName,$DataDescription["Axis"]["X"],$bogus);
\r
514 $TextWidth = abs($Position[2])+abs($Position[0]);
\r
515 $TextLeft = (($this->GArea_X2 - $this->GArea_X1) / 2) + $this->GArea_X1 + ($TextWidth/2);
\r
516 imagettftext($this->Picture,$this->FontSize,0,$TextLeft,$YMax+$this->FontSize+5,$C_TextColor,$this->FontName,$DataDescription["Axis"]["X"]);
\r
520 /* Compute and draw the scale */
\r
521 function drawGrid($LineWidth,$Mosaic=TRUE,$R=220,$G=220,$B=220,$Alpha=100)
\r
526 $LayerWidth = $this->GArea_X2-$this->GArea_X1;
\r
527 $LayerHeight = $this->GArea_Y2-$this->GArea_Y1;
\r
529 $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight);
\r
530 $C_White = imagecolorallocate($this->Layers[0],255,255,255);
\r
531 imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White);
\r
532 imagecolortransparent($this->Layers[0],$C_White);
\r
534 $C_Rectangle = imagecolorallocate($this->Layers[0],250,250,250);
\r
536 $YPos = $LayerHeight; //$this->GArea_Y2-1;
\r
538 for($i=0;$i<=$this->DivisionCount;$i++)
\r
541 $YPos = $YPos - $this->DivisionHeight;
\r
543 if ( $YPos <= 0 ) { $YPos = 1; }
\r
547 imagefilledrectangle($this->Layers[0],1,$YPos,$LayerWidth-1,$LastY,$C_Rectangle);
\r
550 imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha);
\r
551 imagedestroy($this->Layers[0]);
\r
554 /* Horizontal lines */
\r
555 $YPos = $this->GArea_Y2 - $this->DivisionHeight;
\r
556 for($i=1;$i<=$this->DivisionCount;$i++)
\r
558 if ( $YPos > $this->GArea_Y1 && $YPos < $this->GArea_Y2 )
\r
559 $this->drawDottedLine($this->GArea_X1,$YPos,$this->GArea_X2,$YPos,$LineWidth,$R,$G,$B);
\r
561 $YPos = $YPos - $this->DivisionHeight;
\r
564 /* Vertical lines */
\r
565 if ( $this->GAreaXOffset == 0 )
\r
566 { $XPos = $this->GArea_X1 + $this->DivisionWidth + $this->GAreaXOffset; $ColCount = $this->DataCount-2; }
\r
568 { $XPos = $this->GArea_X1 + $this->GAreaXOffset; $ColCount = $this->DataCount; }
\r
570 for($i=1;$i<=$ColCount;$i++)
\r
572 if ( $XPos > $this->GArea_X1 && $XPos < $this->GArea_X2 )
\r
573 $this->drawDottedLine(floor($XPos),$this->GArea_Y1,floor($XPos),$this->GArea_Y2,$LineWidth,$R,$G,$B);
\r
574 $XPos = $XPos + $this->DivisionWidth;
\r
578 /* retrieve the legends size */
\r
579 function getLegendBoxSize($DataDescription)
\r
581 if ( !isset($DataDescription["Description"]) )
\r
584 /* <-10->[8]<-4->Text<-10-> */
\r
585 $MaxWidth = 0; $MaxHeight = 8;
\r
586 foreach($DataDescription["Description"] as $Key => $Value)
\r
588 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value,$bogus);
\r
589 $TextWidth = $Position[2]-$Position[0];
\r
590 $TextHeight = $Position[1]-$Position[7];
\r
591 if ( $TextWidth > $MaxWidth) { $MaxWidth = $TextWidth; }
\r
592 $MaxHeight = $MaxHeight + $TextHeight + 4;
\r
594 $MaxHeight = $MaxHeight - 3;
\r
595 $MaxWidth = $MaxWidth + 32;
\r
597 return(array($MaxWidth,$MaxHeight));
\r
600 /* Draw the data legends */
\r
601 function drawLegend($XPos,$YPos,&$DataDescription,$R,$G,$B,$Rs=-1,$Gs=-1,$Bs=-1)
\r
603 /* Validate the Data and DataDescription array */
\r
604 $this->validateDataDescription("drawLegend",$DataDescription);
\r
606 if ( !isset($DataDescription["Description"]) )
\r
609 $C_TextColor = imagecolorallocate($this->Picture,0,0,0);
\r
611 /* <-10->[8]<-4->Text<-10-> */
\r
612 $MaxWidth = 0; $MaxHeight = 8;
\r
613 foreach($DataDescription["Description"] as $Key => $Value)
\r
615 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value,$bogus);
\r
616 $TextWidth = $Position[2]-$Position[0];
\r
617 $TextHeight = $Position[1]-$Position[7];
\r
618 if ( $TextWidth > $MaxWidth) { $MaxWidth = $TextWidth; }
\r
619 $MaxHeight = $MaxHeight + $TextHeight + 4;
\r
621 $MaxHeight = $MaxHeight - 5;
\r
622 $MaxWidth = $MaxWidth + 32;
\r
624 if ( $Rs == -1 || $Gs == -1 || $Bs == -1 )
\r
625 { $Rs = $R-30; $Gs = $G-30; $Bs = $B-30; }
\r
627 $this->drawFilledRoundedRectangle($XPos+1,$YPos+1,$XPos+$MaxWidth+1,$YPos+$MaxHeight+1,5,$Rs,$Gs,$Bs);
\r
628 $this->drawFilledRoundedRectangle($XPos,$YPos,$XPos+$MaxWidth,$YPos+$MaxHeight,5,$R,$G,$B);
\r
630 $YOffset = 4 + $this->FontSize; $ID = 0;
\r
631 foreach($DataDescription["Description"] as $Key => $Value)
\r
633 $this->drawFilledRoundedRectangle($XPos+10,$YPos+$YOffset-4,$XPos+14,$YPos+$YOffset-4,2,$this->Palette[$ID]["R"],$this->Palette[$ID]["G"],$this->Palette[$ID]["B"]);
\r
634 imagettftext($this->Picture,$this->FontSize,0,$XPos+22,$YPos+$YOffset,$C_TextColor,$this->FontName,$Value);
\r
636 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value,$bogus);
\r
637 $TextHeight = $Position[1]-$Position[7];
\r
639 $YOffset = $YOffset + $TextHeight + 4;
\r
644 /* Draw the data legends */
\r
645 function drawPieLegend($XPos,$YPos,&$Data,&$DataDescription,$R,$G,$B)
\r
647 /* Validate the Data and DataDescription array */
\r
648 $this->validateDataDescription("drawPieLegend",$DataDescription,FALSE);
\r
649 $this->validateData("drawPieLegend",$Data);
\r
651 if ( !isset($DataDescription["Position"]) )
\r
654 $C_TextColor = imagecolorallocate($this->Picture,0,0,0);
\r
656 /* <-10->[8]<-4->Text<-10-> */
\r
657 $MaxWidth = 0; $MaxHeight = 8;
\r
658 foreach($Data as $Key => $Value)
\r
660 $Value2 = $Value[$DataDescription["Position"]];
\r
661 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value2,$bogus);
\r
662 $TextWidth = $Position[2]-$Position[0];
\r
663 $TextHeight = $Position[1]-$Position[7];
\r
664 if ( $TextWidth > $MaxWidth) { $MaxWidth = $TextWidth; }
\r
666 $MaxHeight = $MaxHeight + $TextHeight + 4;
\r
668 $MaxHeight = $MaxHeight - 3;
\r
669 $MaxWidth = $MaxWidth + 32;
\r
671 $this->drawFilledRoundedRectangle($XPos+1,$YPos+1,$XPos+$MaxWidth+1,$YPos+$MaxHeight+1,5,$R-30,$G-30,$B-30);
\r
672 $this->drawFilledRoundedRectangle($XPos,$YPos,$XPos+$MaxWidth,$YPos+$MaxHeight,5,$R,$G,$B);
\r
674 $YOffset = 4 + $this->FontSize; $ID = 0;
\r
675 foreach($Data as $Key => $Value)
\r
677 $Value2 = $Value[$DataDescription["Position"]];
\r
678 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value2,$bogus);
\r
679 $TextHeight = $Position[1]-$Position[7];
\r
680 $this->drawFilledRectangle($XPos+10,$YPos+$YOffset-6,$XPos+14,$YPos+$YOffset-2,$this->Palette[$ID]["R"],$this->Palette[$ID]["G"],$this->Palette[$ID]["B"]);
\r
682 imagettftext($this->Picture,$this->FontSize,0,$XPos+22,$YPos+$YOffset,$C_TextColor,$this->FontName,$Value2);
\r
683 $YOffset = $YOffset + $TextHeight + 4;
\r
688 /* Draw the graph title */
\r
689 function drawTitle($XPos,$YPos,$Value,$R,$G,$B,$XPos2 = -1, $YPos2 = -1)
\r
691 $C_TextColor = imagecolorallocate($this->Picture,$R,$G,$B);
\r
693 if ( $XPos2 != -1 )
\r
695 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value,$bogus);
\r
696 $TextWidth = $Position[2]-$Position[0];
\r
697 $XPos = floor(( $XPos2 - $XPos - $TextWidth ) / 2 ) + $XPos;
\r
700 if ( $YPos2 != -1 )
\r
702 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value,$bogus);
\r
703 $TextHeight = $Position[5]-$Position[3];
\r
704 $YPos = floor(( $YPos2 - $YPos - $TextHeight ) / 2 ) + $YPos;
\r
707 imagettftext($this->Picture,$this->FontSize,0,$XPos,$YPos,$C_TextColor,$this->FontName,$Value);
\r
710 /* Draw a text box with text align & alpha properties */
\r
711 function drawTextBox($X1,$Y1,$X2,$Y2,$Text,$Angle=0,$R=255,$G=255,$B=255,$Align=ALIGN_LEFT,$Shadow=TRUE,$BgR=-1,$BgG=-1,$BgB=-1,$Alpha=100)
\r
713 $Position = imageftbbox($this->FontSize,$Angle,$this->FontName,$Text,$bogus);
\r
714 $TextWidth = $Position[2]-$Position[0];
\r
715 $TextHeight = $Position[5]-$Position[3];
\r
716 $AreaWidth = $X2 - $X1;
\r
717 $AreaHeight = $Y2 - $Y1;
\r
719 if ( $BgR != -1 && $BgG != -1 && $BgB != -1 )
\r
720 $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$BgR,$BgG,$BgB,FALSE,$Alpha);
\r
722 if ( $Align == ALIGN_TOP_LEFT ) { $X = $X1+1; $Y = $Y1+$this->FontSize+1; }
\r
723 if ( $Align == ALIGN_TOP_CENTER ) { $X = $X1+($AreaWidth/2)-($TextWidth/2); $Y = $Y1+$this->FontSize+1; }
\r
724 if ( $Align == ALIGN_TOP_RIGHT ) { $X = $X2-$TextWidth-1; $Y = $Y1+$this->FontSize+1; }
\r
725 if ( $Align == ALIGN_LEFT ) { $X = $X1+1; $Y = $Y1+($AreaHeight/2)-($TextHeight/2); }
\r
726 if ( $Align == ALIGN_CENTER ) { $X = $X1+($AreaWidth/2)-($TextWidth/2); $Y = $Y1+($AreaHeight/2)-($TextHeight/2); }
\r
727 if ( $Align == ALIGN_RIGHT ) { $X = $X2-$TextWidth-1; $Y = $Y1+($AreaHeight/2)-($TextHeight/2); }
\r
728 if ( $Align == ALIGN_BOTTOM_LEFT ) { $X = $X1+1; $Y = $Y2-1; }
\r
729 if ( $Align == ALIGN_BOTTOM_CENTER ) { $X = $X1+($AreaWidth/2)-($TextWidth/2); $Y = $Y2-1; }
\r
730 if ( $Align == ALIGN_BOTTOM_RIGHT ) { $X = $X2-$TextWidth-1; $Y = $Y2-1; }
\r
732 $C_TextColor = imagecolorallocate($this->Picture,$R,$G,$B);
\r
733 $C_ShadowColor = imagecolorallocate($this->Picture,0,0,0);
\r
735 imagettftext($this->Picture,$this->FontSize,$Angle,$X+1,$Y+1,$C_ShadowColor,$this->FontName,$Text);
\r
737 imagettftext($this->Picture,$this->FontSize,$Angle,$X,$Y,$C_TextColor,$this->FontName,$Text);
\r
740 /* Compute and draw the scale */
\r
741 function drawTreshold($Value,$R,$G,$B,$ShowLabel=FALSE,$ShowOnRight=FALSE,$TickWidth=4,$FreeText=NULL)
\r
743 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
744 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
745 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
747 $C_TextColor = imagecolorallocate($this->Picture,$R,$G,$B);
\r
748 $Y = $this->GArea_Y2 - ($Value - $this->VMin) * $this->DivisionRatio;
\r
750 if ( $Y <= $this->GArea_Y1 || $Y >= $this->GArea_Y2 )
\r
753 if ( $TickWidth == 0 )
\r
754 $this->drawLine($this->GArea_X1,$Y,$this->GArea_X2,$Y,$R,$G,$B);
\r
756 $this->drawDottedLine($this->GArea_X1,$Y,$this->GArea_X2,$Y,$TickWidth,$R,$G,$B);
\r
760 if ( $FreeText == NULL )
\r
761 { $Label = $Value; } else { $Label = $FreeText; }
\r
763 if ( $ShowOnRight )
\r
764 imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X2+2,$Y+($this->FontSize/2),$C_TextColor,$this->FontName,$Label);
\r
766 imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X1+2,$Y-($this->FontSize/2),$C_TextColor,$this->FontName,$Label);
\r
770 /* This function put a label on a specific point */
\r
771 function setLabel(&$Data,&$DataDescription,$SerieName,$ValueName,$Caption,$R=210,$G=210,$B=210)
\r
773 /* Validate the Data and DataDescription array */
\r
774 $this->validateDataDescription("setLabel",$DataDescription);
\r
775 $this->validateData("setLabel",$Data);
\r
777 $C_Label = imagecolorallocate($this->Picture,$R,$G,$B);
\r
778 $C_Shadow = imagecolorallocate($this->Picture,$R-30,$G-30,$B-30);
\r
779 $C_TextColor = imagecolorallocate($this->Picture,0,0,0);
\r
781 $Cp = 0; $Found = FALSE;
\r
782 foreach ( $Data as $Key => $Value )
\r
784 if ( $Data[$Key][$DataDescription["Position"]] == $ValueName )
\r
785 { $NumericalValue = $Data[$Key][$SerieName]; $Found = TRUE; }
\r
790 $XPos = $this->GArea_X1 + $this->GAreaXOffset + ( $this->DivisionWidth * $Cp ) + 2;
\r
791 $YPos = $this->GArea_Y2 - ($NumericalValue - $this->VMin) * $this->DivisionRatio;
\r
793 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Caption,$bogus);
\r
794 $TextHeight = $Position[3] - $Position[5];
\r
795 $TextWidth = $Position[2]-$Position[0];
\r
796 $TextOffset = floor($TextHeight/2);
\r
799 $Poly = array($XPos+1,$YPos+1,$XPos + 9,$YPos - $TextOffset,$XPos + 8,$YPos + $TextOffset + 2);
\r
800 imagefilledpolygon($this->Picture,$Poly,3,$C_Shadow);
\r
801 $this->drawLine($XPos,$YPos+1,$XPos + 9,$YPos - $TextOffset - 1,$R-30,$G-30,$B-30);
\r
802 $this->drawLine($XPos,$YPos+1,$XPos + 9,$YPos + $TextOffset + 3,$R-30,$G-30,$B-30);
\r
803 $this->drawFilledRectangle($XPos + 9,$YPos - $TextOffset,$XPos + 13 + $TextWidth,$YPos + $TextOffset + 2,$R-30,$G-30,$B-30);
\r
805 // Label background
\r
806 $Poly = array($XPos,$YPos,$XPos + 8,$YPos - $TextOffset - 1,$XPos + 8,$YPos + $TextOffset + 1);
\r
807 imagefilledpolygon($this->Picture,$Poly,3,$C_Label);
\r
808 $this->drawLine($XPos-1,$YPos,$XPos + 8,$YPos - $TextOffset - 2,$R,$G,$B);
\r
809 $this->drawLine($XPos-1,$YPos,$XPos + 8,$YPos + $TextOffset + 2,$R,$G,$B);
\r
810 $this->drawFilledRectangle($XPos + 8,$YPos - $TextOffset - 1,$XPos + 12 + $TextWidth,$YPos + $TextOffset + 1,$R,$G,$B);
\r
812 imagettftext($this->Picture,$this->FontSize,0,$XPos + 10,$YPos + $TextOffset,$C_TextColor,$this->FontName,$Caption);
\r
815 /* This function draw a line graph */
\r
816 function drawPlotGraph(&$Data,&$DataDescription,$BigRadius=5,$SmallRadius=2,$R2=-1,$G2=-1,$B2=-1)
\r
818 /* Validate the Data and DataDescription array */
\r
819 $this->validateDataDescription("drawPlotGraph",$DataDescription);
\r
820 $this->validateData("drawPlotGraph",$Data);
\r
824 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
827 foreach ( $DataDescription["Description"] as $keyI => $ValueI )
\r
828 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; }
\r
830 $R = $this->Palette[$ColorID]["R"];
\r
831 $G = $this->Palette[$ColorID]["G"];
\r
832 $B = $this->Palette[$ColorID]["B"];
\r
834 if ( isset($DataDescription["Symbol"][$ColName]) )
\r
836 //$Is_Alpha = ((ord ( file_get_contents ($DataDescription["Symbol"][$ColName], false, null, 25, 1)) & 6) & 4) == 4;
\r
837 $Is_Alpha = ((ord ( file_get_contents ($DataDescription["Symbol"][$ColName], false)) & 6) & 4) == 4;
\r
839 $Infos = getimagesize($DataDescription["Symbol"][$ColName]);
\r
840 $ImageWidth = $Infos[0];
\r
841 $ImageHeight = $Infos[1];
\r
842 $Symbol = imagecreatefromgif($DataDescription["Symbol"][$ColName]);
\r
845 $XPos = $this->GArea_X1 + $this->GAreaXOffset;
\r
846 $Hsize = round($BigRadius/2);
\r
847 foreach ( $Data as $Key => $Values )
\r
849 $Value = $Data[$Key][$ColName];
\r
850 $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio);
\r
852 /* Save point into the image map if option activated */
\r
853 if ( $this->BuildMap )
\r
854 $this->addToImageMap($XPos-$Hsize,$YPos-$Hsize,$XPos+1+$Hsize,$YPos+$Hsize+1,$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"Plot");
\r
856 if ( is_numeric($Value) )
\r
858 if ( !isset($DataDescription["Symbol"][$ColName]) )
\r
860 $this->drawFilledCircle($XPos+1,$YPos+1,$BigRadius,$R,$G,$B);
\r
862 if ( $R2 !=-1 && $G2 !=-1 && $B2 !=-1 )
\r
863 $this->drawFilledCircle($XPos+1,$YPos+1,$SmallRadius,$R2,$G2,$B2);
\r
866 $R = $this->Palette[$ColorID]["R"]-5; if ( $R < 0 ) { $R = 0; }
\r
867 $G = $this->Palette[$ColorID]["G"]-5; if ( $G < 0 ) { $G = 0; }
\r
868 $B = $this->Palette[$ColorID]["B"]-5; if ( $B < 0 ) { $B = 0; }
\r
870 $this->drawFilledCircle($XPos+1,$YPos+1,$SmallRadius,$R,$G,$B);
\r
875 imagecopymerge($this->Picture,$Symbol,$XPos+1-$ImageWidth/2,$YPos+1-$ImageHeight/2,0,0,$ImageWidth,$ImageHeight,100);
\r
879 $XPos = $XPos + $this->DivisionWidth;
\r
886 /* This function draw an area between two series */
\r
887 function drawArea(&$Data,$Serie1,$Serie2,$R,$G,$B,$Alpha = 50)
\r
889 /* Validate the Data and DataDescription array */
\r
890 $this->validateData("drawArea",$Data);
\r
892 $LayerWidth = $this->GArea_X2-$this->GArea_X1;
\r
893 $LayerHeight = $this->GArea_Y2-$this->GArea_Y1;
\r
895 $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight);
\r
896 $C_White = imagecolorallocate($this->Layers[0],255,255,255);
\r
897 imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White);
\r
898 imagecolortransparent($this->Layers[0],$C_White);
\r
900 $C_Graph = imagecolorallocate($this->Layers[0],$R,$G,$B);
\r
902 $XPos = $this->GAreaXOffset;
\r
904 foreach ( $Data as $Key => $Values )
\r
906 $Value1 = $Data[$Key][$Serie1];
\r
907 $Value2 = $Data[$Key][$Serie2];
\r
908 $YPos1 = $LayerHeight - (($Value1-$this->VMin) * $this->DivisionRatio);
\r
909 $YPos2 = $LayerHeight - (($Value2-$this->VMin) * $this->DivisionRatio);
\r
911 if ( $LastXPos != -1 )
\r
914 $Points[] = $LastXPos; $Points[] = $LastYPos1;
\r
915 $Points[] = $LastXPos; $Points[] = $LastYPos2;
\r
916 $Points[] = $XPos; $Points[] = $YPos2;
\r
917 $Points[] = $XPos; $Points[] = $YPos1;
\r
919 imagefilledpolygon($this->Layers[0],$Points,4,$C_Graph);
\r
922 $LastYPos1 = $YPos1;
\r
923 $LastYPos2 = $YPos2;
\r
926 $XPos = $XPos + $this->DivisionWidth;
\r
929 imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha);
\r
930 imagedestroy($this->Layers[0]);
\r
934 /* This function write the values of the specified series */
\r
935 function writeValues(&$Data,&$DataDescription,$Series)
\r
937 /* Validate the Data and DataDescription array */
\r
938 $this->validateDataDescription("writeValues",$DataDescription);
\r
939 $this->validateData("writeValues",$Data);
\r
941 if ( !is_array($Series) ) { $Series = array($Series); }
\r
943 foreach($Series as $Key => $Serie)
\r
946 foreach ( $DataDescription["Description"] as $keyI => $ValueI )
\r
947 { if ( $keyI == $Serie ) { $ColorID = $ID; }; $ID++; }
\r
949 $XPos = $this->GArea_X1 + $this->GAreaXOffset;
\r
951 foreach ( $Data as $Key => $Values )
\r
953 if ( isset($Data[$Key][$Serie]) && is_numeric($Data[$Key][$Serie]))
\r
955 $Value = $Data[$Key][$Serie];
\r
956 $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio);
\r
958 $Positions = imagettfbbox($this->FontSize,0,$this->FontName,$Value);
\r
959 $Width = $Positions[2] - $Positions[6]; $XOffset = $XPos - ($Width/2);
\r
960 $Height = $Positions[3] - $Positions[7]; $YOffset = $YPos - 4;
\r
962 $C_TextColor = imagecolorallocate($this->Picture,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]);
\r
963 imagettftext($this->Picture,$this->FontSize,0,$XOffset,$YOffset,$C_TextColor,$this->FontName,$Value);
\r
965 $XPos = $XPos + $this->DivisionWidth;
\r
971 /* This function draw a line graph */
\r
972 function drawLineGraph(&$Data,&$DataDescription,$SerieName="")
\r
974 /* Validate the Data and DataDescription array */
\r
975 $this->validateDataDescription("drawLineGraph",$DataDescription);
\r
976 $this->validateData("drawLineGraph",$Data);
\r
979 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
982 foreach ( $DataDescription["Description"] as $keyI => $ValueI )
\r
983 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; }
\r
985 if ( $SerieName == "" || $SerieName == $ColName )
\r
987 $XPos = $this->GArea_X1 + $this->GAreaXOffset;
\r
989 foreach ( $Data as $Key => $Values )
\r
991 if ( isset($Data[$Key][$ColName]))
\r
993 $Value = $Data[$Key][$ColName];
\r
994 $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio);
\r
996 /* Save point into the image map if option activated */
\r
997 if ( $this->BuildMap )
\r
998 $this->addToImageMap($XPos-3,$YPos-3,$XPos+3,$YPos+3,$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"Line");
\r
1000 if (!is_numeric($Value)) { $XLast = -1; }
\r
1001 if ( $XLast != -1 )
\r
1002 $this->drawLine($XLast,$YLast,$XPos,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE);
\r
1006 if (!is_numeric($Value)) { $XLast = -1; }
\r
1008 $XPos = $XPos + $this->DivisionWidth;
\r
1015 /* This function draw a cubic curve */
\r
1016 function drawCubicCurve(&$Data,&$DataDescription,$Accuracy=.1,$SerieName="")
\r
1018 /* Validate the Data and DataDescription array */
\r
1019 $this->validateDataDescription("drawCubicCurve",$DataDescription);
\r
1020 $this->validateData("drawCubicCurve",$Data);
\r
1023 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1025 if ( $SerieName == "" || $SerieName == $ColName )
\r
1027 $XIn = ""; $Yin = ""; $Yt = ""; $U = "";
\r
1028 $XIn[0] = 0; $YIn[0] = 0;
\r
1031 foreach ( $DataDescription["Description"] as $keyI => $ValueI )
\r
1032 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; }
\r
1035 $XLast = -1; $Missing = "";
\r
1036 foreach ( $Data as $Key => $Values )
\r
1038 if ( isset($Data[$Key][$ColName]) )
\r
1040 $Value = $Data[$Key][$ColName];
\r
1041 $XIn[$Index] = $Index;
\r
1042 $YIn[$Index] = $Value;
\r
1043 if ( !is_numeric($Value) ) { $Missing[$Index] = TRUE; }
\r
1052 for($i=2;$i<=$Index-1;$i++)
\r
1054 $Sig = ($XIn[$i] - $XIn[$i-1]) / ($XIn[$i+1] - $XIn[$i-1]);
\r
1055 $p = $Sig * $Yt[$i-1] + 2;
\r
1056 $Yt[$i] = ($Sig - 1) / $p;
\r
1057 $U[$i] = ($YIn[$i+1] - $YIn[$i]) / ($XIn[$i+1] - $XIn[$i]) - ($YIn[$i] - $YIn[$i-1]) / ($XIn[$i] - $XIn[$i-1]);
\r
1058 $U[$i] = (6 * $U[$i] / ($XIn[$i+1] - $XIn[$i-1]) - $Sig * $U[$i-1]) / $p;
\r
1063 $Yt[$Index] = ($un - $qn * $U[$Index-1]) / ($qn * $Yt[$Index-1] + 1);
\r
1065 for($k=$Index-1;$k>=1;$k--)
\r
1066 $Yt[$k] = $Yt[$k] * $Yt[$k+1] + $U[$k];
\r
1068 $XPos = $this->GArea_X1 + $this->GAreaXOffset;
\r
1069 for($X=1;$X<=$Index;$X=$X+$Accuracy)
\r
1077 If ( $XIn[$k] >= $X )
\r
1084 $h = $XIn[$khi] - $XIn[$klo];
\r
1085 $a = ($XIn[$khi] - $X) / $h;
\r
1086 $b = ($X - $XIn[$klo]) / $h;
\r
1087 $Value = $a * $YIn[$klo] + $b * $YIn[$khi] + (($a*$a*$a - $a) * $Yt[$klo] + ($b*$b*$b - $b) * $Yt[$khi]) * ($h*$h) / 6;
\r
1089 $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio);
\r
1091 if ( $XLast != -1 && !isset($Missing[floor($X)]) && !isset($Missing[floor($X+1)]) )
\r
1092 $this->drawLine($XLast,$YLast,$XPos,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE);
\r
1096 $XPos = $XPos + $this->DivisionWidth * $Accuracy;
\r
1099 // Add potentialy missing values
\r
1100 $XPos = $XPos - $this->DivisionWidth * $Accuracy;
\r
1101 if ( $XPos < ($this->GArea_X2 - $this->GAreaXOffset) )
\r
1103 $YPos = $this->GArea_Y2 - (($YIn[$Index]-$this->VMin) * $this->DivisionRatio);
\r
1104 $this->drawLine($XLast,$YLast,$this->GArea_X2-$this->GAreaXOffset,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE);
\r
1112 /* This function draw a filled cubic curve */
\r
1113 function drawFilledCubicCurve(&$Data,&$DataDescription,$Accuracy=.1,$Alpha=100,$AroundZero=FALSE)
\r
1115 /* Validate the Data and DataDescription array */
\r
1116 $this->validateDataDescription("drawFilledCubicCurve",$DataDescription);
\r
1117 $this->validateData("drawFilledCubicCurve",$Data);
\r
1119 $LayerWidth = $this->GArea_X2-$this->GArea_X1;
\r
1120 $LayerHeight = $this->GArea_Y2-$this->GArea_Y1;
\r
1121 $YZero = $LayerHeight - ((0-$this->VMin) * $this->DivisionRatio);
\r
1122 if ( $YZero > $LayerHeight ) { $YZero = $LayerHeight; }
\r
1125 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1127 $XIn = ""; $Yin = ""; $Yt = ""; $U = "";
\r
1128 $XIn[0] = 0; $YIn[0] = 0;
\r
1131 foreach ( $DataDescription["Description"] as $keyI => $ValueI )
\r
1132 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; }
\r
1135 $XLast = -1; $Missing = "";
\r
1136 foreach ( $Data as $Key => $Values )
\r
1138 $Value = $Data[$Key][$ColName];
\r
1139 $XIn[$Index] = $Index;
\r
1140 $YIn[$Index] = $Value;
\r
1141 if ( !is_numeric($Value) ) { $Missing[$Index] = TRUE; }
\r
1149 for($i=2;$i<=$Index-1;$i++)
\r
1151 $Sig = ($XIn[$i] - $XIn[$i-1]) / ($XIn[$i+1] - $XIn[$i-1]);
\r
1152 $p = $Sig * $Yt[$i-1] + 2;
\r
1153 $Yt[$i] = ($Sig - 1) / $p;
\r
1154 $U[$i] = ($YIn[$i+1] - $YIn[$i]) / ($XIn[$i+1] - $XIn[$i]) - ($YIn[$i] - $YIn[$i-1]) / ($XIn[$i] - $XIn[$i-1]);
\r
1155 $U[$i] = (6 * $U[$i] / ($XIn[$i+1] - $XIn[$i-1]) - $Sig * $U[$i-1]) / $p;
\r
1160 $Yt[$Index] = ($un - $qn * $U[$Index-1]) / ($qn * $Yt[$Index-1] + 1);
\r
1162 for($k=$Index-1;$k>=1;$k--)
\r
1163 $Yt[$k] = $Yt[$k] * $Yt[$k+1] + $U[$k];
\r
1166 $Points[] = $this->GAreaXOffset;
\r
1167 $Points[] = $LayerHeight;
\r
1169 $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight);
\r
1170 $C_White = imagecolorallocate($this->Layers[0],255,255,255);
\r
1171 imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White);
\r
1172 imagecolortransparent($this->Layers[0],$C_White);
\r
1175 $XPos = $this->GAreaXOffset; $PointsCount = 2;
\r
1176 for($X=1;$X<=$Index;$X=$X+$Accuracy)
\r
1184 If ( $XIn[$k] >= $X )
\r
1191 $h = $XIn[$khi] - $XIn[$klo];
\r
1192 $a = ($XIn[$khi] - $X) / $h;
\r
1193 $b = ($X - $XIn[$klo]) / $h;
\r
1194 $Value = $a * $YIn[$klo] + $b * $YIn[$khi] + (($a*$a*$a - $a) * $Yt[$klo] + ($b*$b*$b - $b) * $Yt[$khi]) * ($h*$h) / 6;
\r
1196 $YPos = $LayerHeight - (($Value-$this->VMin) * $this->DivisionRatio);
\r
1198 if ( $YLast != NULL && $AroundZero && !isset($Missing[floor($X)]) && !isset($Missing[floor($X+1)]))
\r
1201 $aPoints[] = $XLast;
\r
1202 $aPoints[] = $YLast;
\r
1203 $aPoints[] = $XPos;
\r
1204 $aPoints[] = $YPos;
\r
1205 $aPoints[] = $XPos;
\r
1206 $aPoints[] = $YZero;
\r
1207 $aPoints[] = $XLast;
\r
1208 $aPoints[] = $YZero;
\r
1210 $C_Graph = imagecolorallocate($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]);
\r
1211 imagefilledpolygon($this->Layers[0],$aPoints,4,$C_Graph);
\r
1214 if ( !isset($Missing[floor($X)]) || $YLast == NULL )
\r
1217 $Points[] = $XPos;
\r
1218 $Points[] = $YPos;
\r
1222 $PointsCount++; $Points[] = $XLast; $Points[] = $LayerHeight;
\r
1225 $YLast = $YPos; $XLast = $XPos;
\r
1226 $XPos = $XPos + $this->DivisionWidth * $Accuracy;
\r
1229 // Add potentialy missing values
\r
1230 $XPos = $XPos - $this->DivisionWidth * $Accuracy;
\r
1231 if ( $XPos < ($LayerWidth-$this->GAreaXOffset) )
\r
1233 $YPos = $LayerHeight - (($YIn[$Index]-$this->VMin) * $this->DivisionRatio);
\r
1235 if ( $YLast != NULL && $AroundZero )
\r
1238 $aPoints[] = $XLast;
\r
1239 $aPoints[] = $YLast;
\r
1240 $aPoints[] = $LayerWidth-$this->GAreaXOffset;
\r
1241 $aPoints[] = $YPos;
\r
1242 $aPoints[] = $LayerWidth-$this->GAreaXOffset;
\r
1243 $aPoints[] = $YZero;
\r
1244 $aPoints[] = $XLast;
\r
1245 $aPoints[] = $YZero;
\r
1247 $C_Graph = imagecolorallocate($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]);
\r
1248 imagefilledpolygon($this->Layers[0],$aPoints,4,$C_Graph);
\r
1251 if ( $YIn[$klo] != "" && $YIn[$khi] != "" || $YLast == NULL )
\r
1254 $Points[] = $LayerWidth-$this->GAreaXOffset;
\r
1255 $Points[] = $YPos;
\r
1259 $Points[] = $LayerWidth-$this->GAreaXOffset;
\r
1260 $Points[] = $LayerHeight;
\r
1262 if ( !$AroundZero )
\r
1264 $C_Graph = imagecolorallocate($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]);
\r
1265 imagefilledpolygon($this->Layers[0],$Points,$PointsCount,$C_Graph);
\r
1268 imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha);
\r
1269 imagedestroy($this->Layers[0]);
\r
1271 $this->drawCubicCurve($Data,$DataDescription,$Accuracy,$ColName);
\r
1277 /* This function draw a filled line graph */
\r
1278 function drawFilledLineGraph(&$Data,&$DataDescription,$Alpha=100,$AroundZero=FALSE)
\r
1280 $Empty = -2147483647;
\r
1282 /* Validate the Data and DataDescription array */
\r
1283 $this->validateDataDescription("drawFilledLineGraph",$DataDescription);
\r
1284 $this->validateData("drawFilledLineGraph",$Data);
\r
1286 $LayerWidth = $this->GArea_X2-$this->GArea_X1;
\r
1287 $LayerHeight = $this->GArea_Y2-$this->GArea_Y1;
\r
1290 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1293 foreach ( $DataDescription["Description"] as $keyI => $ValueI )
\r
1294 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; }
\r
1297 $aPoints[] = $this->GAreaXOffset;
\r
1298 $aPoints[] = $LayerHeight;
\r
1300 $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight);
\r
1301 $C_White = imagecolorallocate($this->Layers[0],255,255,255);
\r
1302 imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White);
\r
1303 imagecolortransparent($this->Layers[0],$C_White);
\r
1305 $XPos = $this->GAreaXOffset;
\r
1306 $XLast = -1; $PointsCount = 2;
\r
1307 $YZero = $LayerHeight - ((0-$this->VMin) * $this->DivisionRatio);
\r
1308 if ( $YZero > $LayerHeight ) { $YZero = $LayerHeight; }
\r
1311 foreach ( $Data as $Key => $Values )
\r
1313 $Value = $Data[$Key][$ColName];
\r
1314 $YPos = $LayerHeight - (($Value-$this->VMin) * $this->DivisionRatio);
\r
1316 /* Save point into the image map if option activated */
\r
1317 if ( $this->BuildMap )
\r
1318 $this->addToImageMap($XPos-3,$YPos-3,$XPos+3,$YPos+3,$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"FLine");
\r
1320 if ( !is_numeric($Value) )
\r
1323 $aPoints[] = $XLast;
\r
1324 $aPoints[] = $LayerHeight;
\r
1331 if ( $YLast <> $Empty )
\r
1332 { $aPoints[] = $XPos; $aPoints[] = $YPos; }
\r
1334 { $PointsCount++; $aPoints[] = $XPos; $aPoints[] = $LayerHeight; $aPoints[] = $XPos; $aPoints[] = $YPos; }
\r
1336 if ($YLast <> $Empty && $AroundZero)
\r
1339 $Points[] = $XLast; $Points[] = $YLast;
\r
1340 $Points[] = $XPos;
\r
1341 $Points[] = $YPos;
\r
1342 $Points[] = $XPos;
\r
1343 $Points[] = $YZero;
\r
1344 $Points[] = $XLast;
\r
1345 $Points[] = $YZero;
\r
1347 $C_Graph = imagecolorallocate($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]);
\r
1348 imagefilledpolygon($this->Layers[0],$Points,4,$C_Graph);
\r
1354 $XPos = $XPos + $this->DivisionWidth;
\r
1356 $aPoints[] = $LayerWidth - $this->GAreaXOffset;
\r
1357 $aPoints[] = $LayerHeight;
\r
1359 if ( $AroundZero == FALSE )
\r
1361 $C_Graph = imagecolorallocate($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]);
\r
1362 imagefilledpolygon($this->Layers[0],$aPoints,$PointsCount,$C_Graph);
\r
1365 imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha);
\r
1366 imagedestroy($this->Layers[0]);
\r
1368 $this->drawLineGraph($Data,$DataDescription,$ColName);
\r
1372 /* This function draw a bar graph */
\r
1373 function drawOverlayBarGraph(&$Data,&$DataDescription,$Alpha=50)
\r
1375 /* Validate the Data and DataDescription array */
\r
1376 $this->validateDataDescription("drawOverlayBarGraph",$DataDescription);
\r
1377 $this->validateData("drawOverlayBarGraph",$Data);
\r
1379 $LayerWidth = $this->GArea_X2-$this->GArea_X1;
\r
1380 $LayerHeight = $this->GArea_Y2-$this->GArea_Y1;
\r
1383 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1386 foreach ( $DataDescription["Description"] as $keyI => $ValueI )
\r
1387 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; }
\r
1389 $this->Layers[$GraphID] = imagecreatetruecolor($LayerWidth,$LayerHeight);
\r
1390 $C_White = imagecolorallocate($this->Layers[$GraphID],255,255,255);
\r
1391 $C_Graph = imagecolorallocate($this->Layers[$GraphID],$this->Palette[$GraphID]["R"],$this->Palette[$GraphID]["G"],$this->Palette[$GraphID]["B"]);
\r
1392 imagefilledrectangle($this->Layers[$GraphID],0,0,$LayerWidth,$LayerHeight,$C_White);
\r
1393 imagecolortransparent($this->Layers[$GraphID],$C_White);
\r
1395 $XWidth = $this->DivisionWidth / 4;
\r
1396 $XPos = $this->GAreaXOffset;
\r
1397 $YZero = $LayerHeight - ((0-$this->VMin) * $this->DivisionRatio);
\r
1398 $XLast = -1; $PointsCount = 2;
\r
1399 foreach ( $Data as $Key => $Values )
\r
1401 if ( isset($Data[$Key][$ColName]) )
\r
1403 $Value = $Data[$Key][$ColName];
\r
1404 if ( is_numeric($Value) )
\r
1406 $YPos = $LayerHeight - (($Value-$this->VMin) * $this->DivisionRatio);
\r
1408 imagefilledrectangle($this->Layers[$GraphID],$XPos-$XWidth,$YPos,$XPos+$XWidth,$YZero,$C_Graph);
\r
1410 $X1 = floor($XPos - $XWidth + $this->GArea_X1); $Y1 = floor($YPos+$this->GArea_Y1) + .2;
\r
1411 $X2 = floor($XPos + $XWidth + $this->GArea_X1); $Y2 = $this->GArea_Y2 - ((0-$this->VMin) * $this->DivisionRatio);
\r
1412 if ( $X1 <= $this->GArea_X1 ) { $X1 = $this->GArea_X1 + 1; }
\r
1413 if ( $X2 >= $this->GArea_X2 ) { $X2 = $this->GArea_X2 - 1; }
\r
1415 /* Save point into the image map if option activated */
\r
1416 if ( $this->BuildMap )
\r
1417 $this->addToImageMap($X1,min($Y1,$Y2),$X2,max($Y1,$Y2),$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"oBar");
\r
1419 $this->drawLine($X1,$Y1,$X2,$Y1,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE);
\r
1422 $XPos = $XPos + $this->DivisionWidth;
\r
1428 for($i=0;$i<=($GraphID-1);$i++)
\r
1430 imagecopymerge($this->Picture,$this->Layers[$i],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha);
\r
1431 imagedestroy($this->Layers[$i]);
\r
1435 /* This function draw a bar graph */
\r
1436 function drawBarGraph(&$Data,&$DataDescription,$Shadow=FALSE,$Alpha=100)
\r
1438 /* Validate the Data and DataDescription array */
\r
1439 $this->validateDataDescription("drawBarGraph",$DataDescription);
\r
1440 $this->validateData("drawBarGraph",$Data);
\r
1443 $Series = count($DataDescription["Values"]);
\r
1444 $SeriesWidth = $this->DivisionWidth / ($Series+1);
\r
1445 $SerieXOffset = $this->DivisionWidth / 2 - $SeriesWidth / 2;
\r
1447 $YZero = $this->GArea_Y2 - ((0-$this->VMin) * $this->DivisionRatio);
\r
1448 if ( $YZero > $this->GArea_Y2 ) { $YZero = $this->GArea_Y2; }
\r
1451 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1454 foreach ( $DataDescription["Description"] as $keyI => $ValueI )
\r
1455 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; }
\r
1457 $XPos = $this->GArea_X1 + $this->GAreaXOffset - $SerieXOffset + $SeriesWidth * $SerieID;
\r
1459 foreach ( $Data as $Key => $Values )
\r
1461 if ( isset($Data[$Key][$ColName]))
\r
1463 if ( is_numeric($Data[$Key][$ColName]) )
\r
1465 $Value = $Data[$Key][$ColName];
\r
1466 $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio);
\r
1468 /* Save point into the image map if option activated */
\r
1469 if ( $this->BuildMap )
\r
1471 $this->addToImageMap($XPos+1,min($YZero,$YPos),$XPos+$SeriesWidth-1,max($YZero,$YPos),$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"Bar");
\r
1474 if ( $Shadow && $Alpha == 100 )
\r
1475 $this->drawRectangle($XPos+1,$YZero,$XPos+$SeriesWidth-1,$YPos,25,25,25,TRUE,$Alpha);
\r
1477 $this->drawFilledRectangle($XPos+1,$YZero,$XPos+$SeriesWidth-1,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE,$Alpha);
\r
1480 $XPos = $XPos + $this->DivisionWidth;
\r
1486 /* This function draw a stacked bar graph */
\r
1487 function drawStackedBarGraph(&$Data,&$DataDescription,$Alpha=50)
\r
1489 /* Validate the Data and DataDescription array */
\r
1490 $this->validateDataDescription("drawBarGraph",$DataDescription);
\r
1491 $this->validateData("drawBarGraph",$Data);
\r
1494 $Series = count($DataDescription["Values"]);
\r
1495 $SeriesWidth = $this->DivisionWidth * .8;
\r
1497 $YZero = $this->GArea_Y2 - ((0-$this->VMin) * $this->DivisionRatio);
\r
1498 if ( $YZero > $this->GArea_Y2 ) { $YZero = $this->GArea_Y2; }
\r
1500 $SerieID = 0; $LastValue = "";
\r
1501 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1504 foreach ( $DataDescription["Description"] as $keyI => $ValueI )
\r
1505 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; }
\r
1507 $XPos = $this->GArea_X1 + $this->GAreaXOffset - $SeriesWidth / 2;
\r
1509 foreach ( $Data as $Key => $Values )
\r
1511 if ( isset($Data[$Key][$ColName]))
\r
1513 if ( is_numeric($Data[$Key][$ColName]) )
\r
1515 $Value = $Data[$Key][$ColName];
\r
1517 if ( isset($LastValue[$Key]) )
\r
1519 $YPos = $this->GArea_Y2 - ((($Value+$LastValue[$Key])-$this->VMin) * $this->DivisionRatio);
\r
1520 $YBottom = $this->GArea_Y2 - (($LastValue[$Key]-$this->VMin) * $this->DivisionRatio);
\r
1521 $LastValue[$Key] += $Value;
\r
1525 $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio);
\r
1526 $YBottom = $YZero;
\r
1527 $LastValue[$Key] = $Value;
\r
1530 /* Save point into the image map if option activated */
\r
1531 if ( $this->BuildMap )
\r
1532 $this->addToImageMap($XPos+1,min($YBottom,$YPos),$XPos+$SeriesWidth-1,max($YBottom,$YPos),$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"sBar");
\r
1534 $this->drawFilledRectangle($XPos+1,$YBottom,$XPos+$SeriesWidth-1,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE,$Alpha);
\r
1537 $XPos = $XPos + $this->DivisionWidth;
\r
1543 /* This function draw a limits bar graphs */
\r
1544 function drawLimitsGraph(&$Data,&$DataDescription,$R=0,$G=0,$B=0)
\r
1546 /* Validate the Data and DataDescription array */
\r
1547 $this->validateDataDescription("drawLimitsGraph",$DataDescription);
\r
1548 $this->validateData("drawLimitsGraph",$Data);
\r
1550 $XWidth = $this->DivisionWidth / 4;
\r
1551 $XPos = $this->GArea_X1 + $this->GAreaXOffset;
\r
1553 foreach ( $Data as $Key => $Values )
\r
1555 $Min = $Data[$Key][$DataDescription["Values"][0]];
\r
1556 $Max = $Data[$Key][$DataDescription["Values"][0]];
\r
1557 $GraphID = 0; $MaxID = 0; $MinID = 0;
\r
1558 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1560 if ( isset($Data[$Key][$ColName]) )
\r
1562 if ( $Data[$Key][$ColName] > $Max && is_numeric($Data[$Key][$ColName]))
\r
1563 { $Max = $Data[$Key][$ColName]; $MaxID = $GraphID; }
\r
1565 if ( isset($Data[$Key][$ColName]) && is_numeric($Data[$Key][$ColName]))
\r
1567 if ( $Data[$Key][$ColName] < $Min )
\r
1568 { $Min = $Data[$Key][$ColName]; $MinID = $GraphID; }
\r
1573 $YPos = $this->GArea_Y2 - (($Max-$this->VMin) * $this->DivisionRatio);
\r
1574 $X1 = floor($XPos - $XWidth); $Y1 = floor($YPos) - .2;
\r
1575 $X2 = floor($XPos + $XWidth);
\r
1576 if ( $X1 <= $this->GArea_X1 ) { $X1 = $this->GArea_X1 + 1; }
\r
1577 if ( $X2 >= $this->GArea_X2 ) { $X2 = $this->GArea_X2 - 1; }
\r
1579 $YPos = $this->GArea_Y2 - (($Min-$this->VMin) * $this->DivisionRatio);
\r
1580 $Y2 = floor($YPos) + .2;
\r
1582 $this->drawLine(floor($XPos)-.2,$Y1+1,floor($XPos)-.2,$Y2-1,$R,$G,$B,TRUE);
\r
1583 $this->drawLine(floor($XPos)+.2,$Y1+1,floor($XPos)+.2,$Y2-1,$R,$G,$B,TRUE);
\r
1584 $this->drawLine($X1,$Y1,$X2,$Y1,$this->Palette[$MaxID]["R"],$this->Palette[$MaxID]["G"],$this->Palette[$MaxID]["B"],FALSE);
\r
1585 $this->drawLine($X1,$Y2,$X2,$Y2,$this->Palette[$MinID]["R"],$this->Palette[$MinID]["G"],$this->Palette[$MinID]["B"],FALSE);
\r
1587 $XPos = $XPos + $this->DivisionWidth;
\r
1591 /* This function draw radar axis centered on the graph area */
\r
1592 function drawRadarAxis(&$Data,&$DataDescription,$Mosaic=TRUE,$BorderOffset=10,$A_R=60,$A_G=60,$A_B=60,$S_R=200,$S_G=200,$S_B=200,$MaxValue=-1)
\r
1594 /* Validate the Data and DataDescription array */
\r
1595 $this->validateDataDescription("drawRadarAxis",$DataDescription);
\r
1596 $this->validateData("drawRadarAxis",$Data);
\r
1598 $C_TextColor = imagecolorallocate($this->Picture,$A_R,$A_G,$A_B);
\r
1600 /* Draw radar axis */
\r
1601 $Points = count($Data);
\r
1602 $Radius = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 - $BorderOffset;
\r
1603 $XCenter = ( $this->GArea_X2 - $this->GArea_X1 ) / 2 + $this->GArea_X1;
\r
1604 $YCenter = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 + $this->GArea_Y1;
\r
1606 /* Search for the max value */
\r
1607 if ( $MaxValue == -1 )
\r
1609 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1611 foreach ( $Data as $Key => $Values )
\r
1613 if ( isset($Data[$Key][$ColName]))
\r
1614 if ( $Data[$Key][$ColName] > $MaxValue ) { $MaxValue = $Data[$Key][$ColName]; }
\r
1619 /* Draw the mosaic */
\r
1622 $RadiusScale = $Radius / $MaxValue;
\r
1623 for ( $t=1; $t<=$MaxValue-1; $t++)
\r
1625 $TRadius = $RadiusScale * $t;
\r
1628 for ( $i=0; $i<=$Points; $i++)
\r
1630 $Angle = -90 + $i * 360/$Points;
\r
1631 $X1 = cos($Angle * 3.1418 / 180 ) * $TRadius + $XCenter;
\r
1632 $Y1 = sin($Angle * 3.1418 / 180 ) * $TRadius + $YCenter;
\r
1633 $X2 = cos($Angle * 3.1418 / 180 ) * ($TRadius+$RadiusScale) + $XCenter;
\r
1634 $Y2 = sin($Angle * 3.1418 / 180 ) * ($TRadius+$RadiusScale) + $YCenter;
\r
1636 if ( $t % 2 == 1 && $LastX1 != -1)
\r
1639 $Plots[] = $X1; $Plots[] = $Y1;
\r
1640 $Plots[] = $X2; $Plots[] = $Y2;
\r
1641 $Plots[] = $LastX2; $Plots[] = $LastY2;
\r
1642 $Plots[] = $LastX1; $Plots[] = $LastY1;
\r
1644 $C_Graph = imagecolorallocate($this->Picture,250,250,250);
\r
1645 imagefilledpolygon($this->Picture,$Plots,(count($Plots)+1)/2,$C_Graph);
\r
1648 $LastX1 = $X1; $LastY1= $Y1;
\r
1649 $LastX2 = $X2; $LastY2= $Y2;
\r
1655 /* Draw the spider web */
\r
1656 for ( $t=1; $t<=$MaxValue; $t++)
\r
1658 $TRadius = ( $Radius / $MaxValue ) * $t;
\r
1661 for ( $i=0; $i<=$Points; $i++)
\r
1663 $Angle = -90 + $i * 360/$Points;
\r
1664 $X = cos($Angle * 3.1418 / 180 ) * $TRadius + $XCenter;
\r
1665 $Y = sin($Angle * 3.1418 / 180 ) * $TRadius + $YCenter;
\r
1667 if ( $LastX != -1 )
\r
1668 $this->drawDottedLine($LastX,$LastY,$X,$Y,4,$S_R,$S_G,$S_B);
\r
1670 $LastX = $X; $LastY= $Y;
\r
1674 /* Draw the axis */
\r
1675 for ( $i=0; $i<=$Points; $i++)
\r
1677 $Angle = -90 + $i * 360/$Points;
\r
1678 $X = cos($Angle * 3.1418 / 180 ) * $Radius + $XCenter;
\r
1679 $Y = sin($Angle * 3.1418 / 180 ) * $Radius + $YCenter;
\r
1681 $this->drawLine($XCenter,$YCenter,$X,$Y,$A_R,$A_G,$A_B);
\r
1683 $XOffset = 0; $YOffset = 0;
\r
1684 if (isset($Data[$i][$DataDescription["Position"]]))
\r
1686 $Label = $Data[$i][$DataDescription["Position"]];
\r
1688 $Positions = imagettfbbox($this->FontSize,0,$this->FontName,$Label);
\r
1689 $Width = $Positions[2] - $Positions[6];
\r
1690 $Height = $Positions[3] - $Positions[7];
\r
1692 if ( $Angle >= 0 && $Angle <= 90 )
\r
1693 $YOffset = $Height;
\r
1695 if ( $Angle > 90 && $Angle <= 180 )
\r
1696 { $YOffset = $Height; $XOffset = -$Width; }
\r
1698 if ( $Angle > 180 && $Angle <= 270 )
\r
1699 { $XOffset = -$Width; }
\r
1701 imagettftext($this->Picture,$this->FontSize,0,$X+$XOffset,$Y+$YOffset,$C_TextColor,$this->FontName,$Label);
\r
1705 /* Write the values */
\r
1706 for ( $t=1; $t<=$MaxValue; $t++)
\r
1708 $TRadius = ( $Radius / $MaxValue ) * $t;
\r
1710 $Angle = -90 + 360 / $Points;
\r
1712 $Y1 = $YCenter - $TRadius;
\r
1713 $X2 = cos($Angle * 3.1418 / 180 ) * $TRadius + $XCenter;
\r
1714 $Y2 = sin($Angle * 3.1418 / 180 ) * $TRadius + $YCenter;
\r
1716 $XPos = floor(($X2-$X1)/2) + $X1;
\r
1717 $YPos = floor(($Y2-$Y1)/2) + $Y1;
\r
1719 $Positions = imagettfbbox($this->FontSize,0,$this->FontName,$t);
\r
1720 $X = $XPos - ( $X+$Positions[2] - $X+$Positions[6] ) / 2;
\r
1721 $Y = $YPos + $this->FontSize;
\r
1723 $this->drawFilledRoundedRectangle($X+$Positions[6]-2,$Y+$Positions[7]-1,$X+$Positions[2]+4,$Y+$Positions[3]+1,2,240,240,240);
\r
1724 $this->drawRoundedRectangle($X+$Positions[6]-2,$Y+$Positions[7]-1,$X+$Positions[2]+4,$Y+$Positions[3]+1,2,220,220,220);
\r
1725 imagettftext($this->Picture,$this->FontSize,0,$X,$Y,$C_TextColor,$this->FontName,$t);
\r
1729 /* This function draw a radar graph centered on the graph area */
\r
1730 function drawRadar(&$Data,&$DataDescription,$BorderOffset=10,$MaxValue=-1)
\r
1732 /* Validate the Data and DataDescription array */
\r
1733 $this->validateDataDescription("drawRadar",$DataDescription);
\r
1734 $this->validateData("drawRadar",$Data);
\r
1736 $Points = count($Data);
\r
1737 $Radius = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 - $BorderOffset;
\r
1738 $XCenter = ( $this->GArea_X2 - $this->GArea_X1 ) / 2 + $this->GArea_X1;
\r
1739 $YCenter = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 + $this->GArea_Y1;
\r
1741 /* Search for the max value */
\r
1742 if ( $MaxValue == -1 )
\r
1744 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1746 foreach ( $Data as $Key => $Values )
\r
1748 if ( isset($Data[$Key][$ColName]))
\r
1749 if ( $Data[$Key][$ColName] > $MaxValue ) { $MaxValue = $Data[$Key][$ColName]; }
\r
1755 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1758 foreach ( $DataDescription["Description"] as $keyI => $ValueI )
\r
1759 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; }
\r
1763 foreach ( $Data as $Key => $Values )
\r
1765 if ( isset($Data[$Key][$ColName]))
\r
1767 $Value = $Data[$Key][$ColName];
\r
1768 $Strength = ( $Radius / $MaxValue ) * $Value;
\r
1770 $XPos = cos($Angle * 3.1418 / 180 ) * $Strength + $XCenter;
\r
1771 $YPos = sin($Angle * 3.1418 / 180 ) * $Strength + $YCenter;
\r
1773 if ( $XLast != -1 )
\r
1774 $this->drawLine($XLast,$YLast,$XPos,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]);
\r
1776 if ( $XLast == -1 )
\r
1777 { $FirstX = $XPos; $FirstY = $YPos; }
\r
1779 $Angle = $Angle + (360/$Points);
\r
1784 $this->drawLine($XPos,$YPos,$FirstX,$FirstY,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]);
\r
1789 /* This function draw a radar graph centered on the graph area */
\r
1790 function drawFilledRadar(&$Data,&$DataDescription,$Alpha=50,$BorderOffset=10,$MaxValue=-1)
\r
1792 /* Validate the Data and DataDescription array */
\r
1793 $this->validateDataDescription("drawFilledRadar",$DataDescription);
\r
1794 $this->validateData("drawFilledRadar",$Data);
\r
1796 $Points = count($Data);
\r
1797 $LayerWidth = $this->GArea_X2-$this->GArea_X1;
\r
1798 $LayerHeight = $this->GArea_Y2-$this->GArea_Y1;
\r
1799 $Radius = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 - $BorderOffset;
\r
1800 $XCenter = ( $this->GArea_X2 - $this->GArea_X1 ) / 2;
\r
1801 $YCenter = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2;
\r
1803 /* Search for the max value */
\r
1804 if ( $MaxValue == -1 )
\r
1806 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1808 foreach ( $Data as $Key => $Values )
\r
1810 if ( isset($Data[$Key][$ColName]))
\r
1811 if ( $Data[$Key][$ColName] > $MaxValue && is_numeric($Data[$Key][$ColName])) { $MaxValue = $Data[$Key][$ColName]; }
\r
1817 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1820 foreach ( $DataDescription["Description"] as $keyI => $ValueI )
\r
1821 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; }
\r
1826 foreach ( $Data as $Key => $Values )
\r
1828 if ( isset($Data[$Key][$ColName]))
\r
1830 $Value = $Data[$Key][$ColName];
\r
1831 if ( !is_numeric($Value) ) { $Value = 0; }
\r
1832 $Strength = ( $Radius / $MaxValue ) * $Value;
\r
1834 $XPos = cos($Angle * 3.1418 / 180 ) * $Strength + $XCenter;
\r
1835 $YPos = sin($Angle * 3.1418 / 180 ) * $Strength + $YCenter;
\r
1840 $Angle = $Angle + (360/$Points);
\r
1846 if (isset($Plots[0]))
\r
1848 $Plots[] = $Plots[0];
\r
1849 $Plots[] = $Plots[1];
\r
1851 $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight);
\r
1852 $C_White = imagecolorallocate($this->Layers[0],255,255,255);
\r
1853 imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White);
\r
1854 imagecolortransparent($this->Layers[0],$C_White);
\r
1856 $C_Graph = imagecolorallocate($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]);
\r
1857 imagefilledpolygon($this->Layers[0],$Plots,(count($Plots)+1)/2,$C_Graph);
\r
1859 imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha);
\r
1860 imagedestroy($this->Layers[0]);
\r
1862 for($i=0;$i<=count($Plots)-4;$i=$i+2)
\r
1863 $this->drawLine($Plots[$i]+$this->GArea_X1,$Plots[$i+1]+$this->GArea_Y1,$Plots[$i+2]+$this->GArea_X1,$Plots[$i+3]+$this->GArea_Y1,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]);
\r
1870 /* This function draw a flat pie chart */
\r
1871 function drawBasicPieGraph(&$Data,&$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$R=255,$G=255,$B=255,$Decimals=0)
\r
1873 /* Validate the Data and DataDescription array */
\r
1874 $this->validateDataDescription("drawBasicPieGraph",$DataDescription,FALSE);
\r
1875 $this->validateData("drawBasicPieGraph",$Data);
\r
1877 /* Determine pie sum */
\r
1878 $Series = 0; $PieSum = 0;
\r
1879 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1881 if ( $ColName != $DataDescription["Position"] )
\r
1884 foreach ( $Data as $Key => $Values )
\r
1886 if ( isset($Data[$Key][$ColName]))
\r
1887 $PieSum = $PieSum + $Data[$Key][$ColName]; $iValues[] = $Data[$Key][$ColName]; $iLabels[] = $Data[$Key][$DataDescription["Position"]];
\r
1892 /* Validate serie */
\r
1893 if ( $Series != 1 )
\r
1894 RaiseFatal("Pie chart can only accept one serie of data.");
\r
1896 $SpliceRatio = 360 / $PieSum;
\r
1897 $SplicePercent = 100 / $PieSum;
\r
1899 /* Calculate all polygons */
\r
1900 $Angle = 0; $TopPlots = "";
\r
1901 foreach($iValues as $Key => $Value)
\r
1903 $TopPlots[$Key][] = $XPos;
\r
1904 $TopPlots[$Key][] = $YPos;
\r
1906 /* Process labels position & size */
\r
1907 if ( !($DrawLabels == PIE_NOLABEL) )
\r
1909 $TAngle = $Angle+($Value*$SpliceRatio/2);
\r
1910 if ($DrawLabels == PIE_PERCENTAGE)
\r
1911 $Caption = (round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%";
\r
1912 elseif ($DrawLabels == PIE_LABELS)
\r
1913 $Caption = $iLabels[$Key];
\r
1914 $TX = cos(($TAngle) * 3.1418 / 180 ) * ($Radius + 10)+ $XPos;
\r
1915 $TY = sin(($TAngle) * 3.1418 / 180 ) * ($Radius+ 10) + $YPos + 4;
\r
1917 if ( $TAngle > 90 && $TAngle < 270 )
\r
1919 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Caption,$bogus);
\r
1920 $TextWidth = $Position[2]-$Position[0];
\r
1921 $TX = $TX - $TextWidth;
\r
1924 $C_TextColor = imagecolorallocate($this->Picture,70,70,70);
\r
1925 imagettftext($this->Picture,$this->FontSize,0,$TX,$TY,$C_TextColor,$this->FontName,$Caption);
\r
1928 /* Process pie slices */
\r
1929 for($iAngle=$Angle;$iAngle<=$Angle+$Value*$SpliceRatio;$iAngle=$iAngle+.5)
\r
1931 $TopX = cos($iAngle * 3.1418 / 180 ) * $Radius + $XPos;
\r
1932 $TopY = sin($iAngle * 3.1418 / 180 ) * $Radius + $YPos;
\r
1934 $TopPlots[$Key][] = $TopX;
\r
1935 $TopPlots[$Key][] = $TopY;
\r
1938 $TopPlots[$Key][] = $XPos;
\r
1939 $TopPlots[$Key][] = $YPos;
\r
1943 $PolyPlots = $TopPlots;
\r
1945 /* Set array values type to float --- PHP Bug with imagefilledpolygon casting to integer */
\r
1946 foreach ($TopPlots as $Key => $Value)
\r
1947 { foreach ($TopPlots[$Key] as $Key2 => $Value2) { settype($TopPlots[$Key][$Key2],"float"); } }
\r
1949 /* Draw Top polygons */
\r
1950 foreach ($PolyPlots as $Key => $Value)
\r
1952 $C_GraphLo = imagecolorallocate($this->Picture,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"]);
\r
1953 imagefilledpolygon($this->Picture,$PolyPlots[$Key],(count($PolyPlots[$Key])+1)/2,$C_GraphLo);
\r
1956 $this->drawCircle($XPos-.5,$YPos-.5,$Radius,$R,$G,$B);
\r
1957 $this->drawCircle($XPos-.5,$YPos-.5,$Radius+.5,$R,$G,$B);
\r
1959 /* Draw Top polygons */
\r
1960 foreach ($TopPlots as $Key => $Value)
\r
1962 for($j=0;$j<=count($TopPlots[$Key])-4;$j=$j+2)
\r
1963 $this->drawLine($TopPlots[$Key][$j],$TopPlots[$Key][$j+1],$TopPlots[$Key][$j+2],$TopPlots[$Key][$j+3],$R,$G,$B);
\r
1967 /* This function draw a flat pie chart */
\r
1968 function drawFlatPieGraph(&$Data,&$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$SpliceDistance=0,$Decimals = 0)
\r
1970 /* Validate the Data and DataDescription array */
\r
1971 $this->validateDataDescription("drawFlatPieGraph",$DataDescription,FALSE);
\r
1972 $this->validateData("drawFlatPieGraph",$Data);
\r
1974 /* Determine pie sum */
\r
1975 $Series = 0; $PieSum = 0;
\r
1976 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
1978 if ( $ColName != $DataDescription["Position"] )
\r
1981 foreach ( $Data as $Key => $Values )
\r
1983 if ( isset($Data[$Key][$ColName]))
\r
1984 $PieSum = $PieSum + $Data[$Key][$ColName]; $iValues[] = $Data[$Key][$ColName]; $iLabels[] = $Data[$Key][$DataDescription["Position"]];
\r
1989 /* Validate serie */
\r
1990 if ( $Series != 1 )
\r
1991 RaiseFatal("Pie chart can only accept one serie of data.");
\r
1993 $SpliceDistanceRatio = $SpliceDistance;
\r
1994 $SpliceRatio = (360 - $SpliceDistanceRatio * count($iValues) ) / $PieSum;
\r
1995 $SplicePercent = 100 / $PieSum;
\r
1997 /* Calculate all polygons */
\r
1998 $Angle = 0; $TopPlots = "";
\r
1999 foreach($iValues as $Key => $Value)
\r
2001 $XCenterPos = cos(($Angle+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.1418 / 180 ) * $SpliceDistance + $XPos;
\r
2002 $YCenterPos = sin(($Angle+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.1418 / 180 ) * $SpliceDistance + $YPos;
\r
2004 $TopPlots[$Key][] = $XCenterPos;
\r
2005 $TopPlots[$Key][] = $YCenterPos;
\r
2007 /* Process labels position & size */
\r
2008 if ( !($DrawLabels == PIE_NOLABEL) )
\r
2010 $TAngle = $Angle+($Value*$SpliceRatio/2);
\r
2011 if ($DrawLabels == PIE_PERCENTAGE)
\r
2012 $Caption = (round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%";
\r
2013 elseif ($DrawLabels == PIE_LABELS)
\r
2014 $Caption = $iLabels[$Key];
\r
2015 $TX = cos(($TAngle) * 3.1418 / 180 ) * ($Radius+10+$SpliceDistance)+$XPos;
\r
2016 $TY = sin(($TAngle) * 3.1418 / 180 ) * ($Radius+10+$SpliceDistance) + $YPos + 4;
\r
2018 if ( $TAngle > 90 && $TAngle < 270 )
\r
2020 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Caption,$bogus);
\r
2021 $TextWidth = $Position[2]-$Position[0];
\r
2022 $TX = $TX - $TextWidth;
\r
2025 $C_TextColor = imagecolorallocate($this->Picture,70,70,70);
\r
2026 imagettftext($this->Picture,$this->FontSize,0,$TX,$TY,$C_TextColor,$this->FontName,$Caption);
\r
2029 /* Draw borders to correct imagefilledpolygon bug */
\r
2031 for($i=-1;$i<=$BMax;$i++)
\r
2033 $BorderX1 = cos(($Angle+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.1418 / 180 ) * ($SpliceDistance+$i) + $XPos;
\r
2034 $BorderY1 = sin(($Angle+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.1418 / 180 ) * ($SpliceDistance+$i) + $YPos;
\r
2035 $BorderX2 = cos(($Angle+$i*.5) * 3.1418 / 180 ) * (($Radius+$BMax)+$SpliceDistance) + $XPos;
\r
2036 $BorderY2 = sin(($Angle+$i*.5) * 3.1418 / 180 ) * (($Radius+$BMax)+$SpliceDistance) + $YPos;
\r
2037 $this->drawLine($BorderX1,$BorderY1,$BorderX2,$BorderY2,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"]);
\r
2039 $BorderX1 = cos(($Angle+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.1418 / 180 ) * ($SpliceDistance+$i) + $XPos;
\r
2040 $BorderY1 = sin(($Angle+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.1418 / 180 ) * ($SpliceDistance+$i) + $YPos;
\r
2041 $BorderX2 = cos(($Angle-$i*.5+$Value*$SpliceRatio) * 3.1418 / 180 ) * (($Radius+$BMax)+$SpliceDistance) + $XPos;
\r
2042 $BorderY2 = sin(($Angle-$i*.5+$Value*$SpliceRatio) * 3.1418 / 180 ) * (($Radius+$BMax)+$SpliceDistance) + $YPos;
\r
2043 $this->drawLine($BorderX1,$BorderY1,$BorderX2,$BorderY2,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"]);
\r
2046 /* Process pie slices */
\r
2047 for($iAngle=$Angle;$iAngle<=$Angle+$Value*$SpliceRatio;$iAngle=$iAngle+.5)
\r
2049 $TopX = cos($iAngle * 3.1418 / 180 ) * ($Radius+$SpliceDistance) + $XPos;
\r
2050 $TopY = sin($iAngle * 3.1418 / 180 ) * ($Radius+$SpliceDistance) + $YPos;
\r
2052 $TopPlots[$Key][] = $TopX;
\r
2053 $TopPlots[$Key][] = $TopY;
\r
2055 if ( $iAngle != $Angle )
\r
2057 for($i=-1;$i<=2;$i++)
\r
2059 $BorderX1 = cos(($iAngle-.5) * 3.1418 / 180 ) * (($Radius+$i)+$SpliceDistance) + $XPos;
\r
2060 $BorderY1 = sin(($iAngle-.5) * 3.1418 / 180 ) * (($Radius+$i)+$SpliceDistance) + $YPos;
\r
2061 $BorderX2 = cos($iAngle * 3.1418 / 180 ) * (($Radius+$i)+$SpliceDistance) + $XPos;
\r
2062 $BorderY2 = sin($iAngle * 3.1418 / 180 ) * (($Radius+$i)+$SpliceDistance) + $YPos;
\r
2064 $this->drawLine($BorderX1,$BorderY1,$BorderX2,$BorderY2,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"]);
\r
2069 $TopPlots[$Key][] = $XCenterPos;
\r
2070 $TopPlots[$Key][] = $YCenterPos;
\r
2072 $Angle = $iAngle + $SpliceDistanceRatio;
\r
2074 $PolyPlots = $TopPlots;
\r
2076 /* Set array values type to float --- PHP Bug with imagefilledpolygon casting to integer */
\r
2077 foreach ($TopPlots as $Key => $Value)
\r
2078 { foreach ($TopPlots[$Key] as $Key2 => $Value2) { settype($TopPlots[$Key][$Key2],"float"); } }
\r
2080 /* Draw Top polygons */
\r
2081 foreach ($TopPlots as $Key => $Value)
\r
2083 $C_GraphLo = imagecolorallocate($this->Picture,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"]);
\r
2084 imagefilledpolygon($this->Picture,$PolyPlots[$Key],(count($PolyPlots[$Key])+1)/2,$C_GraphLo);
\r
2088 /* This function draw a pseudo-3D pie chart */
\r
2089 function drawPieGraph(&$Data,&$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$EnhanceColors=TRUE,$Skew=60,$SpliceHeight=20,$SpliceDistance=0,$Decimals=0)
\r
2091 /* Validate the Data and DataDescription array */
\r
2092 $this->validateDataDescription("drawPieGraph",$DataDescription,FALSE);
\r
2093 $this->validateData("drawPieGraph",$Data);
\r
2095 /* Determine pie sum */
\r
2096 $Series = 0; $PieSum = 0; $rPieSum = 0;
\r
2097 foreach ( $DataDescription["Values"] as $Key2 => $ColName )
\r
2099 if ( $ColName != $DataDescription["Position"] )
\r
2102 foreach ( $Data as $Key => $Values )
\r
2103 if ( isset($Data[$Key][$ColName]))
\r
2105 if ( $Data[$Key][$ColName] == 0 )
\r
2106 { $PieSum++; $iValues[] = 1; $rValues[] = 0; }
\r
2108 { $PieSum += $Data[$Key][$ColName]; $iValues[] = $Data[$Key][$ColName]; $iLabels[] = $Data[$Key][$DataDescription["Position"]]; $rValues[] = $Data[$Key][$ColName]; $rPieSum += $Data[$Key][$ColName];}
\r
2113 /* Validate serie */
\r
2114 if ( $Series != 1 )
\r
2115 RaiseFatal("Pie chart can only accept one serie of data.");
\r
2117 $SpliceDistanceRatio = $SpliceDistance;
\r
2118 $SkewHeight = ($Radius * $Skew) / 100;
\r
2119 $SpliceRatio = (360 - $SpliceDistanceRatio * count($iValues) ) / $PieSum;
\r
2120 $SplicePercent = 100 / $PieSum;
\r
2121 $rSplicePercent = 100 / $rPieSum;
\r
2123 /* Calculate all polygons */
\r
2124 $Angle = 0; $TopPlots = ""; $BotPlots = ""; $CDev = 5;
\r
2125 foreach($iValues as $Key => $Value)
\r
2127 $XCenterPos = cos(($Angle-$CDev+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.1418 / 180 ) * $SpliceDistance + $XPos;
\r
2128 $YCenterPos = sin(($Angle-$CDev+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.1418 / 180 ) * $SpliceDistance + $YPos;
\r
2129 $XCenterPos2 = cos(($Angle+$CDev+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.1418 / 180 ) * $SpliceDistance + $XPos;
\r
2130 $YCenterPos2 = sin(($Angle+$CDev+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.1418 / 180 ) * $SpliceDistance + $YPos;
\r
2132 $TopPlots[$Key][] = $XCenterPos; $BotPlots[$Key][] = $XCenterPos;
\r
2133 $TopPlots[$Key][] = $YCenterPos; $BotPlots[$Key][] = $YCenterPos + $SpliceHeight;
\r
2135 /* Process labels position & size */
\r
2136 if ( !($DrawLabels == PIE_NOLABEL) )
\r
2138 $TAngle = $Angle+($Value*$SpliceRatio/2);
\r
2139 if ($DrawLabels == PIE_PERCENTAGE)
\r
2140 $Caption = (round($rValues[$Key] * pow(10,$Decimals) * $rSplicePercent)/pow(10,$Decimals))."%";
\r
2141 elseif ($DrawLabels == PIE_LABELS)
\r
2142 $Caption = $iLabels[$Key];
\r
2144 $TX = cos(($TAngle) * 3.1418 / 180 ) * ($Radius + 10)+ $XPos;
\r
2146 if ( $TAngle > 0 && $TAngle < 180 )
\r
2147 $TY = sin(($TAngle) * 3.1418 / 180 ) * ($SkewHeight + 10) + $YPos + $SpliceHeight + 4;
\r
2149 $TY = sin(($TAngle) * 3.1418 / 180 ) * ($SkewHeight + 10) + $YPos + 4;
\r
2151 if ( $TAngle > 90 && $TAngle < 270 )
\r
2153 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Caption,$bogus);
\r
2154 $TextWidth = $Position[2]-$Position[0];
\r
2155 $TX = $TX - $TextWidth;
\r
2158 $C_TextColor = imagecolorallocate($this->Picture,70,70,70);
\r
2159 imagettftext($this->Picture,$this->FontSize,0,$TX,$TY,$C_TextColor,$this->FontName,$Caption);
\r
2162 /* Process pie slices */
\r
2163 for($iAngle=$Angle;$iAngle<=$Angle+$Value*$SpliceRatio;$iAngle=$iAngle+.5)
\r
2165 $TopX = cos($iAngle * 3.1418 / 180 ) * $Radius + $XPos;
\r
2166 $TopY = sin($iAngle * 3.1418 / 180 ) * $SkewHeight + $YPos;
\r
2168 $TopPlots[$Key][] = $TopX; $BotPlots[$Key][] = $TopX;
\r
2169 $TopPlots[$Key][] = $TopY; $BotPlots[$Key][] = $TopY + $SpliceHeight;
\r
2172 $TopPlots[$Key][] = $XCenterPos2; $BotPlots[$Key][] = $XCenterPos2;
\r
2173 $TopPlots[$Key][] = $YCenterPos2; $BotPlots[$Key][] = $YCenterPos2 + $SpliceHeight;
\r
2175 $Angle = $iAngle + $SpliceDistanceRatio;
\r
2178 /* Draw Bottom polygons */
\r
2179 foreach($iValues as $Key => $Value)
\r
2181 $C_GraphLo = $this->AllocateColor($this->Picture,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"],-20);
\r
2182 imagefilledpolygon($this->Picture,$BotPlots[$Key],(count($BotPlots[$Key])+1)/2,$C_GraphLo);
\r
2184 for($j=0;$j<=count($BotPlots[$Key])-4;$j=$j+2)
\r
2185 $this->drawLine($BotPlots[$Key][$j],$BotPlots[$Key][$j+1],$BotPlots[$Key][$j+2],$BotPlots[$Key][$j+3],$this->Palette[$Key]["R"]-20,$this->Palette[$Key]["G"]-20,$this->Palette[$Key]["B"]-20);
\r
2188 /* Draw pie layers */
\r
2189 if ( $EnhanceColors ) { $ColorRatio = 30 / $SpliceHeight; } else { $ColorRatio = 25 / $SpliceHeight; }
\r
2190 for($i=$SpliceHeight-1;$i>=1;$i--)
\r
2192 foreach($iValues as $Key => $Value)
\r
2194 $C_GraphLo = $this->AllocateColor($this->Picture,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"],-10);
\r
2195 $Plots = ""; $Plot = 0;
\r
2196 foreach($TopPlots[$Key] as $Key2 => $Value2)
\r
2199 if ( $Plot % 2 == 1 )
\r
2200 $Plots[] = $Value2;
\r
2202 $Plots[] = $Value2+$i;
\r
2204 imagefilledpolygon($this->Picture,$Plots,(count($Plots)+1)/2,$C_GraphLo);
\r
2206 $Index = count($Plots);
\r
2207 $ColorFactor = -20 + ($SpliceHeight - $i) * $ColorRatio;
\r
2208 $this->drawAntialiasPixel($Plots[0],$Plots[1],$this->Palette[$Key]["R"]+$ColorFactor,$this->Palette[$Key]["G"]+$ColorFactor,$this->Palette[$Key]["B"]+$ColorFactor);
\r
2209 $this->drawAntialiasPixel($Plots[2],$Plots[3],$this->Palette[$Key]["R"]+$ColorFactor,$this->Palette[$Key]["G"]+$ColorFactor,$this->Palette[$Key]["B"]+$ColorFactor);
\r
2210 $this->drawAntialiasPixel($Plots[$Index-4],$Plots[$Index-3],$this->Palette[$Key]["R"]+$ColorFactor,$this->Palette[$Key]["G"]+$ColorFactor,$this->Palette[$Key]["B"]+$ColorFactor);
\r
2214 /* Draw Top polygons */
\r
2215 for($Key=count($iValues)-1;$Key>=0;$Key--)
\r
2217 $C_GraphLo = $this->AllocateColor($this->Picture,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"]);
\r
2218 imagefilledpolygon($this->Picture,$TopPlots[$Key],(count($TopPlots[$Key])+1)/2,$C_GraphLo);
\r
2220 if ( $EnhanceColors ) { $En = 10; } else { $En = 5; }
\r
2221 for($j=0;$j<=count($TopPlots[$Key])-4;$j=$j+2)
\r
2222 $this->drawLine($TopPlots[$Key][$j],$TopPlots[$Key][$j+1],$TopPlots[$Key][$j+2],$TopPlots[$Key][$j+3],$this->Palette[$Key]["R"]+$En,$this->Palette[$Key]["G"]+$En,$this->Palette[$Key]["B"]+$En);
\r
2226 /* This function can be used to set the background color */
\r
2227 function drawBackground($R,$G,$B)
\r
2229 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2230 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2231 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2233 $C_Background = imagecolorallocate($this->Picture,$R,$G,$B);
\r
2234 imagefilledrectangle($this->Picture,0,0,$this->XSize,$this->YSize,$C_Background);
\r
2237 /* This function can be used to set the background color */
\r
2238 function drawGraphAreaGradient($R,$G,$B,$Decay,$Target=TARGET_GRAPHAREA)
\r
2240 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2241 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2242 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2244 if ( $Target == TARGET_GRAPHAREA ) { $X1 = $this->GArea_X1+1; $X2 = $this->GArea_X2-1; $Y1 = $this->GArea_Y1+1; $Y2 = $this->GArea_Y2; }
\r
2245 if ( $Target == TARGET_BACKGROUND ) { $X1 = 0; $X2 = $this->XSize; $Y1 = 0; $Y2 = $this->YSize; }
\r
2247 $YStep = ($Y2 - $Y1 - 2) / $Decay;
\r
2248 for($i=0;$i<=$Decay;$i++)
\r
2250 $R-=1;$G-=1;$B-=1;
\r
2251 $Yi1 = $Y1 + ( $i * $YStep );
\r
2252 $Yi2 = ceil( $Yi1 + ( $i * $YStep ) + $YStep );
\r
2253 if ( $Yi2 >= $Yi2 ) { $Yi2 = $Y2-1; }
\r
2255 $C_Background = $this->AllocateColor($this->Picture,$R,$G,$B);
\r
2256 imagefilledrectangle($this->Picture,$X1,$Yi1,$X2,$Yi2,$C_Background);
\r
2260 /* This function create a rectangle with antialias */
\r
2261 function drawRectangle($X1,$Y1,$X2,$Y2,$R,$G,$B)
\r
2263 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2264 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2265 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2267 $C_Rectangle = imagecolorallocate($this->Picture,$R,$G,$B);
\r
2269 $X1=$X1-.2;$Y1=$Y1-.2;
\r
2270 $X2=$X2+.2;$Y2=$Y2+.2;
\r
2271 $this->drawLine($X1,$Y1,$X2,$Y1,$R,$G,$B);
\r
2272 $this->drawLine($X2,$Y1,$X2,$Y2,$R,$G,$B);
\r
2273 $this->drawLine($X2,$Y2,$X1,$Y2,$R,$G,$B);
\r
2274 $this->drawLine($X1,$Y2,$X1,$Y1,$R,$G,$B);
\r
2277 /* This function create a filled rectangle with antialias */
\r
2278 function drawFilledRectangle($X1,$Y1,$X2,$Y2,$R,$G,$B,$DrawBorder=TRUE,$Alpha=100)
\r
2280 if ( $X2 > $X1 ) { list($X1, $X2) = array($X2, $X1); }
\r
2281 if ( $Y2 > $Y1 ) { list($Y1, $Y2) = array($Y2, $Y1); }
\r
2283 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2284 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2285 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2287 if ( $Alpha == 100 )
\r
2289 $C_Rectangle = imagecolorallocate($this->Picture,$R,$G,$B);
\r
2290 imagefilledrectangle($this->Picture,$X1,$Y1,$X2,$Y2,$C_Rectangle);
\r
2294 $LayerWidth = abs($X2-$X1)+2;
\r
2295 $LayerHeight = abs($Y2-$Y1)+2;
\r
2297 $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight);
\r
2298 $C_White = imagecolorallocate($this->Layers[0],255,255,255);
\r
2299 imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White);
\r
2300 imagecolortransparent($this->Layers[0],$C_White);
\r
2302 $C_Rectangle = imagecolorallocate($this->Layers[0],$R,$G,$B);
\r
2303 imagefilledrectangle($this->Layers[0],1,1,$LayerWidth-1,$LayerHeight-1,$C_Rectangle);
\r
2305 imagecopymerge($this->Picture,$this->Layers[0],min($X1,$X2)-1,min($Y1,$Y2)-1,0,0,$LayerWidth,$LayerHeight,$Alpha);
\r
2306 imagedestroy($this->Layers[0]);
\r
2309 if ( $DrawBorder )
\r
2310 $this->drawRectangle($X1,$Y1,$X2,$Y2,$R,$G,$B);
\r
2313 /* This function create a rectangle with rounded corners and antialias */
\r
2314 function drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$R,$G,$B)
\r
2316 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2317 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2318 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2320 $C_Rectangle = imagecolorallocate($this->Picture,$R,$G,$B);
\r
2322 $Step = 90 / ((3.1418 * $Radius)/2);
\r
2324 for($i=0;$i<=90;$i=$i+$Step)
\r
2326 $X = cos(($i+180)*3.1418/180) * $Radius + $X1 + $Radius;
\r
2327 $Y = sin(($i+180)*3.1418/180) * $Radius + $Y1 + $Radius;
\r
2328 $this->drawAntialiasPixel($X,$Y,$R,$G,$B);
\r
2330 $X = cos(($i-90)*3.1418/180) * $Radius + $X2 - $Radius;
\r
2331 $Y = sin(($i-90)*3.1418/180) * $Radius + $Y1 + $Radius;
\r
2332 $this->drawAntialiasPixel($X,$Y,$R,$G,$B);
\r
2334 $X = cos(($i)*3.1418/180) * $Radius + $X2 - $Radius;
\r
2335 $Y = sin(($i)*3.1418/180) * $Radius + $Y2 - $Radius;
\r
2336 $this->drawAntialiasPixel($X,$Y,$R,$G,$B);
\r
2338 $X = cos(($i+90)*3.1418/180) * $Radius + $X1 + $Radius;
\r
2339 $Y = sin(($i+90)*3.1418/180) * $Radius + $Y2 - $Radius;
\r
2340 $this->drawAntialiasPixel($X,$Y,$R,$G,$B);
\r
2343 $X1=$X1-.2;$Y1=$Y1-.2;
\r
2344 $X2=$X2+.2;$Y2=$Y2+.2;
\r
2345 $this->drawLine($X1+$Radius,$Y1,$X2-$Radius,$Y1,$R,$G,$B);
\r
2346 $this->drawLine($X2,$Y1+$Radius,$X2,$Y2-$Radius,$R,$G,$B);
\r
2347 $this->drawLine($X2-$Radius,$Y2,$X1+$Radius,$Y2,$R,$G,$B);
\r
2348 $this->drawLine($X1,$Y2-$Radius,$X1,$Y1+$Radius,$R,$G,$B);
\r
2351 /* This function create a filled rectangle with rounded corners and antialias */
\r
2352 function drawFilledRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$R,$G,$B)
\r
2354 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2355 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2356 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2358 $C_Rectangle = imagecolorallocate($this->Picture,$R,$G,$B);
\r
2360 $Step = 90 / ((3.1418 * $Radius)/2);
\r
2362 for($i=0;$i<=90;$i=$i+$Step)
\r
2364 $Xi1 = cos(($i+180)*3.1418/180) * $Radius + $X1 + $Radius;
\r
2365 $Yi1 = sin(($i+180)*3.1418/180) * $Radius + $Y1 + $Radius;
\r
2367 $Xi2 = cos(($i-90)*3.1418/180) * $Radius + $X2 - $Radius;
\r
2368 $Yi2 = sin(($i-90)*3.1418/180) * $Radius + $Y1 + $Radius;
\r
2370 $Xi3 = cos(($i)*3.1418/180) * $Radius + $X2 - $Radius;
\r
2371 $Yi3 = sin(($i)*3.1418/180) * $Radius + $Y2 - $Radius;
\r
2373 $Xi4 = cos(($i+90)*3.1418/180) * $Radius + $X1 + $Radius;
\r
2374 $Yi4 = sin(($i+90)*3.1418/180) * $Radius + $Y2 - $Radius;
\r
2376 imageline($this->Picture,$Xi1,$Yi1,$X1+$Radius,$Yi1,$C_Rectangle);
\r
2377 imageline($this->Picture,$X2-$Radius,$Yi2,$Xi2,$Yi2,$C_Rectangle);
\r
2378 imageline($this->Picture,$X2-$Radius,$Yi3,$Xi3,$Yi3,$C_Rectangle);
\r
2379 imageline($this->Picture,$Xi4,$Yi4,$X1+$Radius,$Yi4,$C_Rectangle);
\r
2381 $this->drawAntialiasPixel($Xi1,$Yi1,$R,$G,$B);
\r
2382 $this->drawAntialiasPixel($Xi2,$Yi2,$R,$G,$B);
\r
2383 $this->drawAntialiasPixel($Xi3,$Yi3,$R,$G,$B);
\r
2384 $this->drawAntialiasPixel($Xi4,$Yi4,$R,$G,$B);
\r
2387 imagefilledrectangle($this->Picture,$X1,$Y1+$Radius,$X2,$Y2-$Radius,$C_Rectangle);
\r
2388 imagefilledrectangle($this->Picture,$X1+$Radius,$Y1,$X2-$Radius,$Y2,$C_Rectangle);
\r
2390 $X1=$X1-.2;$Y1=$Y1-.2;
\r
2391 $X2=$X2+.2;$Y2=$Y2+.2;
\r
2392 $this->drawLine($X1+$Radius,$Y1,$X2-$Radius,$Y1,$R,$G,$B);
\r
2393 $this->drawLine($X2,$Y1+$Radius,$X2,$Y2-$Radius,$R,$G,$B);
\r
2394 $this->drawLine($X2-$Radius,$Y2,$X1+$Radius,$Y2,$R,$G,$B);
\r
2395 $this->drawLine($X1,$Y2-$Radius,$X1,$Y1+$Radius,$R,$G,$B);
\r
2398 /* This function create a circle with antialias */
\r
2399 function drawCircle($Xc,$Yc,$Height,$R,$G,$B,$Width=0)
\r
2401 if ( $Width == 0 ) { $Width = $Height; }
\r
2402 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2403 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2404 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2406 $C_Circle = imagecolorallocate($this->Picture,$R,$G,$B);
\r
2407 $Step = 360 / (2 * 3.1418 * max($Width,$Height));
\r
2409 for($i=0;$i<=360;$i=$i+$Step)
\r
2411 $X = cos($i*3.1418/180) * $Height + $Xc;
\r
2412 $Y = sin($i*3.1418/180) * $Width + $Yc;
\r
2413 $this->drawAntialiasPixel($X,$Y,$R,$G,$B);
\r
2417 /* This function create a filled circle/ellipse with antialias */
\r
2418 function drawFilledCircle($Xc,$Yc,$Height,$R,$G,$B,$Width=0)
\r
2420 if ( $Width == 0 ) { $Width = $Height; }
\r
2421 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2422 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2423 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2425 $C_Circle = imagecolorallocate($this->Picture,$R,$G,$B);
\r
2426 $Step = 360 / (2 * 3.1418 * max($Width,$Height));
\r
2428 for($i=90;$i<=270;$i=$i+$Step)
\r
2430 $X1 = cos($i*3.1418/180) * $Height + $Xc;
\r
2431 $Y1 = sin($i*3.1418/180) * $Width + $Yc;
\r
2432 $X2 = cos((180-$i)*3.1418/180) * $Height + $Xc;
\r
2433 $Y2 = sin((180-$i)*3.1418/180) * $Width + $Yc;
\r
2435 $this->drawAntialiasPixel($X1-1,$Y1-1,$R,$G,$B);
\r
2436 $this->drawAntialiasPixel($X2-1,$Y2-1,$R,$G,$B);
\r
2438 if ( ($Y1-1) > $Yc - max($Width,$Height) )
\r
2439 imageline($this->Picture,$X1,$Y1-1,$X2-1,$Y2-1,$C_Circle);
\r
2443 /* This function will draw a filled ellipse */
\r
2444 function drawEllipse($Xc,$Yc,$Height,$Width,$R,$G,$B)
\r
2445 { $this->drawCircle($Xc,$Yc,$Height,$R,$G,$B,$Width); }
\r
2447 /* This function will draw an ellipse */
\r
2448 function drawFilledEllipse($Xc,$Yc,$Height,$Width,$R,$G,$B)
\r
2449 { $this->drawFilledCircle($Xc,$Yc,$Height,$R,$G,$B,$Width); }
\r
2451 /* This function create a line with antialias */
\r
2452 function drawLine($X1,$Y1,$X2,$Y2,$R,$G,$B,$GraphFunction=FALSE)
\r
2454 if ( $this->LineDotSize > 1 ) { $this->drawDottedLine($X1,$Y1,$X2,$Y2,$this->LineDotSize,$R,$G,$B,$GraphFunction); return(0); }
\r
2455 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2456 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2457 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2459 $Distance = sqrt(($X2-$X1)*($X2-$X1)+($Y2-$Y1)*($Y2-$Y1));
\r
2460 if ( $Distance == 0 )
\r
2462 $XStep = ($X2-$X1) / $Distance;
\r
2463 $YStep = ($Y2-$Y1) / $Distance;
\r
2465 for($i=0;$i<=$Distance;$i++)
\r
2467 $X = $i * $XStep + $X1;
\r
2468 $Y = $i * $YStep + $Y1;
\r
2470 if ( ($X >= $this->GArea_X1 && $X <= $this->GArea_X2 && $Y >= $this->GArea_Y1 && $Y <= $this->GArea_Y2) || !$GraphFunction )
\r
2472 if ( $this->LineWidth == 1 )
\r
2473 $this->drawAntialiasPixel($X,$Y,$R,$G,$B);
\r
2476 $StartOffset = -($this->LineWidth/2); $EndOffset = ($this->LineWidth/2);
\r
2477 for($j=$StartOffset;$j<=$EndOffset;$j++)
\r
2478 $this->drawAntialiasPixel($X+$j,$Y+$j,$R,$G,$B);
\r
2484 /* This function create a line with antialias */
\r
2485 function drawDottedLine($X1,$Y1,$X2,$Y2,$DotSize,$R,$G,$B,$GraphFunction=FALSE)
\r
2487 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2488 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2489 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2491 $Distance = sqrt(($X2-$X1)*($X2-$X1)+($Y2-$Y1)*($Y2-$Y1));
\r
2493 $XStep = ($X2-$X1) / $Distance;
\r
2494 $YStep = ($Y2-$Y1) / $Distance;
\r
2497 for($i=0;$i<=$Distance;$i++)
\r
2499 $X = $i * $XStep + $X1;
\r
2500 $Y = $i * $YStep + $Y1;
\r
2502 if ( $DotIndex <= $DotSize)
\r
2504 if ( ($X >= $this->GArea_X1 && $X <= $this->GArea_X2 && $Y >= $this->GArea_Y1 && $Y <= $this->GArea_Y2) || !$GraphFunction )
\r
2506 if ( $this->LineWidth == 1 )
\r
2507 $this->drawAntialiasPixel($X,$Y,$R,$G,$B);
\r
2510 $StartOffset = -($this->LineWidth/2); $EndOffset = ($this->LineWidth/2);
\r
2511 for($j=$StartOffset;$j<=$EndOffset;$j++)
\r
2512 $this->drawAntialiasPixel($X+$j,$Y+$j,$R,$G,$B);
\r
2518 if ( $DotIndex == $DotSize * 2 )
\r
2523 /* Load a PNG file and draw it over the chart */
\r
2524 function drawFromPNG($FileName,$X,$Y,$Alpha=100)
\r
2525 { $this->drawFromPicture(1,$FileName,$X,$Y,$Alpha); }
\r
2527 /* Load a GIF file and draw it over the chart */
\r
2528 function drawFromGIF($FileName,$X,$Y,$Alpha=100)
\r
2529 { $this->drawFromPicture(2,$FileName,$X,$Y,$Alpha); }
\r
2531 /* Load a JPEG file and draw it over the chart */
\r
2532 function drawFromJPG($FileName,$X,$Y,$Alpha=100)
\r
2533 { $this->drawFromPicture(3,$FileName,$X,$Y,$Alpha); }
\r
2535 /* Generic loader function for external pictures */
\r
2536 function drawFromPicture($PicType,$FileName,$X,$Y,$Alpha=100)
\r
2538 if ( file_exists($FileName))
\r
2540 $Infos = getimagesize($FileName);
\r
2541 $Width = $Infos[0];
\r
2542 $Height = $Infos[1];
\r
2543 if ( $PicType == 1 ) { $Raster = imagecreatefrompng($FileName); }
\r
2544 if ( $PicType == 2 ) { $Raster = imagecreatefromgif($FileName); }
\r
2545 if ( $PicType == 3 ) { $Raster = imagecreatefromjpeg($FileName); }
\r
2547 imagecopymerge($this->Picture,$Raster,$X,$Y,0,0,$Width,$Height,$Alpha);
\r
2548 imagedestroy($Raster);
\r
2552 /* Draw an alpha pixel */
\r
2553 function drawAlphaPixel($X,$Y,$Alpha,$R,$G,$B)
\r
2555 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2556 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2557 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2559 if ( $X < 0 || $Y < 0 || $X >= $this->XSize || $Y >= $this->YSize )
\r
2562 $RGB2 = imagecolorat($this->Picture, $X, $Y);
\r
2563 $R2 = ($RGB2 >> 16) & 0xFF;
\r
2564 $G2 = ($RGB2 >> 8) & 0xFF;
\r
2565 $B2 = $RGB2 & 0xFF;
\r
2567 $iAlpha = (100 - $Alpha)/100;
\r
2568 $Alpha = $Alpha / 100;
\r
2570 $Ra = floor($R*$Alpha+$R2*$iAlpha);
\r
2571 $Ga = floor($G*$Alpha+$G2*$iAlpha);
\r
2572 $Ba = floor($B*$Alpha+$B2*$iAlpha);
\r
2574 $C_Aliased = imagecolorallocate($this->Picture,$Ra,$Ga,$Ba);
\r
2575 imagesetpixel($this->Picture,$X,$Y,$C_Aliased);
\r
2578 /* Color helper */
\r
2579 function AllocateColor($Picture,$R,$G,$B,$Factor=0)
\r
2581 $R = $R + $Factor;
\r
2582 $G = $G + $Factor;
\r
2583 $B = $B + $Factor;
\r
2584 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2585 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2586 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2588 return(imagecolorallocate($Picture,$R,$G,$B));
\r
2591 /* Add a border to the picture */
\r
2592 function addBorder($Size=3,$R=0,$G=0,$B=0)
\r
2594 $Width = $this->XSize+2*$Size;
\r
2595 $Height = $this->YSize+2*$Size;
\r
2597 $Resampled = imagecreatetruecolor($Width,$Height);
\r
2598 $C_Background = imagecolorallocate($Resampled,$R,$G,$B);
\r
2599 imagefilledrectangle($Resampled,0,0,$Width,$Height,$C_Background);
\r
2601 imagecopy($Resampled,$this->Picture,$Size,$Size,0,0,$this->XSize,$this->YSize);
\r
2602 imagedestroy($this->Picture);
\r
2604 $this->XSize = $Width;
\r
2605 $this->YSize = $Height;
\r
2607 $this->Picture = imagecreatetruecolor($this->XSize,$this->YSize);
\r
2608 $C_White = imagecolorallocate($this->Picture,255,255,255);
\r
2609 imagefilledrectangle($this->Picture,0,0,$this->XSize,$this->YSize,$C_White);
\r
2610 imagecolortransparent($this->Picture,$C_White);
\r
2611 imagecopy($this->Picture,$Resampled,0,0,0,0,$this->XSize,$this->YSize);
\r
2614 /* Render the current picture to a file */
\r
2615 function Render($FileName)
\r
2617 if ( $this->ErrorReporting )
\r
2618 $this->printErrors($this->ErrorInterface);
\r
2620 /* Save image map if requested */
\r
2621 if ( $this->BuildMap )
\r
2622 $this->SaveImageMap();
\r
2624 imagepng($this->Picture,$FileName);
\r
2627 /* Render the current picture to STDOUT */
\r
2630 if ( $this->ErrorReporting )
\r
2631 $this->printErrors("GD");
\r
2633 /* Save image map if requested */
\r
2634 if ( $this->BuildMap )
\r
2635 $this->SaveImageMap();
\r
2637 header('Content-type: image/png');
\r
2638 imagepng($this->Picture);
\r
2641 /* Private functions for internal processing */
\r
2642 function drawAntialiasPixel($X,$Y,$R,$G,$B)
\r
2644 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
\r
2645 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
\r
2646 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
\r
2652 if ( $Xi == $X && $Yi == $Y)
\r
2654 /* $this->drawAlphaPixel($Xi,$Yi,0,$R,$G,$B); */
\r
2655 $C_Aliased = imagecolorallocate($this->Picture,$R,$G,$B);
\r
2656 imagesetpixel($this->Picture,$X,$Y,$C_Aliased);
\r
2660 $Alpha1 = (1 - ($X - floor($X))) * (1 - ($Y - floor($Y))) * 100;
\r
2661 if ( $Alpha1 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi,$Yi,$Alpha1,$R,$G,$B); }
\r
2663 $Alpha2 = ($X - floor($X)) * (1 - ($Y - floor($Y))) * 100;
\r
2664 if ( $Alpha2 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi+1,$Yi,$Alpha2,$R,$G,$B); }
\r
2666 $Alpha3 = (1 - ($X - floor($X))) * ($Y - floor($Y)) * 100;
\r
2667 if ( $Alpha3 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi,$Yi+1,$Alpha3,$R,$G,$B); }
\r
2669 $Alpha4 = ($X - floor($X)) * ($Y - floor($Y)) * 100;
\r
2670 if ( $Alpha4 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi+1,$Yi+1,$Alpha4,$R,$G,$B); }
\r
2674 /* Validate data contained in the description array */
\r
2675 function validateDataDescription($FunctionName,&$DataDescription,$DescriptionRequired=TRUE)
\r
2677 if (!isset($DataDescription["Position"]))
\r
2679 $this->Errors[] = "[Warning] ".$FunctionName." - Y Labels are not set.";
\r
2680 $DataDescription["Position"] = "Name";
\r
2683 if ( $DescriptionRequired )
\r
2685 if (!isset($DataDescription["Description"]))
\r
2687 $this->Errors[] = "[Warning] ".$FunctionName." - Series descriptions are not set.";
\r
2688 foreach($DataDescription["Values"] as $key => $Value)
\r
2690 $DataDescription["Description"][$Value] = $Value;
\r
2694 if (count($DataDescription["Description"]) < count($DataDescription["Values"]))
\r
2696 $this->Errors[] = "[Warning] ".$FunctionName." - Some series descriptions are not set.";
\r
2697 foreach($DataDescription["Values"] as $key => $Value)
\r
2699 if ( !isset($DataDescription["Description"][$Value]))
\r
2700 $DataDescription["Description"][$Value] = $Value;
\r
2706 /* Validate data contained in the data array */
\r
2707 function validateData($FunctionName,&$Data)
\r
2709 $DataSummary = "";
\r
2711 foreach($Data as $key => $Values)
\r
2713 foreach($Values as $key2 => $Value)
\r
2715 if (!isset($DataSummary[$key2]))
\r
2716 $DataSummary[$key2] = 1;
\r
2718 $DataSummary[$key2]++;
\r
2722 if ( max($DataSummary) == 0 )
\r
2723 $this->Errors[] = "[Warning] ".$FunctionName." - No data set.";
\r
2725 foreach($DataSummary as $key => $Value)
\r
2727 if ($Value < max($DataSummary))
\r
2729 $this->Errors[] = "[Warning] ".$FunctionName." - Missing data in serie ".$key.".";
\r
2734 /* Print all error messages on the CLI or graphically */
\r
2735 function printErrors($Mode="CLI")
\r
2737 if (count($this->Errors) == 0)
\r
2740 if ( $Mode == "CLI" )
\r
2742 foreach($this->Errors as $key => $Value)
\r
2743 echo $Value."\r\n";
\r
2745 elseif ( $Mode == "GD" )
\r
2747 $this->setLineStyle($Width=1);
\r
2749 foreach($this->Errors as $key => $Value)
\r
2751 $Position = imageftbbox($this->ErrorFontSize,0,$this->ErrorFontName,$Value,$bogus);
\r
2752 $TextWidth = $Position[2]-$Position[0];
\r
2753 if ( $TextWidth > $MaxWidth ) { $MaxWidth = $TextWidth; }
\r
2755 $this->drawFilledRoundedRectangle($this->XSize-($MaxWidth+20),$this->YSize-(20+(($this->ErrorFontSize+4)*count($this->Errors))),$this->XSize-10,$this->YSize-10,6,233,185,185);
\r
2756 $this->drawRoundedRectangle($this->XSize-($MaxWidth+20),$this->YSize-(20+(($this->ErrorFontSize+4)*count($this->Errors))),$this->XSize-10,$this->YSize-10,6,193,145,145);
\r
2758 $C_TextColor = imagecolorallocate($this->Picture,133,85,85);
\r
2759 $YPos = $this->YSize - (18 + (count($this->Errors)-1) * ($this->ErrorFontSize + 4));
\r
2760 foreach($this->Errors as $key => $Value)
\r
2762 imagettftext($this->Picture,$this->ErrorFontSize,0,$this->XSize-($MaxWidth+15),$YPos,$C_TextColor,$this->ErrorFontName,$Value);
\r
2763 $YPos = $YPos + ($this->ErrorFontSize + 4);
\r
2768 /* Activate the image map creation process */
\r
2769 function setImageMap($Mode=TRUE,$GraphID="MyGraph")
\r
2771 $this->BuildMap = $Mode;
\r
2772 $this->MapID = $GraphID;
\r
2775 /* Add a box into the image map */
\r
2776 function addToImageMap($X1,$Y1,$X2,$Y2,$SerieName,$Value,$CallerFunction)
\r
2778 if ( $this->MapFunction == NULL || $this->MapFunction == $CallerFunction )
\r
2780 $this->ImageMap[] = round($X1).",".round($Y1).",".round($X2).",".round($Y2).",".$SerieName.",".$Value;
\r
2781 $this->MapFunction = $CallerFunction;
\r
2785 /* Load and cleanup the image map from disk */
\r
2786 function getImageMap($MapName,$Flush=TRUE)
\r
2788 /* Strip HTML query strings */
\r
2789 $Values = $this->tmpFolder.$MapName;
\r
2790 $Value = split("\?",$Values);
\r
2791 $FileName = $Value[0];
\r
2793 if ( file_exists($FileName) )
\r
2795 $Handle = fopen($FileName, "r");
\r
2796 $MapContent = fread($Handle, filesize($FileName));
\r
2801 unlink($FileName);
\r
2807 header("HTTP/1.0 404 Not Found");
\r
2812 /* Save the image map to the disk */
\r
2813 function SaveImageMap()
\r
2815 if ( !$this->BuildMap ) { return(-1); }
\r
2817 if ( $this->ImageMap == NULL )
\r
2819 $this->Errors[] = "[Warning] SaveImageMap - Image map is empty.";
\r
2823 $Handle = fopen($this->tmpFolder.$this->MapID, 'w');
\r
2826 $this->Errors[] = "[Warning] SaveImageMap - Cannot save the image map.";
\r
2831 foreach($this->ImageMap as $Key => $Value)
\r
2832 fwrite($Handle, htmlentities($Value)."\r");
\r
2837 /* Convert seconds to a time format string */
\r
2838 function ToTime($Value)
\r
2840 $Hour = floor($Value/3600);
\r
2841 $Minute = floor(($Value - $Hour*3600)/60);
\r
2842 $Second = floor($Value - $Hour*3600 - $Minute*60);
\r
2844 if (strlen($Hour) == 1 ) { $Hour = "0".$Hour; }
\r
2845 if (strlen($Minute) == 1 ) { $Minute = "0".$Minute; }
\r
2846 if (strlen($Second) == 1 ) { $Second = "0".$Second; }
\r
2848 return($Hour.":".$Minute.":".$Second);
\r
2851 /* Convert to metric system */
\r
2852 function ToMetric($Value)
\r
2854 $Go = floor($Value/1000000000);
\r
2855 $Mo = floor(($Value - $Go*1000000000)/1000000);
\r
2856 $Ko = floor(($Value - $Go*1000000000 - $Mo*1000000)/1000);
\r
2857 $o = floor($Value - $Go*1000000000 - $Mo*1000000 - $Ko*1000);
\r
2859 if ($Go != 0) { return($Go.".".$Mo."g"); }
\r
2860 if ($Mo != 0) { return($Mo.".".$ko."m"); }
\r
2861 if ($Ko != 0) { return($Ko.".".$o)."k"; }
\r
2865 /* Set date format for axis labels */
\r
2866 function setDateFormat($Format)
\r
2868 $this->DateFormat = $Format;
\r
2871 /* Convert TS to a date format string */
\r
2872 function ToDate($Value)
\r
2874 return(date($this->DateFormat,$Value));
\r
2878 function RaiseFatal($Message)
\r
2880 echo "[FATAL] ".$Message."\r\n";
\r