1<?php 2 /* 3 pChart - a PHP class to build charts! 4 Copyright (C) 2008 Jean-Damien POGOLOTTI 5 Version 1.27d last updated on 09/30/08 6 7 http://pchart.sourceforge.net 8 9 This program is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 1,2,3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21 22 Class initialisation : 23 pChart($XSize,$YSize) 24 Draw methods : 25 drawBackground($R,$G,$B) 26 drawRectangle($X1,$Y1,$X2,$Y2,$R,$G,$B) 27 drawFilledRectangle($X1,$Y1,$X2,$Y2,$R,$G,$B,$DrawBorder=TRUE,$Alpha=100) 28 drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$R,$G,$B) 29 drawFilledRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$R,$G,$B) 30 drawCircle($Xc,$Yc,$Height,$R,$G,$B,$Width=0) 31 drawFilledCircle($Xc,$Yc,$Height,$R,$G,$B,$Width=0) 32 drawEllipse($Xc,$Yc,$Height,$Width,$R,$G,$B) 33 drawFilledEllipse($Xc,$Yc,$Height,$Width,$R,$G,$B) 34 drawLine($X1,$Y1,$X2,$Y2,$R,$G,$B,$GraphFunction=FALSE) 35 drawDottedLine($X1,$Y1,$X2,$Y2,$DotSize,$R,$G,$B) 36 drawAlphaPixel($X,$Y,$Alpha,$R,$G,$B) 37 drawFromPNG($FileName,$X,$Y,$Alpha=100) 38 drawFromGIF($FileName,$X,$Y,$Alpha=100) 39 drawFromJPG($FileName,$X,$Y,$Alpha=100) 40 Graph setup methods : 41 addBorder($Width=3,$R=0,$G=0,$B=0) 42 clearScale() 43 clearShadow() 44 createColorGradientPalette($R1,$G1,$B1,$R2,$G2,$B2,$Shades) 45 drawGraphArea($R,$G,$B,$Stripe=FALSE) 46 drawScale($Data,$DataDescription,$ScaleMode,$R,$G,$B,$DrawTicks=TRUE,$Angle=0,$Decimals=1,$WithMargin=FALSE,$SkipLabels=1,$RightScale=FALSE) 47 drawRightScale($Data,$DataDescription,$ScaleMode,$R,$G,$B,$DrawTicks=TRUE,$Angle=0,$Decimals=1,$WithMargin=FALSE,$SkipLabels=1) 48 drawXYScale($Data,$DataDescription,$YSerieName,$XSerieName,$R,$G,$B,$WithMargin=0,$Angle=0,$Decimals=1) 49 drawGrid($LineWidth,$Mosaic=TRUE,$R=220,$G=220,$B=220,$Alpha=100) 50 drawLegend($XPos,$YPos,$DataDescription,$R,$G,$B,$Rs=-1,$Gs=-1,$Bs=-1,$Rt=0,$Gt=0,$Bt=0,$Border=FALSE) 51 drawPieLegend($XPos,$YPos,$Data,$DataDescription,$R,$G,$B) 52 drawTitle($XPos,$YPos,$Value,$R,$G,$B,$XPos2=-1,$YPos2=-1,$Shadow=FALSE) 53 drawTreshold($Value,$R,$G,$B,$ShowLabel=FALSE,$ShowOnRight=FALSE,$TickWidth=4,$FreeText=NULL) 54 drawArea($Data,$Serie1,$Serie2,$R,$G,$B,$Alpha = 50) 55 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) 56 drawGraphAreaGradient($R,$G,$B,$Decay,$Target=TARGET_GRAPHAREA) 57 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) 58 getLegendBoxSize($DataDescription) 59 loadColorPalette($FileName,$Delimiter=",") 60 reportWarnings($Interface="CLI") 61 setGraphArea($X1,$Y1,$X2,$Y2) 62 setLabel($Data,$DataDescription,$SerieName,$ValueName,$Caption,$R=210,$G=210,$B=210) 63 setColorPalette($ID,$R,$G,$B) 64 setCurrency($Currency) 65 setDateFormat($Format) 66 setFontProperties($FontName,$FontSize) 67 setLineStyle($Width=1,$DotSize=0) 68 setFixedScale($VMin,$VMax,$Divisions=5,$VXMin=0,$VXMin=0,$XDivisions=5) 69 setShadowProperties($XDistance=1,$YDistance=1,$R=60,$G=60,$B=60,$Alpha) 70 writeValues($Data,$DataDescription,$Series) 71 Graphs methods : 72 drawPlotGraph($Data,$DataDescription,$BigRadius=5,$SmallRadius=2,$R2=-1,$G2=-1,$B2=-1,$Shadow=FALSE) 73 drawXYPlotGraph($Data,$DataDescription,$YSerieName,$XSerieName,$PaletteID=0,$BigRadius=5,$SmallRadius=2,$R2=-1,$G2=-1,$B2=-1) 74 drawLineGraph($Data,$DataDescription,$SerieName="") 75 drawXYGraph($Data,$DataDescription,$YSerieName,$XSerieName,$PaletteID=0) 76 drawFilledLineGraph($Data,$DataDescription,$Alpha=100,$AroundZero=FALSE) 77 drawCubicCurve($Data,$DataDescription,$Accuracy=.1,$SerieName="") 78 drawFilledCubicCurve($Data,$DataDescription,$Accuracy=.1,$Alpha=100,$AroundZero=FALSE) 79 drawOverlayBarGraph($Data,$DataDescription,$Alpha=50) 80 drawBarGraph($Data,$DataDescription,$Shadow=FALSE) 81 drawStackedBarGraph($Data,$DataDescription,$Alpha=50,$Contiguous=FALSE) 82 drawLimitsGraph($Data,$DataDescription,$R=0,$G=0,$B=0) 83 drawRadar($Data,$DataDescription,$BorderOffset=10,$MaxValue=-1) 84 drawFilledRadar($Data,$DataDescription,$Alpha=50,$BorderOffset=10,$MaxValue=-1) 85 drawBasicPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$R=255,$G=255,$B=255,$Decimals=0) 86 drawFlatPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$SpliceDistance=0,$Decimals = 0) 87 drawFlatPieGraphWithShadow($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$SpliceDistance=0,$Decimals = 0) 88 drawPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$EnhanceColors=TRUE,$Skew=60,$SpliceHeight=20,$SpliceDistance=0,$Decimals=0) 89 Other methods : 90 setImageMap($Mode=TRUE,$GraphID="MyGraph") 91 getImageMap($MapName,$Flush=TRUE) 92 Render($FileName) 93 Stroke() 94 */ 95 96 /* Declare some script wide constants */ 97 define("SCALE_NORMAL",1); 98 define("SCALE_ADDALL",2); 99 define("SCALE_START0",3); 100 define("SCALE_ADDALLSTART0",4); 101 define("PIE_PERCENTAGE", 1); 102 define("PIE_LABELS",2); 103 define("PIE_NOLABEL",3); 104 define("PIE_PERCENTAGE_LABEL", 4); 105 define("TARGET_GRAPHAREA",1); 106 define("TARGET_BACKGROUND",2); 107 define("ALIGN_TOP_LEFT",1); 108 define("ALIGN_TOP_CENTER",2); 109 define("ALIGN_TOP_RIGHT",3); 110 define("ALIGN_LEFT",4); 111 define("ALIGN_CENTER",5); 112 define("ALIGN_RIGHT",6); 113 define("ALIGN_BOTTOM_LEFT",7); 114 define("ALIGN_BOTTOM_CENTER",8); 115 define("ALIGN_BOTTOM_RIGHT",9); 116 117 /* pChart class definition */ 118 class pChart 119 { 120 /* Palettes definition */ 121 var $Palette = array("0"=>array("R"=>188,"G"=>224,"B"=>46), 122 "1"=>array("R"=>224,"G"=>100,"B"=>46), 123 "2"=>array("R"=>224,"G"=>214,"B"=>46), 124 "3"=>array("R"=>46,"G"=>151,"B"=>224), 125 "4"=>array("R"=>176,"G"=>46,"B"=>224), 126 "5"=>array("R"=>224,"G"=>46,"B"=>117), 127 "6"=>array("R"=>92,"G"=>224,"B"=>46), 128 "7"=>array("R"=>224,"G"=>176,"B"=>46)); 129 130 /* Some static vars used in the class */ 131 var $XSize = NULL; 132 var $YSize = NULL; 133 var $Picture = NULL; 134 var $ImageMap = NULL; 135 136 /* Error management */ 137 var $ErrorReporting = FALSE; 138 var $ErrorInterface = "CLI"; 139 var $Errors = NULL; 140 var $ErrorFontName = "Fonts/pf_arma_five.ttf"; 141 var $ErrorFontSize = 6; 142 143 /* vars related to the graphing area */ 144 var $GArea_X1 = NULL; 145 var $GArea_Y1 = NULL; 146 var $GArea_X2 = NULL; 147 var $GArea_Y2 = NULL; 148 var $GAreaXOffset = NULL; 149 var $VMax = NULL; 150 var $VMin = NULL; 151 var $VXMax = NULL; 152 var $VXMin = NULL; 153 var $Divisions = NULL; 154 var $XDivisions = NULL; 155 var $DivisionHeight = NULL; 156 var $XDivisionHeight = NULL; 157 var $DivisionCount = NULL; 158 var $XDivisionCount = NULL; 159 var $DivisionRatio = NULL; 160 var $XDivisionRatio = NULL; 161 var $DivisionWidth = NULL; 162 var $DataCount = NULL; 163 var $Currency = "\$"; 164 165 /* Text format related vars */ 166 var $FontName = NULL; 167 var $FontSize = NULL; 168 var $DateFormat = "d/m/Y"; 169 170 /* Lines format related vars */ 171 var $LineWidth = 1; 172 var $LineDotSize = 0; 173 174 /* Layer related vars */ 175 var $Layers = NULL; 176 177 /* Set antialias quality : 0 is maximum, 100 minimum*/ 178 var $AntialiasQuality = 0; 179 180 /* Shadow settings */ 181 var $ShadowActive = FALSE; 182 var $ShadowXDistance = 1; 183 var $ShadowYDistance = 1; 184 var $ShadowRColor = 60; 185 var $ShadowGColor = 60; 186 var $ShadowBColor = 60; 187 var $ShadowAlpha = 50; 188 var $ShadowBlur = 0; 189 190 /* Image Map settings */ 191 var $BuildMap = FALSE; 192 var $MapFunction = NULL; 193 var $tmpFolder = "tmp/"; 194 var $MapID = NULL; 195 196 /* This function create the background picture */ 197 function pChart($XSize,$YSize) 198 { 199 $this->XSize = $XSize; 200 $this->YSize = $YSize; 201 $this->Picture = imagecreatetruecolor($XSize,$YSize); 202 203 $C_White =$this->AllocateColor($this->Picture,255,255,255); 204 imagefilledrectangle($this->Picture,0,0,$XSize,$YSize,$C_White); 205 imagecolortransparent($this->Picture,$C_White); 206 207 $this->setFontProperties("tahoma.ttf",8); 208 } 209 210 /* Set if warnings should be reported */ 211 function reportWarnings($Interface="CLI") 212 { 213 $this->ErrorReporting = TRUE; 214 $this->ErrorInterface = $Interface; 215 } 216 217 /* Set the font properties */ 218 function setFontProperties($FontName,$FontSize) 219 { 220 $this->FontName = $FontName; 221 $this->FontSize = $FontSize; 222 } 223 224 /* Set the shadow properties */ 225 function setShadowProperties($XDistance=1,$YDistance=1,$R=60,$G=60,$B=60,$Alpha=50,$Blur=0) 226 { 227 $this->ShadowActive = TRUE; 228 $this->ShadowXDistance = $XDistance; 229 $this->ShadowYDistance = $YDistance; 230 $this->ShadowRColor = $R; 231 $this->ShadowGColor = $G; 232 $this->ShadowBColor = $B; 233 $this->ShadowAlpha = $Alpha; 234 $this->ShadowBlur = $Blur; 235 } 236 237 /* Remove shadow option */ 238 function clearShadow() 239 { 240 $this->ShadowActive = FALSE; 241 } 242 243 /* Set Palette color */ 244 function setColorPalette($ID,$R,$G,$B) 245 { 246 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } 247 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } 248 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } 249 250 $this->Palette[$ID]["R"] = $R; 251 $this->Palette[$ID]["G"] = $G; 252 $this->Palette[$ID]["B"] = $B; 253 } 254 255 /* Create a color palette shading from one color to another */ 256 function createColorGradientPalette($R1,$G1,$B1,$R2,$G2,$B2,$Shades) 257 { 258 $RFactor = ($R2-$R1)/$Shades; 259 $GFactor = ($G2-$G1)/$Shades; 260 $BFactor = ($B2-$B1)/$Shades; 261 262 for($i=0;$i<=$Shades-1;$i++) 263 { 264 $this->Palette[$i]["R"] = $R1+$RFactor*$i; 265 $this->Palette[$i]["G"] = $G1+$GFactor*$i; 266 $this->Palette[$i]["B"] = $B1+$BFactor*$i; 267 } 268 } 269 270 /* Load Color Palette from file */ 271 function loadColorPalette($FileName,$Delimiter=",") 272 { 273 $handle = @fopen($FileName,"r"); 274 $ColorID = 0; 275 if ($handle) 276 { 277 while (!feof($handle)) 278 { 279 $buffer = fgets($handle, 4096); 280 $buffer = str_replace(chr(10),"",$buffer); 281 $buffer = str_replace(chr(13),"",$buffer); 282 $Values = split($Delimiter,$buffer); 283 if ( count($Values) == 3 ) 284 { 285 $this->Palette[$ColorID]["R"] = $Values[0]; 286 $this->Palette[$ColorID]["G"] = $Values[1]; 287 $this->Palette[$ColorID]["B"] = $Values[2]; 288 $ColorID++; 289 } 290 } 291 } 292 } 293 294 /* Set line style */ 295 function setLineStyle($Width=1,$DotSize=0) 296 { 297 $this->LineWidth = $Width; 298 $this->LineDotSize = $DotSize; 299 } 300 301 /* Set currency symbol */ 302 function setCurrency($Currency) 303 { 304 $this->Currency = $Currency; 305 } 306 307 /* Set the graph area location */ 308 function setGraphArea($X1,$Y1,$X2,$Y2) 309 { 310 $this->GArea_X1 = $X1; 311 $this->GArea_Y1 = $Y1; 312 $this->GArea_X2 = $X2; 313 $this->GArea_Y2 = $Y2; 314 } 315 316 /* Prepare the graph area */ 317 function drawGraphArea($R,$G,$B,$Stripe=FALSE) 318 { 319 $this->drawFilledRectangle($this->GArea_X1,$this->GArea_Y1,$this->GArea_X2,$this->GArea_Y2,$R,$G,$B,FALSE); 320 $this->drawRectangle($this->GArea_X1,$this->GArea_Y1,$this->GArea_X2,$this->GArea_Y2,$R-40,$G-40,$B-40); 321 322 if ( $Stripe ) 323 { 324 $R2 = $R-15; if ( $R2 < 0 ) { $R2 = 0; } 325 $G2 = $R-15; if ( $G2 < 0 ) { $G2 = 0; } 326 $B2 = $R-15; if ( $B2 < 0 ) { $B2 = 0; } 327 328 $LineColor =$this->AllocateColor($this->Picture,$R2,$G2,$B2); 329 $SkewWidth = $this->GArea_Y2-$this->GArea_Y1-1; 330 331 for($i=$this->GArea_X1-$SkewWidth;$i<=$this->GArea_X2;$i=$i+4) 332 { 333 $X1 = $i; $Y1 = $this->GArea_Y2; 334 $X2 = $i+$SkewWidth; $Y2 = $this->GArea_Y1; 335 336 337 if ( $X1 < $this->GArea_X1 ) 338 { $X1 = $this->GArea_X1; $Y1 = $this->GArea_Y1 + $X2 - $this->GArea_X1 + 1; } 339 340 if ( $X2 >= $this->GArea_X2 ) 341 { $Y2 = $this->GArea_Y1 + $X2 - $this->GArea_X2 +1; $X2 = $this->GArea_X2 - 1; } 342// * Fixed in 1.27 * { $X2 = $this->GArea_X2 - 1; $Y2 = $this->GArea_Y2 - ($this->GArea_X2 - $X1); } 343 344 imageline($this->Picture,$X1,$Y1,$X2,$Y2+1,$LineColor); 345 } 346 } 347 } 348 349 /* Allow you to clear the scale : used if drawing multiple charts */ 350 function clearScale() 351 { 352 $this->VMin = NULL; 353 $this->VMax = NULL; 354 $this->VXMin = NULL; 355 $this->VXMax = NULL; 356 $this->Divisions = NULL; 357 $this->XDivisions = NULL; } 358 359 /* Allow you to fix the scale, use this to bypass the automatic scaling */ 360 function setFixedScale($VMin,$VMax,$Divisions=5,$VXMin=0,$VXMax=0,$XDivisions=5) 361 { 362 $this->VMin = $VMin; 363 $this->VMax = $VMax; 364 $this->Divisions = $Divisions; 365 366 if ( !$VXMin == 0 ) 367 { 368 $this->VXMin = $VXMin; 369 $this->VXMax = $VXMax; 370 $this->XDivisions = $XDivisions; 371 } 372 } 373 374 /* Wrapper to the drawScale() function allowing a second scale to be drawn */ 375 function drawRightScale($Data,$DataDescription,$ScaleMode,$R,$G,$B,$DrawTicks=TRUE,$Angle=0,$Decimals=1,$WithMargin=FALSE,$SkipLabels=1) 376 { 377 $this->drawScale($Data,$DataDescription,$ScaleMode,$R,$G,$B,$DrawTicks,$Angle,$Decimals,$WithMargin,$SkipLabels,TRUE); 378 } 379 380 /* Compute and draw the scale */ 381 function drawScale($Data,$DataDescription,$ScaleMode,$R,$G,$B,$DrawTicks=TRUE,$Angle=0,$Decimals=1,$WithMargin=FALSE,$SkipLabels=1,$RightScale=FALSE) 382 { 383 /* Validate the Data and DataDescription array */ 384 $this->validateData("drawScale",$Data); 385 386 $C_TextColor =$this->AllocateColor($this->Picture,$R,$G,$B); 387 388 $this->drawLine($this->GArea_X1,$this->GArea_Y1,$this->GArea_X1,$this->GArea_Y2,$R,$G,$B); 389 $this->drawLine($this->GArea_X1,$this->GArea_Y2,$this->GArea_X2,$this->GArea_Y2,$R,$G,$B); 390 391 if ( $this->VMin == NULL && $this->VMax == NULL) 392 { 393 if (isset($DataDescription["Values"][0])) 394 { 395 $this->VMin = $Data[0][$DataDescription["Values"][0]]; 396 $this->VMax = $Data[0][$DataDescription["Values"][0]]; 397 } 398 else { $this->VMin = 2147483647; $this->VMax = -2147483647; } 399 400 /* Compute Min and Max values */ 401 if ( $ScaleMode == SCALE_NORMAL || $ScaleMode == SCALE_START0 ) 402 { 403 if ( $ScaleMode == SCALE_START0 ) { $this->VMin = 0; } 404 405 foreach ( $Data as $Key => $Values ) 406 { 407 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 408 { 409 if (isset($Data[$Key][$ColName])) 410 { 411 $Value = $Data[$Key][$ColName]; 412 413 if ( is_numeric($Value) ) 414 { 415 if ( $this->VMax < $Value) { $this->VMax = $Value; } 416 if ( $this->VMin > $Value) { $this->VMin = $Value; } 417 } 418 } 419 } 420 } 421 } 422 elseif ( $ScaleMode == SCALE_ADDALL || $ScaleMode == SCALE_ADDALLSTART0 ) /* Experimental */ 423 { 424 if ( $ScaleMode == SCALE_ADDALLSTART0 ) { $this->VMin = 0; } 425 426 foreach ( $Data as $Key => $Values ) 427 { 428 $Sum = 0; 429 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 430 { 431 if (isset($Data[$Key][$ColName])) 432 { 433 $Value = $Data[$Key][$ColName]; 434 if ( is_numeric($Value) ) 435 $Sum += $Value; 436 } 437 } 438 if ( $this->VMax < $Sum) { $this->VMax = $Sum; } 439 if ( $this->VMin > $Sum) { $this->VMin = $Sum; } 440 } 441 } 442 443 if ( $this->VMax > preg_replace('/\.[0-9]+/','',$this->VMax) ) 444 $this->VMax = preg_replace('/\.[0-9]+/','',$this->VMax)+1; 445 446 /* If all values are the same */ 447 if ( $this->VMax == $this->VMin ) 448 { 449 if ( $this->VMax >= 0 ) { $this->VMax++; } 450 else { $this->VMin--; } 451 } 452 453 $DataRange = $this->VMax - $this->VMin; 454 if ( $DataRange == 0 ) { $DataRange = .1; } 455 456 /* Compute automatic scaling */ 457 $ScaleOk = FALSE; $Factor = 1; 458 $MinDivHeight = 25; $MaxDivs = ($this->GArea_Y2 - $this->GArea_Y1) / $MinDivHeight; 459 460 if ( $this->VMin == 0 && $this->VMax == 0 ) 461 { $this->VMin = 0; $this->VMax = 2; $Scale = 1; $Divisions = 2;} 462 elseif ($MaxDivs > 1) 463 { 464 while(!$ScaleOk) 465 { 466 $Scale1 = ( $this->VMax - $this->VMin ) / $Factor; 467 $Scale2 = ( $this->VMax - $this->VMin ) / $Factor / 2; 468 $Scale4 = ( $this->VMax - $this->VMin ) / $Factor / 4; 469 470 if ( $Scale1 > 1 && $Scale1 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $Divisions = floor($Scale1); $Scale = 1;} 471 if ( $Scale2 > 1 && $Scale2 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $Divisions = floor($Scale2); $Scale = 2;} 472 if (!$ScaleOk) 473 { 474 if ( $Scale2 > 1 ) { $Factor = $Factor * 10; } 475 if ( $Scale2 < 1 ) { $Factor = $Factor / 10; } 476 } 477 } 478 479 if ( floor($this->VMax / $Scale / $Factor) != $this->VMax / $Scale / $Factor) 480 { 481 $GridID = floor ( $this->VMax / $Scale / $Factor) + 1; 482 $this->VMax = $GridID * $Scale * $Factor; 483 $Divisions++; 484 } 485 486 if ( floor($this->VMin / $Scale / $Factor) != $this->VMin / $Scale / $Factor) 487 { 488 $GridID = floor( $this->VMin / $Scale / $Factor); 489 $this->VMin = $GridID * $Scale * $Factor; 490 $Divisions++; 491 } 492 } 493 else /* Can occurs for small graphs */ 494 $Scale = 1; 495 496 if ( !isset($Divisions) ) 497 $Divisions = 2; 498 499 if ($Scale == 1 && $Divisions%2 == 1) 500 $Divisions--; 501 } 502 else 503 $Divisions = $this->Divisions; 504 505 $this->DivisionCount = $Divisions; 506 507 $DataRange = $this->VMax - $this->VMin; 508 if ( $DataRange == 0 ) { $DataRange = .1; } 509 510 $this->DivisionHeight = ( $this->GArea_Y2 - $this->GArea_Y1 ) / $Divisions; 511 $this->DivisionRatio = ( $this->GArea_Y2 - $this->GArea_Y1 ) / $DataRange; 512 513 $this->GAreaXOffset = 0; 514 if ( count($Data) > 1 ) 515 { 516 if ( $WithMargin == FALSE ) 517 $this->DivisionWidth = ( $this->GArea_X2 - $this->GArea_X1 ) / (count($Data)-1); 518 else 519 { 520 $this->DivisionWidth = ( $this->GArea_X2 - $this->GArea_X1 ) / (count($Data)); 521 $this->GAreaXOffset = $this->DivisionWidth / 2; 522 } 523 } 524 else 525 { 526 $this->DivisionWidth = $this->GArea_X2 - $this->GArea_X1; 527 $this->GAreaXOffset = $this->DivisionWidth / 2; 528 } 529 530 $this->DataCount = count($Data); 531 532 if ( $DrawTicks == FALSE ) 533 return(0); 534 535 $YPos = $this->GArea_Y2; $XMin = NULL; 536 for($i=1;$i<=$Divisions+1;$i++) 537 { 538 if ( $RightScale ) 539 $this->drawLine($this->GArea_X2,$YPos,$this->GArea_X2+5,$YPos,$R,$G,$B); 540 else 541 $this->drawLine($this->GArea_X1,$YPos,$this->GArea_X1-5,$YPos,$R,$G,$B); 542 543 $Value = $this->VMin + ($i-1) * (( $this->VMax - $this->VMin ) / $Divisions); 544 $Value = round($Value * pow(10,$Decimals)) / pow(10,$Decimals); 545 if ( $DataDescription["Format"]["Y"] == "number" ) 546 $Value = $Value.$DataDescription["Unit"]["Y"]; 547 if ( $DataDescription["Format"]["Y"] == "time" ) 548 $Value = $this->ToTime($Value); 549 if ( $DataDescription["Format"]["Y"] == "date" ) 550 $Value = $this->ToDate($Value); 551 if ( $DataDescription["Format"]["Y"] == "metric" ) 552 $Value = $this->ToMetric($Value); 553 if ( $DataDescription["Format"]["Y"] == "currency" ) 554 $Value = $this->ToCurrency($Value); 555 556 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); 557 $TextWidth = $Position[2]-$Position[0]; 558 559 if ( $RightScale ) 560 { 561 imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X2+10,$YPos+($this->FontSize/2),$C_TextColor,$this->FontName,$Value); 562 if ( $XMin < $this->GArea_X2+15+$TextWidth || $XMin == NULL ) { $XMin = $this->GArea_X2+15+$TextWidth; } 563 } 564 else 565 { 566 imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X1-10-$TextWidth,$YPos+($this->FontSize/2),$C_TextColor,$this->FontName,$Value); 567 if ( $XMin > $this->GArea_X1-10-$TextWidth || $XMin == NULL ) { $XMin = $this->GArea_X1-10-$TextWidth; } 568 } 569 570 $YPos = $YPos - $this->DivisionHeight; 571 } 572 573 /* Write the Y Axis caption if set */ 574 if ( isset($DataDescription["Axis"]["Y"]) ) 575 { 576 $Position = imageftbbox($this->FontSize,90,$this->FontName,$DataDescription["Axis"]["Y"]); 577 $TextHeight = abs($Position[1])+abs($Position[3]); 578 $TextTop = (($this->GArea_Y2 - $this->GArea_Y1) / 2) + $this->GArea_Y1 + ($TextHeight/2); 579 580 if ( $RightScale ) 581 imagettftext($this->Picture,$this->FontSize,90,$XMin+$this->FontSize,$TextTop,$C_TextColor,$this->FontName,$DataDescription["Axis"]["Y"]); 582 else 583 imagettftext($this->Picture,$this->FontSize,90,$XMin-$this->FontSize,$TextTop,$C_TextColor,$this->FontName,$DataDescription["Axis"]["Y"]); 584 } 585 586 /* Horizontal Axis */ 587 $XPos = $this->GArea_X1 + $this->GAreaXOffset; 588 $ID = 1; $YMax = NULL; 589 foreach ( $Data as $Key => $Values ) 590 { 591 if ( $ID % $SkipLabels == 0 ) 592 { 593 $this->drawLine(floor($XPos),$this->GArea_Y2,floor($XPos),$this->GArea_Y2+5,$R,$G,$B); 594 $Value = $Data[$Key][$DataDescription["Position"]]; 595 if ( $DataDescription["Format"]["X"] == "number" ) 596 $Value = $Value.$DataDescription["Unit"]["X"]; 597 if ( $DataDescription["Format"]["X"] == "time" ) 598 $Value = $this->ToTime($Value); 599 if ( $DataDescription["Format"]["X"] == "date" ) 600 $Value = $this->ToDate($Value); 601 if ( $DataDescription["Format"]["X"] == "metric" ) 602 $Value = $this->ToMetric($Value); 603 if ( $DataDescription["Format"]["X"] == "currency" ) 604 $Value = $this->ToCurrency($Value); 605 606 $Position = imageftbbox($this->FontSize,$Angle,$this->FontName,$Value); 607 $TextWidth = abs($Position[2])+abs($Position[0]); 608 $TextHeight = abs($Position[1])+abs($Position[3]); 609 610 if ( $Angle == 0 ) 611 { 612 $YPos = $this->GArea_Y2+18; 613 imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)-floor($TextWidth/2),$YPos,$C_TextColor,$this->FontName,$Value); 614 } 615 else 616 { 617 $YPos = $this->GArea_Y2+10+$TextHeight; 618 if ( $Angle <= 90 ) 619 imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)-$TextWidth+5,$YPos,$C_TextColor,$this->FontName,$Value); 620 else 621 imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)+$TextWidth+5,$YPos,$C_TextColor,$this->FontName,$Value); 622 } 623 if ( $YMax < $YPos || $YMax == NULL ) { $YMax = $YPos; } 624 } 625 626 $XPos = $XPos + $this->DivisionWidth; 627 $ID++; 628 } 629 630 /* Write the X Axis caption if set */ 631 if ( isset($DataDescription["Axis"]["X"]) ) 632 { 633 $Position = imageftbbox($this->FontSize,90,$this->FontName,$DataDescription["Axis"]["X"]); 634 $TextWidth = abs($Position[2])+abs($Position[0]); 635 $TextLeft = (($this->GArea_X2 - $this->GArea_X1) / 2) + $this->GArea_X1 + ($TextWidth/2); 636 imagettftext($this->Picture,$this->FontSize,0,$TextLeft,$YMax+$this->FontSize+5,$C_TextColor,$this->FontName,$DataDescription["Axis"]["X"]); 637 } 638 } 639 640 /* Compute and draw the scale for X/Y charts */ 641 function drawXYScale($Data,$DataDescription,$YSerieName,$XSerieName,$R,$G,$B,$WithMargin=0,$Angle=0,$Decimals=1) 642 { 643 /* Validate the Data and DataDescription array */ 644 $this->validateData("drawScale",$Data); 645 646 $C_TextColor =$this->AllocateColor($this->Picture,$R,$G,$B); 647 648 $this->drawLine($this->GArea_X1,$this->GArea_Y1,$this->GArea_X1,$this->GArea_Y2,$R,$G,$B); 649 $this->drawLine($this->GArea_X1,$this->GArea_Y2,$this->GArea_X2,$this->GArea_Y2,$R,$G,$B); 650 651 /* Process Y scale */ 652 if ( $this->VMin == NULL && $this->VMax == NULL) 653 { 654 $this->VMin = $Data[0][$YSerieName]; 655 $this->VMax = $Data[0][$YSerieName]; 656 657 foreach ( $Data as $Key => $Values ) 658 { 659 if (isset($Data[$Key][$YSerieName])) 660 { 661 $Value = $Data[$Key][$YSerieName]; 662 if ( $this->VMax < $Value) { $this->VMax = $Value; } 663 if ( $this->VMin > $Value) { $this->VMin = $Value; } 664 } 665 } 666 667 if ( $this->VMax > preg_replace('/\.[0-9]+/','',$this->VMax) ) 668 $this->VMax = preg_replace('/\.[0-9]+/','',$this->VMax)+1; 669 670 $DataRange = $this->VMax - $this->VMin; 671 if ( $DataRange == 0 ) { $DataRange = .1; } 672 673 /* Compute automatic scaling */ 674 $ScaleOk = FALSE; $Factor = 1; 675 $MinDivHeight = 25; $MaxDivs = ($this->GArea_Y2 - $this->GArea_Y1) / $MinDivHeight; 676 677 if ( $this->VMin == 0 && $this->VMax == 0 ) 678 { $this->VMin = 0; $this->VMax = 2; $Scale = 1; $Divisions = 2;} 679 elseif ($MaxDivs > 1) 680 { 681 while(!$ScaleOk) 682 { 683 $Scale1 = ( $this->VMax - $this->VMin ) / $Factor; 684 $Scale2 = ( $this->VMax - $this->VMin ) / $Factor / 2; 685 $Scale4 = ( $this->VMax - $this->VMin ) / $Factor / 4; 686 687 if ( $Scale1 > 1 && $Scale1 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $Divisions = floor($Scale1); $Scale = 1;} 688 if ( $Scale2 > 1 && $Scale2 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $Divisions = floor($Scale2); $Scale = 2;} 689 if (!$ScaleOk) 690 { 691 if ( $Scale2 > 1 ) { $Factor = $Factor * 10; } 692 if ( $Scale2 < 1 ) { $Factor = $Factor / 10; } 693 } 694 } 695 696 if ( floor($this->VMax / $Scale / $Factor) != $this->VMax / $Scale / $Factor) 697 { 698 $GridID = floor ( $this->VMax / $Scale / $Factor) + 1; 699 $this->VMax = $GridID * $Scale * $Factor; 700 $Divisions++; 701 } 702 703 if ( floor($this->VMin / $Scale / $Factor) != $this->VMin / $Scale / $Factor) 704 { 705 $GridID = floor( $this->VMin / $Scale / $Factor); 706 $this->VMin = $GridID * $Scale * $Factor; 707 $Divisions++; 708 } 709 } 710 else /* Can occurs for small graphs */ 711 $Scale = 1; 712 713 if ( !isset($Divisions) ) 714 $Divisions = 2; 715 716 if ( $this->isRealInt(($this->VMax-$this->VMin)/($Divisions-1))) 717 $Divisions--; 718 elseif ( $this->isRealInt(($this->VMax-$this->VMin)/($Divisions+1))) 719 $Divisions++; 720 } 721 else 722 $Divisions = $this->Divisions; 723 724 $this->DivisionCount = $Divisions; 725 726 $DataRange = $this->VMax - $this->VMin; 727 if ( $DataRange == 0 ) { $DataRange = .1; } 728 729 $this->DivisionHeight = ( $this->GArea_Y2 - $this->GArea_Y1 ) / $Divisions; 730 $this->DivisionRatio = ( $this->GArea_Y2 - $this->GArea_Y1 ) / $DataRange; 731 732 $YPos = $this->GArea_Y2; $XMin = NULL; 733 for($i=1;$i<=$Divisions+1;$i++) 734 { 735 $this->drawLine($this->GArea_X1,$YPos,$this->GArea_X1-5,$YPos,$R,$G,$B); 736 $Value = $this->VMin + ($i-1) * (( $this->VMax - $this->VMin ) / $Divisions); 737 $Value = round($Value * pow(10,$Decimals)) / pow(10,$Decimals); 738 if ( $DataDescription["Format"]["Y"] == "number" ) 739 $Value = $Value.$DataDescription["Unit"]["Y"]; 740 if ( $DataDescription["Format"]["Y"] == "time" ) 741 $Value = $this->ToTime($Value); 742 if ( $DataDescription["Format"]["Y"] == "date" ) 743 $Value = $this->ToDate($Value); 744 if ( $DataDescription["Format"]["Y"] == "metric" ) 745 $Value = $this->ToMetric($Value); 746 if ( $DataDescription["Format"]["Y"] == "currency" ) 747 $Value = $this->ToCurrency($Value); 748 749 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); 750 $TextWidth = $Position[2]-$Position[0]; 751 imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X1-10-$TextWidth,$YPos+($this->FontSize/2),$C_TextColor,$this->FontName,$Value); 752 753 if ( $XMin > $this->GArea_X1-10-$TextWidth || $XMin == NULL ) { $XMin = $this->GArea_X1-10-$TextWidth; } 754 755 $YPos = $YPos - $this->DivisionHeight; 756 } 757 758 /* Process X scale */ 759 if ( $this->VXMin == NULL && $this->VXMax == NULL) 760 { 761 $this->VXMin = $Data[0][$XSerieName]; 762 $this->VXMax = $Data[0][$XSerieName]; 763 764 foreach ( $Data as $Key => $Values ) 765 { 766 if (isset($Data[$Key][$XSerieName])) 767 { 768 $Value = $Data[$Key][$XSerieName]; 769 if ( $this->VXMax < $Value) { $this->VXMax = $Value; } 770 if ( $this->VXMin > $Value) { $this->VXMin = $Value; } 771 } 772 } 773 774 if ( $this->VXMax > preg_replace('/\.[0-9]+/','',$this->VXMax) ) 775 $this->VXMax = preg_replace('/\.[0-9]+/','',$this->VXMax)+1; 776 777 $DataRange = $this->VMax - $this->VMin; 778 if ( $DataRange == 0 ) { $DataRange = .1; } 779 780 /* Compute automatic scaling */ 781 $ScaleOk = FALSE; $Factor = 1; 782 $MinDivWidth = 25; $MaxDivs = ($this->GArea_X2 - $this->GArea_X1) / $MinDivWidth; 783 784 if ( $this->VXMin == 0 && $this->VXMax == 0 ) 785 { $this->VXMin = 0; $this->VXMax = 2; $Scale = 1; $XDivisions = 2;} 786 elseif ($MaxDivs > 1) 787 { 788 while(!$ScaleOk) 789 { 790 $Scale1 = ( $this->VXMax - $this->VXMin ) / $Factor; 791 $Scale2 = ( $this->VXMax - $this->VXMin ) / $Factor / 2; 792 $Scale4 = ( $this->VXMax - $this->VXMin ) / $Factor / 4; 793 794 if ( $Scale1 > 1 && $Scale1 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $XDivisions = floor($Scale1); $Scale = 1;} 795 if ( $Scale2 > 1 && $Scale2 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $XDivisions = floor($Scale2); $Scale = 2;} 796 if (!$ScaleOk) 797 { 798 if ( $Scale2 > 1 ) { $Factor = $Factor * 10; } 799 if ( $Scale2 < 1 ) { $Factor = $Factor / 10; } 800 } 801 } 802 803 if ( floor($this->VXMax / $Scale / $Factor) != $this->VXMax / $Scale / $Factor) 804 { 805 $GridID = floor ( $this->VXMax / $Scale / $Factor) + 1; 806 $this->VXMax = $GridID * $Scale * $Factor; 807 $XDivisions++; 808 } 809 810 if ( floor($this->VXMin / $Scale / $Factor) != $this->VXMin / $Scale / $Factor) 811 { 812 $GridID = floor( $this->VXMin / $Scale / $Factor); 813 $this->VXMin = $GridID * $Scale * $Factor; 814 $XDivisions++; 815 } 816 } 817 else /* Can occurs for small graphs */ 818 $Scale = 1; 819 820 if ( !isset($XDivisions) ) 821 $XDivisions = 2; 822 823 if ( $this->isRealInt(($this->VXMax-$this->VXMin)/($XDivisions-1))) 824 $XDivisions--; 825 elseif ( $this->isRealInt(($this->VXMax-$this->VXMin)/($XDivisions+1))) 826 $XDivisions++; 827 } 828 else 829 $XDivisions = $this->XDivisions; 830 831 $this->XDivisionCount = $Divisions; 832 $this->DataCount = $Divisions + 2; 833 834 $XDataRange = $this->VXMax - $this->VXMin; 835 if ( $XDataRange == 0 ) { $XDataRange = .1; } 836 837 $this->DivisionWidth = ( $this->GArea_X2 - $this->GArea_X1 ) / $XDivisions; 838 $this->XDivisionRatio = ( $this->GArea_X2 - $this->GArea_X1 ) / $XDataRange; 839 840 $XPos = $this->GArea_X1; $YMax = NULL; 841 for($i=1;$i<=$XDivisions+1;$i++) 842 { 843 $this->drawLine($XPos,$this->GArea_Y2,$XPos,$this->GArea_Y2+5,$R,$G,$B); 844 845 $Value = $this->VXMin + ($i-1) * (( $this->VXMax - $this->VXMin ) / $XDivisions); 846 $Value = round($Value * pow(10,$Decimals)) / pow(10,$Decimals); 847 if ( $DataDescription["Format"]["Y"] == "number" ) 848 $Value = $Value.$DataDescription["Unit"]["Y"]; 849 if ( $DataDescription["Format"]["Y"] == "time" ) 850 $Value = $this->ToTime($Value); 851 if ( $DataDescription["Format"]["Y"] == "date" ) 852 $Value = $this->ToDate($Value); 853 if ( $DataDescription["Format"]["Y"] == "metric" ) 854 $Value = $this->ToMetric($Value); 855 if ( $DataDescription["Format"]["Y"] == "currency" ) 856 $Value = $this->ToCurrency($Value); 857 858 $Position = imageftbbox($this->FontSize,$Angle,$this->FontName,$Value); 859 $TextWidth = abs($Position[2])+abs($Position[0]); 860 $TextHeight = abs($Position[1])+abs($Position[3]); 861 862 if ( $Angle == 0 ) 863 { 864 $YPos = $this->GArea_Y2+18; 865 imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)-floor($TextWidth/2),$YPos,$C_TextColor,$this->FontName,$Value); 866 } 867 else 868 { 869 $YPos = $this->GArea_Y2+10+$TextHeight; 870 if ( $Angle <= 90 ) 871 imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)-$TextWidth+5,$YPos,$C_TextColor,$this->FontName,$Value); 872 else 873 imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)+$TextWidth+5,$YPos,$C_TextColor,$this->FontName,$Value); 874 } 875 876 if ( $YMax < $YPos || $YMax == NULL ) { $YMax = $YPos; } 877 878 $XPos = $XPos + $this->DivisionWidth; 879 } 880 881 /* Write the Y Axis caption if set */ 882 if ( isset($DataDescription["Axis"]["Y"]) ) 883 { 884 $Position = imageftbbox($this->FontSize,90,$this->FontName,$DataDescription["Axis"]["Y"]); 885 $TextHeight = abs($Position[1])+abs($Position[3]); 886 $TextTop = (($this->GArea_Y2 - $this->GArea_Y1) / 2) + $this->GArea_Y1 + ($TextHeight/2); 887 imagettftext($this->Picture,$this->FontSize,90,$XMin-$this->FontSize,$TextTop,$C_TextColor,$this->FontName,$DataDescription["Axis"]["Y"]); 888 } 889 890 /* Write the X Axis caption if set */ 891 if ( isset($DataDescription["Axis"]["X"]) ) 892 { 893 $Position = imageftbbox($this->FontSize,90,$this->FontName,$DataDescription["Axis"]["X"]); 894 $TextWidth = abs($Position[2])+abs($Position[0]); 895 $TextLeft = (($this->GArea_X2 - $this->GArea_X1) / 2) + $this->GArea_X1 + ($TextWidth/2); 896 imagettftext($this->Picture,$this->FontSize,0,$TextLeft,$YMax+$this->FontSize+5,$C_TextColor,$this->FontName,$DataDescription["Axis"]["X"]); 897 } 898 } 899 900 /* Compute and draw the scale */ 901 function drawGrid($LineWidth,$Mosaic=TRUE,$R=220,$G=220,$B=220,$Alpha=100) 902 { 903 /* Draw mosaic */ 904 if ( $Mosaic ) 905 { 906 $LayerWidth = $this->GArea_X2-$this->GArea_X1; 907 $LayerHeight = $this->GArea_Y2-$this->GArea_Y1; 908 909 $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight); 910 $C_White =$this->AllocateColor($this->Layers[0],255,255,255); 911 imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White); 912 imagecolortransparent($this->Layers[0],$C_White); 913 914 $C_Rectangle =$this->AllocateColor($this->Layers[0],250,250,250); 915 916 $YPos = $LayerHeight; //$this->GArea_Y2-1; 917 $LastY = $YPos; 918 for($i=0;$i<=$this->DivisionCount;$i++) 919 { 920 $LastY = $YPos; 921 $YPos = $YPos - $this->DivisionHeight; 922 923 if ( $YPos <= 0 ) { $YPos = 1; } 924 925 if ( $i % 2 == 0 ) 926 { 927 imagefilledrectangle($this->Layers[0],1,$YPos,$LayerWidth-1,$LastY,$C_Rectangle); 928 } 929 } 930 imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha); 931 imagedestroy($this->Layers[0]); 932 } 933 934 /* Horizontal lines */ 935 $YPos = $this->GArea_Y2 - $this->DivisionHeight; 936 for($i=1;$i<=$this->DivisionCount;$i++) 937 { 938 if ( $YPos > $this->GArea_Y1 && $YPos < $this->GArea_Y2 ) 939 $this->drawDottedLine($this->GArea_X1,$YPos,$this->GArea_X2,$YPos,$LineWidth,$R,$G,$B); 940 941 $YPos = $YPos - $this->DivisionHeight; 942 } 943 944 /* Vertical lines */ 945 if ( $this->GAreaXOffset == 0 ) 946 { $XPos = $this->GArea_X1 + $this->DivisionWidth + $this->GAreaXOffset; $ColCount = $this->DataCount-2; } 947 else 948 { $XPos = $this->GArea_X1 + $this->GAreaXOffset; $ColCount = floor( ($this->GArea_X2 - $this->GArea_X1) / $this->DivisionWidth ); } 949 950 for($i=1;$i<=$ColCount;$i++) 951 { 952 if ( $XPos > $this->GArea_X1 && $XPos < $this->GArea_X2 ) 953 $this->drawDottedLine(floor($XPos),$this->GArea_Y1,floor($XPos),$this->GArea_Y2,$LineWidth,$R,$G,$B); 954 $XPos = $XPos + $this->DivisionWidth; 955 } 956 } 957 958 /* retrieve the legends size */ 959 function getLegendBoxSize($DataDescription) 960 { 961 if ( !isset($DataDescription["Description"]) ) 962 return(-1); 963 964 /* <-10->[8]<-4->Text<-10-> */ 965 $MaxWidth = 0; $MaxHeight = 8; 966 foreach($DataDescription["Description"] as $Key => $Value) 967 { 968 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); 969 $TextWidth = $Position[2]-$Position[0]; 970 $TextHeight = $Position[1]-$Position[7]; 971 if ( $TextWidth > $MaxWidth) { $MaxWidth = $TextWidth; } 972 $MaxHeight = $MaxHeight + $TextHeight + 4; 973 } 974 $MaxHeight = $MaxHeight - 3; 975 $MaxWidth = $MaxWidth + 32; 976 977 return(array($MaxWidth,$MaxHeight)); 978 } 979 980 /* retrieve the pie legends size */ 981 function getPieLegendBoxSize($Data, $DataDescription) 982 { 983 if ( !isset($DataDescription["Position"]) ) 984 return(-1); 985 986 /* <-10->[8]<-4->Text<-10-> */ 987 $MaxWidth = 0; $MaxHeight = 8; 988 foreach($Data as $DataPoint) 989 { 990 $Value = $DataPoint[$DataDescription["Position"]]; 991 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); 992 $TextWidth = $Position[2]-$Position[0]; 993 $TextHeight = $Position[1]-$Position[7]; 994 if ( $TextWidth > $MaxWidth) { $MaxWidth = $TextWidth; } 995 $MaxHeight = $MaxHeight + $TextHeight + 4; 996 } 997 998 $MaxHeight = $MaxHeight - 3; 999 $MaxWidth = $MaxWidth + 32; 1000 1001 return(array($MaxWidth,$MaxHeight)); 1002 } 1003 1004 /* Draw the data legends */ 1005 function drawLegend($XPos,$YPos,$DataDescription,$R,$G,$B,$Rs=-1,$Gs=-1,$Bs=-1,$Rt=0,$Gt=0,$Bt=0,$Border=TRUE) 1006 { 1007 /* Validate the Data and DataDescription array */ 1008 $this->validateDataDescription("drawLegend",$DataDescription); 1009 1010 if ( !isset($DataDescription["Description"]) ) 1011 return(-1); 1012 1013 $C_TextColor =$this->AllocateColor($this->Picture,$Rt,$Gt,$Bt); 1014 1015 /* <-10->[8]<-4->Text<-10-> */ 1016 $MaxWidth = 0; $MaxHeight = 8; 1017 foreach($DataDescription["Description"] as $Key => $Value) 1018 { 1019 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); 1020 $TextWidth = $Position[2]-$Position[0]; 1021 $TextHeight = $Position[1]-$Position[7]; 1022 if ( $TextWidth > $MaxWidth) { $MaxWidth = $TextWidth; } 1023 $MaxHeight = $MaxHeight + $TextHeight + 4; 1024 } 1025 $MaxHeight = $MaxHeight - 5; 1026 $MaxWidth = $MaxWidth + 32; 1027 1028 if ( $Rs == -1 || $Gs == -1 || $Bs == -1 ) 1029 { $Rs = $R-30; $Gs = $G-30; $Bs = $B-30; } 1030 1031 if ( $Border ) 1032 { 1033 $this->drawFilledRoundedRectangle($XPos+1,$YPos+1,$XPos+$MaxWidth+1,$YPos+$MaxHeight+1,5,$Rs,$Gs,$Bs); 1034 $this->drawFilledRoundedRectangle($XPos,$YPos,$XPos+$MaxWidth,$YPos+$MaxHeight,5,$R,$G,$B); 1035 } 1036 1037 $YOffset = 4 + $this->FontSize; $ID = 0; 1038 foreach($DataDescription["Description"] as $Key => $Value) 1039 { 1040 $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"]); 1041 imagettftext($this->Picture,$this->FontSize,0,$XPos+22,$YPos+$YOffset,$C_TextColor,$this->FontName,$Value); 1042 1043 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); 1044 $TextHeight = $Position[1]-$Position[7]; 1045 1046 $YOffset = $YOffset + $TextHeight + 4; 1047 $ID++; 1048 } 1049 } 1050 1051 /* Draw the data legends */ 1052 function drawPieLegend($XPos,$YPos,$Data,$DataDescription,$R,$G,$B) 1053 { 1054 /* Validate the Data and DataDescription array */ 1055 $this->validateDataDescription("drawPieLegend",$DataDescription,FALSE); 1056 $this->validateData("drawPieLegend",$Data); 1057 1058 if ( !isset($DataDescription["Position"]) ) 1059 return(-1); 1060 1061 $C_TextColor =$this->AllocateColor($this->Picture,0,0,0); 1062 1063 /* <-10->[8]<-4->Text<-10-> */ 1064 $MaxWidth = 0; $MaxHeight = 8; 1065 foreach($Data as $Key => $Value) 1066 { 1067 $Value2 = $Value[$DataDescription["Position"]]; 1068 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value2); 1069 $TextWidth = $Position[2]-$Position[0]; 1070 $TextHeight = $Position[1]-$Position[7]; 1071 if ( $TextWidth > $MaxWidth) { $MaxWidth = $TextWidth; } 1072 1073 $MaxHeight = $MaxHeight + $TextHeight + 4; 1074 } 1075 $MaxHeight = $MaxHeight - 3; 1076 $MaxWidth = $MaxWidth + 32; 1077 1078 $this->drawFilledRoundedRectangle($XPos+1,$YPos+1,$XPos+$MaxWidth+1,$YPos+$MaxHeight+1,5,$R-30,$G-30,$B-30); 1079 $this->drawFilledRoundedRectangle($XPos,$YPos,$XPos+$MaxWidth,$YPos+$MaxHeight,5,$R,$G,$B); 1080 1081 $YOffset = 4 + $this->FontSize; $ID = 0; 1082 foreach($Data as $Key => $Value) 1083 { 1084 $Value2 = $Value[$DataDescription["Position"]]; 1085 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value2); 1086 $TextHeight = $Position[1]-$Position[7]; 1087 $this->drawFilledRectangle($XPos+10,$YPos+$YOffset-6,$XPos+14,$YPos+$YOffset-2,$this->Palette[$ID]["R"],$this->Palette[$ID]["G"],$this->Palette[$ID]["B"]); 1088 1089 imagettftext($this->Picture,$this->FontSize,0,$XPos+22,$YPos+$YOffset,$C_TextColor,$this->FontName,$Value2); 1090 $YOffset = $YOffset + $TextHeight + 4; 1091 $ID++; 1092 } 1093 } 1094 1095 /* Draw the graph title */ 1096 function drawTitle($XPos,$YPos,$Value,$R,$G,$B,$XPos2=-1,$YPos2=-1,$Shadow=FALSE) 1097 { 1098 $C_TextColor = $this->AllocateColor($this->Picture,$R,$G,$B); 1099 1100 if ( $XPos2 != -1 ) 1101 { 1102 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); 1103 $TextWidth = $Position[2]-$Position[0]; 1104 $XPos = floor(( $XPos2 - $XPos - $TextWidth ) / 2 ) + $XPos; 1105 } 1106 1107 if ( $YPos2 != -1 ) 1108 { 1109 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); 1110 $TextHeight = $Position[5]-$Position[3]; 1111 $YPos = floor(( $YPos2 - $YPos - $TextHeight ) / 2 ) + $YPos; 1112 } 1113 1114 if ( $Shadow ) 1115 { 1116 $C_ShadowColor = $this->AllocateColor($this->Picture,$this->ShadowRColor,$this->ShadowGColor,$this->ShadowBColor); 1117 imagettftext($this->Picture,$this->FontSize,0,$XPos+$this->ShadowXDistance,$YPos+$this->ShadowYDistance,$C_ShadowColor,$this->FontName,$Value); 1118 } 1119 1120 imagettftext($this->Picture,$this->FontSize,0,$XPos,$YPos,$C_TextColor,$this->FontName,$Value); 1121 } 1122 1123 /* Draw a text box with text align & alpha properties */ 1124 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) 1125 { 1126 $Position = imageftbbox($this->FontSize,$Angle,$this->FontName,$Text); 1127 $TextWidth = $Position[2]-$Position[0]; 1128 $TextHeight = $Position[5]-$Position[3]; 1129 $AreaWidth = $X2 - $X1; 1130 $AreaHeight = $Y2 - $Y1; 1131 1132 if ( $BgR != -1 && $BgG != -1 && $BgB != -1 ) 1133 $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$BgR,$BgG,$BgB,FALSE,$Alpha); 1134 1135 if ( $Align == ALIGN_TOP_LEFT ) { $X = $X1+1; $Y = $Y1+$this->FontSize+1; } 1136 if ( $Align == ALIGN_TOP_CENTER ) { $X = $X1+($AreaWidth/2)-($TextWidth/2); $Y = $Y1+$this->FontSize+1; } 1137 if ( $Align == ALIGN_TOP_RIGHT ) { $X = $X2-$TextWidth-1; $Y = $Y1+$this->FontSize+1; } 1138 if ( $Align == ALIGN_LEFT ) { $X = $X1+1; $Y = $Y1+($AreaHeight/2)-($TextHeight/2); } 1139 if ( $Align == ALIGN_CENTER ) { $X = $X1+($AreaWidth/2)-($TextWidth/2); $Y = $Y1+($AreaHeight/2)-($TextHeight/2); } 1140 if ( $Align == ALIGN_RIGHT ) { $X = $X2-$TextWidth-1; $Y = $Y1+($AreaHeight/2)-($TextHeight/2); } 1141 if ( $Align == ALIGN_BOTTOM_LEFT ) { $X = $X1+1; $Y = $Y2-1; } 1142 if ( $Align == ALIGN_BOTTOM_CENTER ) { $X = $X1+($AreaWidth/2)-($TextWidth/2); $Y = $Y2-1; } 1143 if ( $Align == ALIGN_BOTTOM_RIGHT ) { $X = $X2-$TextWidth-1; $Y = $Y2-1; } 1144 1145 $C_TextColor =$this->AllocateColor($this->Picture,$R,$G,$B); 1146 $C_ShadowColor =$this->AllocateColor($this->Picture,0,0,0); 1147 if ( $Shadow ) 1148 imagettftext($this->Picture,$this->FontSize,$Angle,$X+1,$Y+1,$C_ShadowColor,$this->FontName,$Text); 1149 1150 imagettftext($this->Picture,$this->FontSize,$Angle,$X,$Y,$C_TextColor,$this->FontName,$Text); 1151 } 1152 1153 /* Compute and draw the scale */ 1154 function drawTreshold($Value,$R,$G,$B,$ShowLabel=FALSE,$ShowOnRight=FALSE,$TickWidth=4,$FreeText=NULL) 1155 { 1156 if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } 1157 if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } 1158 if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } 1159 1160 $C_TextColor =$this->AllocateColor($this->Picture,$R,$G,$B); 1161 $Y = $this->GArea_Y2 - ($Value - $this->VMin) * $this->DivisionRatio; 1162 1163 if ( $Y <= $this->GArea_Y1 || $Y >= $this->GArea_Y2 ) 1164 return(-1); 1165 1166 if ( $TickWidth == 0 ) 1167 $this->drawLine($this->GArea_X1,$Y,$this->GArea_X2,$Y,$R,$G,$B); 1168 else 1169 $this->drawDottedLine($this->GArea_X1,$Y,$this->GArea_X2,$Y,$TickWidth,$R,$G,$B); 1170 1171 if ( $ShowLabel ) 1172 { 1173 if ( $FreeText == NULL ) 1174 { $Label = $Value; } else { $Label = $FreeText; } 1175 1176 if ( $ShowOnRight ) 1177 imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X2+2,$Y+($this->FontSize/2),$C_TextColor,$this->FontName,$Label); 1178 else 1179 imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X1+2,$Y-($this->FontSize/2),$C_TextColor,$this->FontName,$Label); 1180 } 1181 } 1182 1183 /* This function put a label on a specific point */ 1184 function setLabel($Data,$DataDescription,$SerieName,$ValueName,$Caption,$R=210,$G=210,$B=210) 1185 { 1186 /* Validate the Data and DataDescription array */ 1187 $this->validateDataDescription("setLabel",$DataDescription); 1188 $this->validateData("setLabel",$Data); 1189 $ShadowFactor = 100; 1190 $C_Label =$this->AllocateColor($this->Picture,$R,$G,$B); 1191 $C_Shadow =$this->AllocateColor($this->Picture,$R-$ShadowFactor,$G-$ShadowFactor,$B-$ShadowFactor); 1192 $C_TextColor =$this->AllocateColor($this->Picture,0,0,0); 1193 1194 $Cp = 0; $Found = FALSE; 1195 foreach ( $Data as $Key => $Value ) 1196 { 1197 if ( $Data[$Key][$DataDescription["Position"]] == $ValueName ) 1198 { $NumericalValue = $Data[$Key][$SerieName]; $Found = TRUE; } 1199 if ( !$Found ) 1200 $Cp++; 1201 } 1202 1203 $XPos = $this->GArea_X1 + $this->GAreaXOffset + ( $this->DivisionWidth * $Cp ) + 2; 1204 $YPos = $this->GArea_Y2 - ($NumericalValue - $this->VMin) * $this->DivisionRatio; 1205 1206 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Caption); 1207 $TextHeight = $Position[3] - $Position[5]; 1208 $TextWidth = $Position[2]-$Position[0] + 2; 1209 $TextOffset = floor($TextHeight/2); 1210 1211 // Shadow 1212 $Poly = array($XPos+1,$YPos+1,$XPos + 9,$YPos - $TextOffset,$XPos + 8,$YPos + $TextOffset + 2); 1213 imagefilledpolygon($this->Picture,$Poly,3,$C_Shadow); 1214 $this->drawLine($XPos,$YPos+1,$XPos + 9,$YPos - $TextOffset - .2,$R-$ShadowFactor,$G-$ShadowFactor,$B-$ShadowFactor); 1215 $this->drawLine($XPos,$YPos+1,$XPos + 9,$YPos + $TextOffset + 2.2,$R-$ShadowFactor,$G-$ShadowFactor,$B-$ShadowFactor); 1216 $this->drawFilledRectangle($XPos + 9,$YPos - $TextOffset-.2,$XPos + 13 + $TextWidth,$YPos + $TextOffset + 2.2,$R-$ShadowFactor,$G-$ShadowFactor,$B-$ShadowFactor); 1217 1218 // Label background 1219 $Poly = array($XPos,$YPos,$XPos + 8,$YPos - $TextOffset - 1,$XPos + 8,$YPos + $TextOffset + 1); 1220 imagefilledpolygon($this->Picture,$Poly,3,$C_Label); 1221 $this->drawLine($XPos-1,$YPos,$XPos + 8,$YPos - $TextOffset - 1.2,$R,$G,$B); 1222 $this->drawLine($XPos-1,$YPos,$XPos + 8,$YPos + $TextOffset + 1.2,$R,$G,$B); 1223 $this->drawFilledRectangle($XPos + 8,$YPos - $TextOffset - 1.2,$XPos + 12 + $TextWidth,$YPos + $TextOffset + 1.2,$R,$G,$B); 1224 1225 imagettftext($this->Picture,$this->FontSize,0,$XPos + 10,$YPos + $TextOffset,$C_TextColor,$this->FontName,$Caption); 1226 } 1227 1228 /* This function draw a plot graph */ 1229 function drawPlotGraph($Data,$DataDescription,$BigRadius=5,$SmallRadius=2,$R2=-1,$G2=-1,$B2=-1,$Shadow=FALSE) 1230 { 1231 /* Validate the Data and DataDescription array */ 1232 $this->validateDataDescription("drawPlotGraph",$DataDescription); 1233 $this->validateData("drawPlotGraph",$Data); 1234 1235 $GraphID = 0; 1236 $Ro = $R2; $Go = $G2; $Bo = $B2; 1237 1238 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 1239 { 1240 $ID = 0; 1241 foreach ( $DataDescription["Description"] as $keyI => $ValueI ) 1242 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } 1243 1244 $R = $this->Palette[$ColorID]["R"]; 1245 $G = $this->Palette[$ColorID]["G"]; 1246 $B = $this->Palette[$ColorID]["B"]; 1247 $R2 = $Ro; $G2 = $Go; $B2 = $Bo; 1248 1249 if ( isset($DataDescription["Symbol"][$ColName]) ) 1250 { 1251 $Is_Alpha = ((ord ( file_get_contents ($DataDescription["Symbol"][$ColName], false, null, 25, 1)) & 6) & 4) == 4; 1252 1253 $Infos = getimagesize($DataDescription["Symbol"][$ColName]); 1254 $ImageWidth = $Infos[0]; 1255 $ImageHeight = $Infos[1]; 1256 $Symbol = imagecreatefromgif($DataDescription["Symbol"][$ColName]); 1257 } 1258 1259 $XPos = $this->GArea_X1 + $this->GAreaXOffset; 1260 $Hsize = round($BigRadius/2); 1261 $R3 = -1; $G3 = -1; $B3 = -1; 1262 foreach ( $Data as $Key => $Values ) 1263 { 1264 $Value = $Data[$Key][$ColName]; 1265 $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio); 1266 1267 /* Save point into the image map if option activated */ 1268 if ( $this->BuildMap ) 1269 $this->addToImageMap($XPos-$Hsize,$YPos-$Hsize,$XPos+1+$Hsize,$YPos+$Hsize+1,$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"Plot"); 1270 1271 if ( is_numeric($Value) ) 1272 { 1273 if ( !isset($DataDescription["Symbol"][$ColName]) ) 1274 { 1275 1276 if ( $Shadow ) 1277 { 1278 if ( $R3 !=-1 && $G3 !=-1 && $B3 !=-1 ) 1279 $this->drawFilledCircle($XPos+2,$YPos+2,$BigRadius,$R3,$G3,$B3); 1280 else 1281 { 1282 $R3 = $this->Palette[$ColorID]["R"]-20; if ( $R3 < 0 ) { $R3 = 0; } 1283 $G3 = $this->Palette[$ColorID]["G"]-20; if ( $G3 < 0 ) { $G3 = 0; } 1284 $B3 = $this->Palette[$ColorID]["B"]-20; if ( $B3 < 0 ) { $B3 = 0; } 1285 $this->drawFilledCircle($XPos+2,$YPos+2,$BigRadius,$R3,$G3,$B3); 1286 } 1287 } 1288 1289 $this->drawFilledCircle($XPos+1,$YPos+1,$BigRadius,$R,$G,$B); 1290 1291 if ( $SmallRadius != 0 ) 1292 { 1293 if ( $R2 !=-1 && $G2 !=-1 && $B2 !=-1 ) 1294 $this->drawFilledCircle($XPos+1,$YPos+1,$SmallRadius,$R2,$G2,$B2); 1295 else 1296 { 1297 $R2 = $this->Palette[$ColorID]["R"]-15; if ( $R2 < 0 ) { $R2 = 0; } 1298 $G2 = $this->Palette[$ColorID]["G"]-15; if ( $G2 < 0 ) { $G2 = 0; } 1299 $B2 = $this->Palette[$ColorID]["B"]-15; if ( $B2 < 0 ) { $B2 = 0; } 1300 1301 $this->drawFilledCircle($XPos+1,$YPos+1,$SmallRadius,$R2,$G2,$B2); 1302 } 1303 } 1304 } 1305 else 1306 { 1307 imagecopymerge($this->Picture,$Symbol,$XPos+1-$ImageWidth/2,$YPos+1-$ImageHeight/2,0,0,$ImageWidth,$ImageHeight,100); 1308 } 1309 } 1310 1311 $XPos = $XPos + $this->DivisionWidth; 1312 } 1313 $GraphID++; 1314 } 1315 } 1316 1317 /* This function draw a plot graph in an X/Y space */ 1318 function drawXYPlotGraph($Data,$DataDescription,$YSerieName,$XSerieName,$PaletteID=0,$BigRadius=5,$SmallRadius=2,$R2=-1,$G2=-1,$B2=-1,$Shadow=TRUE) 1319 { 1320 $R = $this->Palette[$PaletteID]["R"]; 1321 $G = $this->Palette[$PaletteID]["G"]; 1322 $B = $this->Palette[$PaletteID]["B"]; 1323 $R3 = -1; $G3 = -1; $B3 = -1; 1324 1325 $YLast = -1; $XLast = -1; 1326 foreach ( $Data as $Key => $Values ) 1327 { 1328 if ( isset($Data[$Key][$YSerieName]) && isset($Data[$Key][$XSerieName]) ) 1329 { 1330 $X = $Data[$Key][$XSerieName]; 1331 $Y = $Data[$Key][$YSerieName]; 1332 1333 $Y = $this->GArea_Y2 - (($Y-$this->VMin) * $this->DivisionRatio); 1334 $X = $this->GArea_X1 + (($X-$this->VXMin) * $this->XDivisionRatio); 1335 1336 1337 if ( $Shadow ) 1338 { 1339 if ( $R3 !=-1 && $G3 !=-1 && $B3 !=-1 ) 1340 $this->drawFilledCircle($X+2,$Y+2,$BigRadius,$R3,$G3,$B3); 1341 else 1342 { 1343 $R3 = $this->Palette[$PaletteID]["R"]-20; if ( $R < 0 ) { $R = 0; } 1344 $G3 = $this->Palette[$PaletteID]["G"]-20; if ( $G < 0 ) { $G = 0; } 1345 $B3 = $this->Palette[$PaletteID]["B"]-20; if ( $B < 0 ) { $B = 0; } 1346 $this->drawFilledCircle($X+2,$Y+2,$BigRadius,$R3,$G3,$B3); 1347 } 1348 } 1349 1350 $this->drawFilledCircle($X+1,$Y+1,$BigRadius,$R,$G,$B); 1351 1352 if ( $R2 !=-1 && $G2 !=-1 && $B2 !=-1 ) 1353 $this->drawFilledCircle($X+1,$Y+1,$SmallRadius,$R2,$G2,$B2); 1354 else 1355 { 1356 $R2 = $this->Palette[$PaletteID]["R"]+20; if ( $R > 255 ) { $R = 255; } 1357 $G2 = $this->Palette[$PaletteID]["G"]+20; if ( $G > 255 ) { $G = 255; } 1358 $B2 = $this->Palette[$PaletteID]["B"]+20; if ( $B > 255 ) { $B = 255; } 1359 $this->drawFilledCircle($X+1,$Y+1,$SmallRadius,$R2,$G2,$B2); 1360 } 1361 } 1362 } 1363 1364 } 1365 1366 /* This function draw an area between two series */ 1367 function drawArea($Data,$Serie1,$Serie2,$R,$G,$B,$Alpha = 50) 1368 { 1369 /* Validate the Data and DataDescription array */ 1370 $this->validateData("drawArea",$Data); 1371 1372 $LayerWidth = $this->GArea_X2-$this->GArea_X1; 1373 $LayerHeight = $this->GArea_Y2-$this->GArea_Y1; 1374 1375 $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight); 1376 $C_White =$this->AllocateColor($this->Layers[0],255,255,255); 1377 imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White); 1378 imagecolortransparent($this->Layers[0],$C_White); 1379 1380 $C_Graph =$this->AllocateColor($this->Layers[0],$R,$G,$B); 1381 1382 $XPos = $this->GAreaXOffset; 1383 $LastXPos = -1; 1384 foreach ( $Data as $Key => $Values ) 1385 { 1386 $Value1 = $Data[$Key][$Serie1]; 1387 $Value2 = $Data[$Key][$Serie2]; 1388 $YPos1 = $LayerHeight - (($Value1-$this->VMin) * $this->DivisionRatio); 1389 $YPos2 = $LayerHeight - (($Value2-$this->VMin) * $this->DivisionRatio); 1390 1391 if ( $LastXPos != -1 ) 1392 { 1393 $Points = ""; 1394 $Points[] = $LastXPos; $Points[] = $LastYPos1; 1395 $Points[] = $LastXPos; $Points[] = $LastYPos2; 1396 $Points[] = $XPos; $Points[] = $YPos2; 1397 $Points[] = $XPos; $Points[] = $YPos1; 1398 1399 imagefilledpolygon($this->Layers[0],$Points,4,$C_Graph); 1400 } 1401 1402 $LastYPos1 = $YPos1; 1403 $LastYPos2 = $YPos2; 1404 $LastXPos = $XPos; 1405 1406 $XPos = $XPos + $this->DivisionWidth; 1407 } 1408 1409 imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha); 1410 imagedestroy($this->Layers[0]); 1411 } 1412 1413 1414 /* This function write the values of the specified series */ 1415 function writeValues($Data,$DataDescription,$Series) 1416 { 1417 /* Validate the Data and DataDescription array */ 1418 $this->validateDataDescription("writeValues",$DataDescription); 1419 $this->validateData("writeValues",$Data); 1420 1421 if ( !is_array($Series) ) { $Series = array($Series); } 1422 1423 foreach($Series as $Key => $Serie) 1424 { 1425 $ID = 0; 1426 foreach ( $DataDescription["Description"] as $keyI => $ValueI ) 1427 { if ( $keyI == $Serie ) { $ColorID = $ID; }; $ID++; } 1428 1429 $XPos = $this->GArea_X1 + $this->GAreaXOffset; 1430 $XLast = -1; 1431 foreach ( $Data as $Key => $Values ) 1432 { 1433 if ( isset($Data[$Key][$Serie]) && is_numeric($Data[$Key][$Serie])) 1434 { 1435 $Value = $Data[$Key][$Serie]; 1436 $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio); 1437 1438 $Positions = imagettfbbox($this->FontSize,0,$this->FontName,$Value); 1439 $Width = $Positions[2] - $Positions[6]; $XOffset = $XPos - ($Width/2); 1440 $Height = $Positions[3] - $Positions[7]; $YOffset = $YPos - 4; 1441 1442 $C_TextColor =$this->AllocateColor($this->Picture,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); 1443 imagettftext($this->Picture,$this->FontSize,0,$XOffset,$YOffset,$C_TextColor,$this->FontName,$Value); 1444 } 1445 $XPos = $XPos + $this->DivisionWidth; 1446 } 1447 1448 } 1449 } 1450 1451 /* This function draw a line graph */ 1452 function drawLineGraph($Data,$DataDescription,$SerieName="") 1453 { 1454 /* Validate the Data and DataDescription array */ 1455 $this->validateDataDescription("drawLineGraph",$DataDescription); 1456 $this->validateData("drawLineGraph",$Data); 1457 1458 $GraphID = 0; 1459 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 1460 { 1461 $ID = 0; 1462 foreach ( $DataDescription["Description"] as $keyI => $ValueI ) 1463 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } 1464 1465 if ( $SerieName == "" || $SerieName == $ColName ) 1466 { 1467 $XPos = $this->GArea_X1 + $this->GAreaXOffset; 1468 $XLast = -1; 1469 foreach ( $Data as $Key => $Values ) 1470 { 1471 if ( isset($Data[$Key][$ColName])) 1472 { 1473 $Value = $Data[$Key][$ColName]; 1474 $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio); 1475 1476 /* Save point into the image map if option activated */ 1477 if ( $this->BuildMap ) 1478 $this->addToImageMap($XPos-3,$YPos-3,$XPos+3,$YPos+3,$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"Line"); 1479 1480 if (!is_numeric($Value)) { $XLast = -1; } 1481 if ( $XLast != -1 ) 1482 $this->drawLine($XLast,$YLast,$XPos,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE); 1483 1484 $XLast = $XPos; 1485 $YLast = $YPos; 1486 if (!is_numeric($Value)) { $XLast = -1; } 1487 } 1488 $XPos = $XPos + $this->DivisionWidth; 1489 } 1490 $GraphID++; 1491 } 1492 } 1493 } 1494 1495 /* This function draw a line graph */ 1496 function drawXYGraph($Data,$DataDescription,$YSerieName,$XSerieName,$PaletteID=0) 1497 { 1498 $YLast = -1; $XLast = -1; 1499 foreach ( $Data as $Key => $Values ) 1500 { 1501 if ( isset($Data[$Key][$YSerieName]) && isset($Data[$Key][$XSerieName]) ) 1502 { 1503 $X = $Data[$Key][$XSerieName]; 1504 $Y = $Data[$Key][$YSerieName]; 1505 1506 $Y = $this->GArea_Y2 - (($Y-$this->VMin) * $this->DivisionRatio); 1507 $X = $this->GArea_X1 + (($X-$this->VXMin) * $this->XDivisionRatio); 1508 1509 if ($XLast != -1 && $YLast != -1) 1510 { 1511 $this->drawLine($XLast,$YLast,$X,$Y,$this->Palette[$PaletteID]["R"],$this->Palette[$PaletteID]["G"],$this->Palette[$PaletteID]["B"],TRUE); 1512 } 1513 1514 $XLast = $X; 1515 $YLast = $Y; 1516 } 1517 } 1518 } 1519 1520 /* This function draw a cubic curve */ 1521 function drawCubicCurve($Data,$DataDescription,$Accuracy=.1,$SerieName="") 1522 { 1523 /* Validate the Data and DataDescription array */ 1524 $this->validateDataDescription("drawCubicCurve",$DataDescription); 1525 $this->validateData("drawCubicCurve",$Data); 1526 1527 $GraphID = 0; 1528 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 1529 { 1530 if ( $SerieName == "" || $SerieName == $ColName ) 1531 { 1532 $XIn = ""; $Yin = ""; $Yt = ""; $U = ""; 1533 $XIn[0] = 0; $YIn[0] = 0; 1534 1535 $ID = 0; 1536 foreach ( $DataDescription["Description"] as $keyI => $ValueI ) 1537 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } 1538 1539 $Index = 1; 1540 $XLast = -1; $Missing = ""; 1541 foreach ( $Data as $Key => $Values ) 1542 { 1543 if ( isset($Data[$Key][$ColName]) ) 1544 { 1545 $Value = $Data[$Key][$ColName]; 1546 $XIn[$Index] = $Index; 1547 $YIn[$Index] = $Value; 1548 if ( !is_numeric($Value) ) { $Missing[$Index] = TRUE; } 1549 $Index++; 1550 } 1551 } 1552 $Index--; 1553 1554 $Yt[0] = 0; 1555 $Yt[1] = 0; 1556 $U[1] = 0; 1557 for($i=2;$i<=$Index-1;$i++) 1558 { 1559 $Sig = ($XIn[$i] - $XIn[$i-1]) / ($XIn[$i+1] - $XIn[$i-1]); 1560 $p = $Sig * $Yt[$i-1] + 2; 1561 $Yt[$i] = ($Sig - 1) / $p; 1562 $U[$i] = ($YIn[$i+1] - $YIn[$i]) / ($XIn[$i+1] - $XIn[$i]) - ($YIn[$i] - $YIn[$i-1]) / ($XIn[$i] - $XIn[$i-1]); 1563 $U[$i] = (6 * $U[$i] / ($XIn[$i+1] - $XIn[$i-1]) - $Sig * $U[$i-1]) / $p; 1564 } 1565 1566 $qn = 0; 1567 $un = 0; 1568 $Yt[$Index] = ($un - $qn * $U[$Index-1]) / ($qn * $Yt[$Index-1] + 1); 1569 1570 for($k=$Index-1;$k>=1;$k--) 1571 $Yt[$k] = $Yt[$k] * $Yt[$k+1] + $U[$k]; 1572 1573 $XPos = $this->GArea_X1 + $this->GAreaXOffset; 1574 for($X=1;$X<=$Index;$X=$X+$Accuracy) 1575 { 1576 $klo = 1; 1577 $khi = $Index; 1578 $k = $khi - $klo; 1579 while($k > 1) 1580 { 1581 $k = $khi - $klo; 1582 If ( $XIn[$k] >= $X ) 1583 $khi = $k; 1584 else 1585 $klo = $k; 1586 } 1587 $klo = $khi - 1; 1588 1589 $h = $XIn[$khi] - $XIn[$klo]; 1590 $a = ($XIn[$khi] - $X) / $h; 1591 $b = ($X - $XIn[$klo]) / $h; 1592 $Value = $a * $YIn[$klo] + $b * $YIn[$khi] + (($a*$a*$a - $a) * $Yt[$klo] + ($b*$b*$b - $b) * $Yt[$khi]) * ($h*$h) / 6; 1593 1594 $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio); 1595 1596 if ( $XLast != -1 && !isset($Missing[floor($X)]) && !isset($Missing[floor($X+1)]) ) 1597 $this->drawLine($XLast,$YLast,$XPos,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE); 1598 1599 $XLast = $XPos; 1600 $YLast = $YPos; 1601 $XPos = $XPos + $this->DivisionWidth * $Accuracy; 1602 } 1603 1604 // Add potentialy missing values 1605 $XPos = $XPos - $this->DivisionWidth * $Accuracy; 1606 if ( $XPos < ($this->GArea_X2 - $this->GAreaXOffset) ) 1607 { 1608 $YPos = $this->GArea_Y2 - (($YIn[$Index]-$this->VMin) * $this->DivisionRatio); 1609 $this->drawLine($XLast,$YLast,$this->GArea_X2-$this->GAreaXOffset,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE); 1610 } 1611 1612 $GraphID++; 1613 } 1614 } 1615 } 1616 1617 /* This function draw a filled cubic curve */ 1618 function drawFilledCubicCurve($Data,$DataDescription,$Accuracy=.1,$Alpha=100,$AroundZero=FALSE) 1619 { 1620 /* Validate the Data and DataDescription array */ 1621 $this->validateDataDescription("drawFilledCubicCurve",$DataDescription); 1622 $this->validateData("drawFilledCubicCurve",$Data); 1623 1624 $LayerWidth = $this->GArea_X2-$this->GArea_X1; 1625 $LayerHeight = $this->GArea_Y2-$this->GArea_Y1; 1626 $YZero = $LayerHeight - ((0-$this->VMin) * $this->DivisionRatio); 1627 if ( $YZero > $LayerHeight ) { $YZero = $LayerHeight; } 1628 1629 $GraphID = 0; 1630 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 1631 { 1632 $XIn = ""; $Yin = ""; $Yt = ""; $U = ""; 1633 $XIn[0] = 0; $YIn[0] = 0; 1634 1635 $ID = 0; 1636 foreach ( $DataDescription["Description"] as $keyI => $ValueI ) 1637 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } 1638 1639 $Index = 1; 1640 $XLast = -1; $Missing = ""; 1641 foreach ( $Data as $Key => $Values ) 1642 { 1643 $Value = $Data[$Key][$ColName]; 1644 $XIn[$Index] = $Index; 1645 $YIn[$Index] = $Value; 1646 if ( !is_numeric($Value) ) { $Missing[$Index] = TRUE; } 1647 $Index++; 1648 } 1649 $Index--; 1650 1651 $Yt[0] = 0; 1652 $Yt[1] = 0; 1653 $U[1] = 0; 1654 for($i=2;$i<=$Index-1;$i++) 1655 { 1656 $Sig = ($XIn[$i] - $XIn[$i-1]) / ($XIn[$i+1] - $XIn[$i-1]); 1657 $p = $Sig * $Yt[$i-1] + 2; 1658 $Yt[$i] = ($Sig - 1) / $p; 1659 $U[$i] = ($YIn[$i+1] - $YIn[$i]) / ($XIn[$i+1] - $XIn[$i]) - ($YIn[$i] - $YIn[$i-1]) / ($XIn[$i] - $XIn[$i-1]); 1660 $U[$i] = (6 * $U[$i] / ($XIn[$i+1] - $XIn[$i-1]) - $Sig * $U[$i-1]) / $p; 1661 } 1662 1663 $qn = 0; 1664 $un = 0; 1665 $Yt[$Index] = ($un - $qn * $U[$Index-1]) / ($qn * $Yt[$Index-1] + 1); 1666 1667 for($k=$Index-1;$k>=1;$k--) 1668 $Yt[$k] = $Yt[$k] * $Yt[$k+1] + $U[$k]; 1669 1670 $Points = ""; 1671 $Points[] = $this->GAreaXOffset; 1672 $Points[] = $LayerHeight; 1673 1674 $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight); 1675 $C_White =$this->AllocateColor($this->Layers[0],255,255,255); 1676 imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White); 1677 imagecolortransparent($this->Layers[0],$C_White); 1678 1679 $YLast = NULL; 1680 $XPos = $this->GAreaXOffset; $PointsCount = 2; 1681 for($X=1;$X<=$Index;$X=$X+$Accuracy) 1682 { 1683 $klo = 1; 1684 $khi = $Index; 1685 $k = $khi - $klo; 1686 while($k > 1) 1687 { 1688 $k = $khi - $klo; 1689 If ( $XIn[$k] >= $X ) 1690 $khi = $k; 1691 else 1692 $klo = $k; 1693 } 1694 $klo = $khi - 1; 1695 1696 $h = $XIn[$khi] - $XIn[$klo]; 1697 $a = ($XIn[$khi] - $X) / $h; 1698 $b = ($X - $XIn[$klo]) / $h; 1699 $Value = $a * $YIn[$klo] + $b * $YIn[$khi] + (($a*$a*$a - $a) * $Yt[$klo] + ($b*$b*$b - $b) * $Yt[$khi]) * ($h*$h) / 6; 1700 1701 $YPos = $LayerHeight - (($Value-$this->VMin) * $this->DivisionRatio); 1702 1703 if ( $YLast != NULL && $AroundZero && !isset($Missing[floor($X)]) && !isset($Missing[floor($X+1)])) 1704 { 1705 $aPoints = ""; 1706 $aPoints[] = $XLast; 1707 $aPoints[] = $YLast; 1708 $aPoints[] = $XPos; 1709 $aPoints[] = $YPos; 1710 $aPoints[] = $XPos; 1711 $aPoints[] = $YZero; 1712 $aPoints[] = $XLast; 1713 $aPoints[] = $YZero; 1714 1715 $C_Graph =$this->AllocateColor($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); 1716 imagefilledpolygon($this->Layers[0],$aPoints,4,$C_Graph); 1717 } 1718 1719 if ( !isset($Missing[floor($X)]) || $YLast == NULL ) 1720 { 1721 $PointsCount++; 1722 $Points[] = $XPos; 1723 $Points[] = $YPos; 1724 } 1725 else 1726 { 1727 $PointsCount++; $Points[] = $XLast; $Points[] = $LayerHeight; 1728 } 1729 1730 $YLast = $YPos; $XLast = $XPos; 1731 $XPos = $XPos + $this->DivisionWidth * $Accuracy; 1732 } 1733 1734 // Add potentialy missing values 1735 $XPos = $XPos - $this->DivisionWidth * $Accuracy; 1736 if ( $XPos < ($LayerWidth-$this->GAreaXOffset) ) 1737 { 1738 $YPos = $LayerHeight - (($YIn[$Index]-$this->VMin) * $this->DivisionRatio); 1739 1740 if ( $YLast != NULL && $AroundZero ) 1741 { 1742 $aPoints = ""; 1743 $aPoints[] = $XLast; 1744 $aPoints[] = $YLast; 1745 $aPoints[] = $LayerWidth-$this->GAreaXOffset; 1746 $aPoints[] = $YPos; 1747 $aPoints[] = $LayerWidth-$this->GAreaXOffset; 1748 $aPoints[] = $YZero; 1749 $aPoints[] = $XLast; 1750 $aPoints[] = $YZero; 1751 1752 $C_Graph =$this->AllocateColor($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); 1753 imagefilledpolygon($this->Layers[0],$aPoints,4,$C_Graph); 1754 } 1755 1756 if ( $YIn[$klo] != "" && $YIn[$khi] != "" || $YLast == NULL ) 1757 { 1758 $PointsCount++; 1759 $Points[] = $LayerWidth-$this->GAreaXOffset; 1760 $Points[] = $YPos; 1761 } 1762 } 1763 1764 $Points[] = $LayerWidth-$this->GAreaXOffset; 1765 $Points[] = $LayerHeight; 1766 1767 if ( !$AroundZero ) 1768 { 1769 $C_Graph =$this->AllocateColor($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); 1770 imagefilledpolygon($this->Layers[0],$Points,$PointsCount,$C_Graph); 1771 } 1772 1773 imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha); 1774 imagedestroy($this->Layers[0]); 1775 1776 $this->drawCubicCurve($Data,$DataDescription,$Accuracy,$ColName); 1777 1778 $GraphID++; 1779 } 1780 } 1781 1782 /* This function draw a filled line graph */ 1783 function drawFilledLineGraph($Data,$DataDescription,$Alpha=100,$AroundZero=FALSE) 1784 { 1785 $Empty = -2147483647; 1786 1787 /* Validate the Data and DataDescription array */ 1788 $this->validateDataDescription("drawFilledLineGraph",$DataDescription); 1789 $this->validateData("drawFilledLineGraph",$Data); 1790 1791 $LayerWidth = $this->GArea_X2-$this->GArea_X1; 1792 $LayerHeight = $this->GArea_Y2-$this->GArea_Y1; 1793 1794 $GraphID = 0; 1795 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 1796 { 1797 $ID = 0; 1798 foreach ( $DataDescription["Description"] as $keyI => $ValueI ) 1799 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } 1800 1801 $aPoints = ""; 1802 $aPoints[] = $this->GAreaXOffset; 1803 $aPoints[] = $LayerHeight; 1804 1805 $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight); 1806 $C_White = $this->AllocateColor($this->Layers[0],255,255,255); 1807 imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White); 1808 imagecolortransparent($this->Layers[0],$C_White); 1809 1810 $XPos = $this->GAreaXOffset; 1811 $XLast = -1; $PointsCount = 2; 1812 $YZero = $LayerHeight - ((0-$this->VMin) * $this->DivisionRatio); 1813 if ( $YZero > $LayerHeight ) { $YZero = $LayerHeight; } 1814 1815 $YLast = $Empty; 1816 foreach ( $Data as $Key => $Values ) 1817 { 1818 $Value = $Data[$Key][$ColName]; 1819 $YPos = $LayerHeight - (($Value-$this->VMin) * $this->DivisionRatio); 1820 1821 /* Save point into the image map if option activated */ 1822 if ( $this->BuildMap ) 1823 $this->addToImageMap($XPos-3,$YPos-3,$XPos+3,$YPos+3,$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"FLine"); 1824 1825 if ( !is_numeric($Value) ) 1826 { 1827 $PointsCount++; 1828 $aPoints[] = $XLast; 1829 $aPoints[] = $LayerHeight; 1830 1831 $YLast = $Empty; 1832 } 1833 else 1834 { 1835 $PointsCount++; 1836 if ( $YLast <> $Empty ) 1837 { $aPoints[] = $XPos; $aPoints[] = $YPos; } 1838 else 1839 { $PointsCount++; $aPoints[] = $XPos; $aPoints[] = $LayerHeight; $aPoints[] = $XPos; $aPoints[] = $YPos; } 1840 1841 if ($YLast <> $Empty && $AroundZero) 1842 { 1843 $Points = ""; 1844 $Points[] = $XLast; $Points[] = $YLast; 1845 $Points[] = $XPos; 1846 $Points[] = $YPos; 1847 $Points[] = $XPos; 1848 $Points[] = $YZero; 1849 $Points[] = $XLast; 1850 $Points[] = $YZero; 1851 1852 $C_Graph = $this->AllocateColor($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); 1853 imagefilledpolygon($this->Layers[0],$Points,4,$C_Graph); 1854 } 1855 $YLast = $YPos; 1856 } 1857 1858 $XLast = $XPos; 1859 $XPos = $XPos + $this->DivisionWidth; 1860 } 1861 $aPoints[] = $LayerWidth - $this->GAreaXOffset; 1862 $aPoints[] = $LayerHeight; 1863 1864 if ( $AroundZero == FALSE ) 1865 { 1866 $C_Graph = $this->AllocateColor($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); 1867 imagefilledpolygon($this->Layers[0],$aPoints,$PointsCount,$C_Graph); 1868 } 1869 1870 imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha); 1871 imagedestroy($this->Layers[0]); 1872 $GraphID++; 1873 $this->drawLineGraph($Data,$DataDescription,$ColName); 1874 } 1875 } 1876 1877 /* This function draw a bar graph */ 1878 function drawOverlayBarGraph($Data,$DataDescription,$Alpha=50) 1879 { 1880 /* Validate the Data and DataDescription array */ 1881 $this->validateDataDescription("drawOverlayBarGraph",$DataDescription); 1882 $this->validateData("drawOverlayBarGraph",$Data); 1883 1884 $LayerWidth = $this->GArea_X2-$this->GArea_X1; 1885 $LayerHeight = $this->GArea_Y2-$this->GArea_Y1; 1886 1887 $GraphID = 0; 1888 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 1889 { 1890 $ID = 0; 1891 foreach ( $DataDescription["Description"] as $keyI => $ValueI ) 1892 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } 1893 1894 $this->Layers[$GraphID] = imagecreatetruecolor($LayerWidth,$LayerHeight); 1895 $C_White = $this->AllocateColor($this->Layers[$GraphID],255,255,255); 1896 $C_Graph = $this->AllocateColor($this->Layers[$GraphID],$this->Palette[$GraphID]["R"],$this->Palette[$GraphID]["G"],$this->Palette[$GraphID]["B"]); 1897 imagefilledrectangle($this->Layers[$GraphID],0,0,$LayerWidth,$LayerHeight,$C_White); 1898 imagecolortransparent($this->Layers[$GraphID],$C_White); 1899 1900 $XWidth = $this->DivisionWidth / 4; 1901 $XPos = $this->GAreaXOffset; 1902 $YZero = $LayerHeight - ((0-$this->VMin) * $this->DivisionRatio); 1903 $XLast = -1; $PointsCount = 2; 1904 foreach ( $Data as $Key => $Values ) 1905 { 1906 if ( isset($Data[$Key][$ColName]) ) 1907 { 1908 $Value = $Data[$Key][$ColName]; 1909 if ( is_numeric($Value) ) 1910 { 1911 $YPos = $LayerHeight - (($Value-$this->VMin) * $this->DivisionRatio); 1912 1913 imagefilledrectangle($this->Layers[$GraphID],$XPos-$XWidth,$YPos,$XPos+$XWidth,$YZero,$C_Graph); 1914 1915 $X1 = floor($XPos - $XWidth + $this->GArea_X1); $Y1 = floor($YPos+$this->GArea_Y1) + .2; 1916 $X2 = floor($XPos + $XWidth + $this->GArea_X1); $Y2 = $this->GArea_Y2 - ((0-$this->VMin) * $this->DivisionRatio); 1917 if ( $X1 <= $this->GArea_X1 ) { $X1 = $this->GArea_X1 + 1; } 1918 if ( $X2 >= $this->GArea_X2 ) { $X2 = $this->GArea_X2 - 1; } 1919 1920 /* Save point into the image map if option activated */ 1921 if ( $this->BuildMap ) 1922 $this->addToImageMap($X1,min($Y1,$Y2),$X2,max($Y1,$Y2),$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"oBar"); 1923 1924 $this->drawLine($X1,$Y1,$X2,$Y1,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE); 1925 } 1926 } 1927 $XPos = $XPos + $this->DivisionWidth; 1928 } 1929 1930 $GraphID++; 1931 } 1932 1933 for($i=0;$i<=($GraphID-1);$i++) 1934 { 1935 imagecopymerge($this->Picture,$this->Layers[$i],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha); 1936 imagedestroy($this->Layers[$i]); 1937 } 1938 } 1939 1940 /* This function draw a bar graph */ 1941 function drawBarGraph($Data,$DataDescription,$Shadow=FALSE,$Alpha=100) 1942 { 1943 /* Validate the Data and DataDescription array */ 1944 $this->validateDataDescription("drawBarGraph",$DataDescription); 1945 $this->validateData("drawBarGraph",$Data); 1946 1947 $GraphID = 0; 1948 $Series = count($DataDescription["Values"]); 1949 $SeriesWidth = $this->DivisionWidth / ($Series+1); 1950 $SerieXOffset = $this->DivisionWidth / 2 - $SeriesWidth / 2; 1951 1952 $YZero = $this->GArea_Y2 - ((0-$this->VMin) * $this->DivisionRatio); 1953 if ( $YZero > $this->GArea_Y2 ) { $YZero = $this->GArea_Y2; } 1954 1955 $SerieID = 0; 1956 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 1957 { 1958 $ID = 0; 1959 foreach ( $DataDescription["Description"] as $keyI => $ValueI ) 1960 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } 1961 1962 $XPos = $this->GArea_X1 + $this->GAreaXOffset - $SerieXOffset + $SeriesWidth * $SerieID; 1963 $XLast = -1; 1964 foreach ( $Data as $Key => $Values ) 1965 { 1966 if ( isset($Data[$Key][$ColName])) 1967 { 1968 if ( is_numeric($Data[$Key][$ColName]) ) 1969 { 1970 $Value = $Data[$Key][$ColName]; 1971 $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio); 1972 1973 /* Save point into the image map if option activated */ 1974 if ( $this->BuildMap ) 1975 { 1976 $this->addToImageMap($XPos+1,min($YZero,$YPos),$XPos+$SeriesWidth-1,max($YZero,$YPos),$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"Bar"); 1977 } 1978 1979 if ( $Shadow && $Alpha == 100 ) 1980 $this->drawRectangle($XPos+1,$YZero,$XPos+$SeriesWidth-1,$YPos,25,25,25,TRUE,$Alpha); 1981 1982 $this->drawFilledRectangle($XPos+1,$YZero,$XPos+$SeriesWidth-1,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE,$Alpha); 1983 } 1984 } 1985 $XPos = $XPos + $this->DivisionWidth; 1986 } 1987 $SerieID++; 1988 } 1989 } 1990 1991 /* This function draw a stacked bar graph */ 1992 function drawStackedBarGraph($Data,$DataDescription,$Alpha=50,$Contiguous=FALSE) 1993 { 1994 /* Validate the Data and DataDescription array */ 1995 $this->validateDataDescription("drawBarGraph",$DataDescription); 1996 $this->validateData("drawBarGraph",$Data); 1997 1998 $GraphID = 0; 1999 $Series = count($DataDescription["Values"]); 2000 if ( $Contiguous ) 2001 $SeriesWidth = $this->DivisionWidth; 2002 else 2003 $SeriesWidth = $this->DivisionWidth * .8; 2004 2005 $YZero = $this->GArea_Y2 - ((0-$this->VMin) * $this->DivisionRatio); 2006 if ( $YZero > $this->GArea_Y2 ) { $YZero = $this->GArea_Y2; } 2007 2008 $SerieID = 0; $LastValue = ""; 2009 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 2010 { 2011 $ID = 0; 2012 foreach ( $DataDescription["Description"] as $keyI => $ValueI ) 2013 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } 2014 2015 $XPos = $this->GArea_X1 + $this->GAreaXOffset - $SeriesWidth / 2; 2016 $XLast = -1; 2017 foreach ( $Data as $Key => $Values ) 2018 { 2019 if ( isset($Data[$Key][$ColName])) 2020 { 2021 if ( is_numeric($Data[$Key][$ColName]) ) 2022 { 2023 $Value = $Data[$Key][$ColName]; 2024 2025 if ( isset($LastValue[$Key]) ) 2026 { 2027 $YPos = $this->GArea_Y2 - ((($Value+$LastValue[$Key])-$this->VMin) * $this->DivisionRatio); 2028 $YBottom = $this->GArea_Y2 - (($LastValue[$Key]-$this->VMin) * $this->DivisionRatio); 2029 $LastValue[$Key] += $Value; 2030 } 2031 else 2032 { 2033 $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio); 2034 $YBottom = $YZero; 2035 $LastValue[$Key] = $Value; 2036 } 2037 2038 /* Save point into the image map if option activated */ 2039 if ( $this->BuildMap ) 2040 $this->addToImageMap($XPos+1,min($YBottom,$YPos),$XPos+$SeriesWidth-1,max($YBottom,$YPos),$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"sBar"); 2041 2042 $this->drawFilledRectangle($XPos+1,$YBottom,$XPos+$SeriesWidth-1,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE,$Alpha); 2043 } 2044 } 2045 $XPos = $XPos + $this->DivisionWidth; 2046 } 2047 $SerieID++; 2048 } 2049 } 2050 2051 /* This function draw a limits bar graphs */ 2052 function drawLimitsGraph($Data,$DataDescription,$R=0,$G=0,$B=0) 2053 { 2054 /* Validate the Data and DataDescription array */ 2055 $this->validateDataDescription("drawLimitsGraph",$DataDescription); 2056 $this->validateData("drawLimitsGraph",$Data); 2057 2058 $XWidth = $this->DivisionWidth / 4; 2059 $XPos = $this->GArea_X1 + $this->GAreaXOffset; 2060 2061 foreach ( $Data as $Key => $Values ) 2062 { 2063 $Min = $Data[$Key][$DataDescription["Values"][0]]; 2064 $Max = $Data[$Key][$DataDescription["Values"][0]]; 2065 $GraphID = 0; $MaxID = 0; $MinID = 0; 2066 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 2067 { 2068 if ( isset($Data[$Key][$ColName]) ) 2069 { 2070 if ( $Data[$Key][$ColName] > $Max && is_numeric($Data[$Key][$ColName])) 2071 { $Max = $Data[$Key][$ColName]; $MaxID = $GraphID; } 2072 } 2073 if ( isset($Data[$Key][$ColName]) && is_numeric($Data[$Key][$ColName])) 2074 { 2075 if ( $Data[$Key][$ColName] < $Min ) 2076 { $Min = $Data[$Key][$ColName]; $MinID = $GraphID; } 2077 $GraphID++; 2078 } 2079 } 2080 2081 $YPos = $this->GArea_Y2 - (($Max-$this->VMin) * $this->DivisionRatio); 2082 $X1 = floor($XPos - $XWidth); $Y1 = floor($YPos) - .2; 2083 $X2 = floor($XPos + $XWidth); 2084 if ( $X1 <= $this->GArea_X1 ) { $X1 = $this->GArea_X1 + 1; } 2085 if ( $X2 >= $this->GArea_X2 ) { $X2 = $this->GArea_X2 - 1; } 2086 2087 $YPos = $this->GArea_Y2 - (($Min-$this->VMin) * $this->DivisionRatio); 2088 $Y2 = floor($YPos) + .2; 2089 2090 $this->drawLine(floor($XPos)-.2,$Y1+1,floor($XPos)-.2,$Y2-1,$R,$G,$B,TRUE); 2091 $this->drawLine(floor($XPos)+.2,$Y1+1,floor($XPos)+.2,$Y2-1,$R,$G,$B,TRUE); 2092 $this->drawLine($X1,$Y1,$X2,$Y1,$this->Palette[$MaxID]["R"],$this->Palette[$MaxID]["G"],$this->Palette[$MaxID]["B"],FALSE); 2093 $this->drawLine($X1,$Y2,$X2,$Y2,$this->Palette[$MinID]["R"],$this->Palette[$MinID]["G"],$this->Palette[$MinID]["B"],FALSE); 2094 2095 $XPos = $XPos + $this->DivisionWidth; 2096 } 2097 } 2098 2099 /* This function draw radar axis centered on the graph area */ 2100 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) 2101 { 2102 /* Validate the Data and DataDescription array */ 2103 $this->validateDataDescription("drawRadarAxis",$DataDescription); 2104 $this->validateData("drawRadarAxis",$Data); 2105 2106 $C_TextColor = $this->AllocateColor($this->Picture,$A_R,$A_G,$A_B); 2107 2108 /* Draw radar axis */ 2109 $Points = count($Data); 2110 $Radius = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 - $BorderOffset; 2111 $XCenter = ( $this->GArea_X2 - $this->GArea_X1 ) / 2 + $this->GArea_X1; 2112 $YCenter = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 + $this->GArea_Y1; 2113 2114 /* Search for the max value */ 2115 if ( $MaxValue == -1 ) 2116 { 2117 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 2118 { 2119 foreach ( $Data as $Key => $Values ) 2120 { 2121 if ( isset($Data[$Key][$ColName])) 2122 if ( $Data[$Key][$ColName] > $MaxValue ) { $MaxValue = $Data[$Key][$ColName]; } 2123 } 2124 } 2125 } 2126 2127 /* Draw the mosaic */ 2128 if ( $Mosaic ) 2129 { 2130 $RadiusScale = $Radius / $MaxValue; 2131 for ( $t=1; $t<=$MaxValue-1; $t++) 2132 { 2133 $TRadius = $RadiusScale * $t; 2134 $LastX1 = -1; 2135 2136 for ( $i=0; $i<=$Points; $i++) 2137 { 2138 $Angle = -90 + $i * 360/$Points; 2139 $X1 = cos($Angle * 3.1418 / 180 ) * $TRadius + $XCenter; 2140 $Y1 = sin($Angle * 3.1418 / 180 ) * $TRadius + $YCenter; 2141 $X2 = cos($Angle * 3.1418 / 180 ) * ($TRadius+$RadiusScale) + $XCenter; 2142 $Y2 = sin($Angle * 3.1418 / 180 ) * ($TRadius+$RadiusScale) + $YCenter; 2143 2144 if ( $t % 2 == 1 && $LastX1 != -1) 2145 { 2146 $Plots = ""; 2147 $Plots[] = $X1; $Plots[] = $Y1; 2148 $Plots[] = $X2; $Plots[] = $Y2; 2149 $Plots[] = $LastX2; $Plots[] = $LastY2; 2150 $Plots[] = $LastX1; $Plots[] = $LastY1; 2151 2152 $C_Graph = $this->AllocateColor($this->Picture,250,250,250); 2153 imagefilledpolygon($this->Picture,$Plots,(count($Plots)+1)/2,$C_Graph); 2154 } 2155 2156 $LastX1 = $X1; $LastY1= $Y1; 2157 $LastX2 = $X2; $LastY2= $Y2; 2158 } 2159 } 2160 } 2161 2162 2163 /* Draw the spider web */ 2164 for ( $t=1; $t<=$MaxValue; $t++) 2165 { 2166 $TRadius = ( $Radius / $MaxValue ) * $t; 2167 $LastX = -1; 2168 2169 for ( $i=0; $i<=$Points; $i++) 2170 { 2171 $Angle = -90 + $i * 360/$Points; 2172 $X = cos($Angle * 3.1418 / 180 ) * $TRadius + $XCenter; 2173 $Y = sin($Angle * 3.1418 / 180 ) * $TRadius + $YCenter; 2174 2175 if ( $LastX != -1 ) 2176 $this->drawDottedLine($LastX,$LastY,$X,$Y,4,$S_R,$S_G,$S_B); 2177 2178 $LastX = $X; $LastY= $Y; 2179 } 2180 } 2181 2182 /* Draw the axis */ 2183 for ( $i=0; $i<=$Points; $i++) 2184 { 2185 $Angle = -90 + $i * 360/$Points; 2186 $X = cos($Angle * 3.1418 / 180 ) * $Radius + $XCenter; 2187 $Y = sin($Angle * 3.1418 / 180 ) * $Radius + $YCenter; 2188 2189 $this->drawLine($XCenter,$YCenter,$X,$Y,$A_R,$A_G,$A_B); 2190 2191 $XOffset = 0; $YOffset = 0; 2192 if (isset($Data[$i][$DataDescription["Position"]])) 2193 { 2194 $Label = $Data[$i][$DataDescription["Position"]]; 2195 2196 $Positions = imagettfbbox($this->FontSize,0,$this->FontName,$Label); 2197 $Width = $Positions[2] - $Positions[6]; 2198 $Height = $Positions[3] - $Positions[7]; 2199 2200 if ( $Angle >= 0 && $Angle <= 90 ) 2201 $YOffset = $Height; 2202 2203 if ( $Angle > 90 && $Angle <= 180 ) 2204 { $YOffset = $Height; $XOffset = -$Width; } 2205 2206 if ( $Angle > 180 && $Angle <= 270 ) 2207 { $XOffset = -$Width; } 2208 2209 imagettftext($this->Picture,$this->FontSize,0,$X+$XOffset,$Y+$YOffset,$C_TextColor,$this->FontName,$Label); 2210 } 2211 } 2212 2213 /* Write the values */ 2214 for ( $t=1; $t<=$MaxValue; $t++) 2215 { 2216 $TRadius = ( $Radius / $MaxValue ) * $t; 2217 2218 $Angle = -90 + 360 / $Points; 2219 $X1 = $XCenter; 2220 $Y1 = $YCenter - $TRadius; 2221 $X2 = cos($Angle * 3.1418 / 180 ) * $TRadius + $XCenter; 2222 $Y2 = sin($Angle * 3.1418 / 180 ) * $TRadius + $YCenter; 2223 2224 $XPos = floor(($X2-$X1)/2) + $X1; 2225 $YPos = floor(($Y2-$Y1)/2) + $Y1; 2226 2227 $Positions = imagettfbbox($this->FontSize,0,$this->FontName,$t); 2228 $X = $XPos - ( $X+$Positions[2] - $X+$Positions[6] ) / 2; 2229 $Y = $YPos + $this->FontSize; 2230 2231 $this->drawFilledRoundedRectangle($X+$Positions[6]-2,$Y+$Positions[7]-1,$X+$Positions[2]+4,$Y+$Positions[3]+1,2,240,240,240); 2232 $this->drawRoundedRectangle($X+$Positions[6]-2,$Y+$Positions[7]-1,$X+$Positions[2]+4,$Y+$Positions[3]+1,2,220,220,220); 2233 imagettftext($this->Picture,$this->FontSize,0,$X,$Y,$C_TextColor,$this->FontName,$t); 2234 } 2235 } 2236 2237 /* This function draw a radar graph centered on the graph area */ 2238 function drawRadar($Data,$DataDescription,$BorderOffset=10,$MaxValue=-1) 2239 { 2240 /* Validate the Data and DataDescription array */ 2241 $this->validateDataDescription("drawRadar",$DataDescription); 2242 $this->validateData("drawRadar",$Data); 2243 2244 $Points = count($Data); 2245 $Radius = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 - $BorderOffset; 2246 $XCenter = ( $this->GArea_X2 - $this->GArea_X1 ) / 2 + $this->GArea_X1; 2247 $YCenter = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 + $this->GArea_Y1; 2248 2249 /* Search for the max value */ 2250 if ( $MaxValue == -1 ) 2251 { 2252 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 2253 { 2254 foreach ( $Data as $Key => $Values ) 2255 { 2256 if ( isset($Data[$Key][$ColName])) 2257 if ( $Data[$Key][$ColName] > $MaxValue ) { $MaxValue = $Data[$Key][$ColName]; } 2258 } 2259 } 2260 } 2261 2262 $GraphID = 0; 2263 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 2264 { 2265 $ID = 0; 2266 foreach ( $DataDescription["Description"] as $keyI => $ValueI ) 2267 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } 2268 2269 $Angle = -90; 2270 $XLast = -1; 2271 foreach ( $Data as $Key => $Values ) 2272 { 2273 if ( isset($Data[$Key][$ColName])) 2274 { 2275 $Value = $Data[$Key][$ColName]; 2276 $Strength = ( $Radius / $MaxValue ) * $Value; 2277 2278 $XPos = cos($Angle * 3.1418 / 180 ) * $Strength + $XCenter; 2279 $YPos = sin($Angle * 3.1418 / 180 ) * $Strength + $YCenter; 2280 2281 if ( $XLast != -1 ) 2282 $this->drawLine($XLast,$YLast,$XPos,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); 2283 2284 if ( $XLast == -1 ) 2285 { $FirstX = $XPos; $FirstY = $YPos; } 2286 2287 $Angle = $Angle + (360/$Points); 2288 $XLast = $XPos; 2289 $YLast = $YPos; 2290 } 2291 } 2292 $this->drawLine($XPos,$YPos,$FirstX,$FirstY,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); 2293 $GraphID++; 2294 } 2295 } 2296 2297 /* This function draw a radar graph centered on the graph area */ 2298 function drawFilledRadar($Data,$DataDescription,$Alpha=50,$BorderOffset=10,$MaxValue=-1) 2299 { 2300 /* Validate the Data and DataDescription array */ 2301 $this->validateDataDescription("drawFilledRadar",$DataDescription); 2302 $this->validateData("drawFilledRadar",$Data); 2303 2304 $Points = count($Data); 2305 $LayerWidth = $this->GArea_X2-$this->GArea_X1; 2306 $LayerHeight = $this->GArea_Y2-$this->GArea_Y1; 2307 $Radius = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 - $BorderOffset; 2308 $XCenter = ( $this->GArea_X2 - $this->GArea_X1 ) / 2; 2309 $YCenter = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2; 2310 2311 /* Search for the max value */ 2312 if ( $MaxValue == -1 ) 2313 { 2314 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 2315 { 2316 foreach ( $Data as $Key => $Values ) 2317 { 2318 if ( isset($Data[$Key][$ColName])) 2319 if ( $Data[$Key][$ColName] > $MaxValue && is_numeric($Data[$Key][$ColName])) { $MaxValue = $Data[$Key][$ColName]; } 2320 } 2321 } 2322 } 2323 2324 $GraphID = 0; 2325 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 2326 { 2327 $ID = 0; 2328 foreach ( $DataDescription["Description"] as $keyI => $ValueI ) 2329 { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } 2330 2331 $Angle = -90; 2332 $XLast = -1; 2333 $Plots = ""; 2334 foreach ( $Data as $Key => $Values ) 2335 { 2336 if ( isset($Data[$Key][$ColName])) 2337 { 2338 $Value = $Data[$Key][$ColName]; 2339 if ( !is_numeric($Value) ) { $Value = 0; } 2340 $Strength = ( $Radius / $MaxValue ) * $Value; 2341 2342 $XPos = cos($Angle * 3.1418 / 180 ) * $Strength + $XCenter; 2343 $YPos = sin($Angle * 3.1418 / 180 ) * $Strength + $YCenter; 2344 2345 $Plots[] = $XPos; 2346 $Plots[] = $YPos; 2347 2348 $Angle = $Angle + (360/$Points); 2349 $XLast = $XPos; 2350 $YLast = $YPos; 2351 } 2352 } 2353 2354 if (isset($Plots[0])) 2355 { 2356 $Plots[] = $Plots[0]; 2357 $Plots[] = $Plots[1]; 2358 2359 $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight); 2360 $C_White = $this->AllocateColor($this->Layers[0],255,255,255); 2361 imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White); 2362 imagecolortransparent($this->Layers[0],$C_White); 2363 2364 $C_Graph = $this->AllocateColor($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); 2365 imagefilledpolygon($this->Layers[0],$Plots,(count($Plots)+1)/2,$C_Graph); 2366 2367 imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha); 2368 imagedestroy($this->Layers[0]); 2369 2370 for($i=0;$i<=count($Plots)-4;$i=$i+2) 2371 $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"]); 2372 } 2373 2374 $GraphID++; 2375 } 2376 } 2377 2378 /* This function draw a flat pie chart */ 2379 function drawBasicPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$R=255,$G=255,$B=255,$Decimals=0) 2380 { 2381 /* Validate the Data and DataDescription array */ 2382 $this->validateDataDescription("drawBasicPieGraph",$DataDescription,FALSE); 2383 $this->validateData("drawBasicPieGraph",$Data); 2384 2385 /* Determine pie sum */ 2386 $Series = 0; $PieSum = 0; 2387 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 2388 { 2389 if ( $ColName != $DataDescription["Position"] ) 2390 { 2391 $Series++; 2392 foreach ( $Data as $Key => $Values ) 2393 { 2394 if ( isset($Data[$Key][$ColName])) 2395 $PieSum = $PieSum + $Data[$Key][$ColName]; $iValues[] = $Data[$Key][$ColName]; $iLabels[] = $Data[$Key][$DataDescription["Position"]]; 2396 } 2397 } 2398 } 2399 2400 /* Validate serie */ 2401 if ( $Series != 1 ) 2402 RaiseFatal("Pie chart can only accept one serie of data."); 2403 2404 $SpliceRatio = 360 / $PieSum; 2405 $SplicePercent = 100 / $PieSum; 2406 2407 /* Calculate all polygons */ 2408 $Angle = 0; $TopPlots = ""; 2409 foreach($iValues as $Key => $Value) 2410 { 2411 $TopPlots[$Key][] = $XPos; 2412 $TopPlots[$Key][] = $YPos; 2413 2414 /* Process labels position & size */ 2415 $Caption = ""; 2416 if ( !($DrawLabels == PIE_NOLABEL) ) 2417 { 2418 $TAngle = $Angle+($Value*$SpliceRatio/2); 2419 if ($DrawLabels == PIE_PERCENTAGE) 2420 $Caption = (round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%"; 2421 elseif ($DrawLabels == PIE_LABELS) 2422 $Caption = $iLabels[$Key]; 2423 elseif ($DrawLabels == PIE_PERCENTAGE_LABEL) 2424 $Caption = $iLabels[$Key]."\r\n".(round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%"; 2425 elseif ($DrawLabels == PIE_PERCENTAGE_LABEL) 2426 $Caption = $iLabels[$Key]."\r\n".(round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%"; 2427 2428 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Caption); 2429 $TextWidth = $Position[2]-$Position[0]; 2430 $TextHeight = abs($Position[1])+abs($Position[3]); 2431 2432 $TX = cos(($TAngle) * 3.1418 / 180 ) * ($Radius+10) + $XPos; 2433 2434 if ( $TAngle > 0 && $TAngle < 180 ) 2435 $TY = sin(($TAngle) * 3.1418 / 180 ) * ($Radius+10) + $YPos + 4; 2436 else 2437 $TY = sin(($TAngle) * 3.1418 / 180 ) * ($Radius+4) + $YPos - ($TextHeight/2); 2438 2439 if ( $TAngle > 90 && $TAngle < 270 ) 2440 $TX = $TX - $TextWidth; 2441 2442 $C_TextColor = $this->AllocateColor($this->Picture,70,70,70); 2443 imagettftext($this->Picture,$this->FontSize,0,$TX,$TY,$C_TextColor,$this->FontName,$Caption); 2444 } 2445 2446 /* Process pie slices */ 2447 for($iAngle=$Angle;$iAngle<=$Angle+$Value*$SpliceRatio;$iAngle=$iAngle+.5) 2448 { 2449 $TopX = cos($iAngle * 3.1418 / 180 ) * $Radius + $XPos; 2450 $TopY = sin($iAngle * 3.1418 / 180 ) * $Radius + $YPos; 2451 2452 $TopPlots[$Key][] = $TopX; 2453 $TopPlots[$Key][] = $TopY; 2454 } 2455 2456 $TopPlots[$Key][] = $XPos; 2457 $TopPlots[$Key][] = $YPos; 2458 2459 $Angle = $iAngle; 2460 } 2461 $PolyPlots = $TopPlots; 2462 2463 /* Set array values type to float --- PHP Bug with imagefilledpolygon casting to integer */ 2464 foreach ($TopPlots as $Key => $Value) 2465 { foreach ($TopPlots[$Key] as $Key2 => $Value2) { settype($TopPlots[$Key][$Key2],"float"); } } 2466 2467 /* Draw Top polygons */ 2468 foreach ($PolyPlots as $Key => $Value) 2469 { 2470 $C_GraphLo = $this->AllocateColor($this->Picture,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"]); 2471 imagefilledpolygon($this->Picture,$PolyPlots[$Key],(count($PolyPlots[$Key])+1)/2,$C_GraphLo); 2472 } 2473 2474 $this->drawCircle($XPos-.5,$YPos-.5,$Radius,$R,$G,$B); 2475 $this->drawCircle($XPos-.5,$YPos-.5,$Radius+.5,$R,$G,$B); 2476 2477 /* Draw Top polygons */ 2478 foreach ($TopPlots as $Key => $Value) 2479 { 2480 for($j=0;$j<=count($TopPlots[$Key])-4;$j=$j+2) 2481 $this->drawLine($TopPlots[$Key][$j],$TopPlots[$Key][$j+1],$TopPlots[$Key][$j+2],$TopPlots[$Key][$j+3],$R,$G,$B); 2482 } 2483 } 2484 2485 function drawFlatPieGraphWithShadow($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$SpliceDistance=0,$Decimals=0) 2486 { 2487 $this->drawFlatPieGraph($Data,$DataDescription,$XPos+$this->ShadowXDistance,$YPos+$this->ShadowYDistance,$Radius,PIE_NOLABEL,$SpliceDistance,$Decimals,TRUE); 2488 $this->drawFlatPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius,$DrawLabels,$SpliceDistance,$Decimals,FALSE); 2489 } 2490 2491 /* This function draw a flat pie chart */ 2492 function drawFlatPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$SpliceDistance=0,$Decimals=0,$AllBlack=FALSE) 2493 { 2494 /* Validate the Data and DataDescription array */ 2495 $this->validateDataDescription("drawFlatPieGraph",$DataDescription,FALSE); 2496 $this->validateData("drawFlatPieGraph",$Data); 2497 2498 $ShadowStatus = $this->ShadowActive ; $this->ShadowActive = FALSE; 2499 2500 /* Determine pie sum */ 2501 $Series = 0; $PieSum = 0; 2502 foreach ( $DataDescription["Values"] as $Key2 => $ColName ) 2503 { 2504 if ( $ColName != $DataDescription["Position"] ) 2505 { 2506 $Series++; 2507 foreach ( $Data as $Key => $Values ) 2508 { 2509 if ( isset($Data[$Key][$ColName])) 2510 $PieSum = $PieSum + $Data[$Key][$ColName]; $iValues[] = $Data[$Key][$ColName]; $iLabels[] = $Data[$Key][$DataDescription["Position"]]; 2511 } 2512 } 2513 } 2514 2515 /* Validate serie */ 2516 if ( $Series != 1 ) 2517 { 2518 RaiseFatal("Pie chart can only accept one serie of data."); 2519 return(0); 2520 } 2521 2522 $SpliceRatio = 360 / $PieSum; 2523 $SplicePercent = 100 / $PieSum; 2524 2525 /* Calculate all polygons */ 2526 $Angle = 0; $TopPlots = ""; 2527 foreach($iValues as $Key => $Value) 2528 { 2529 $XOffset = cos(($Angle+($Value/2*$SpliceRatio)) * 3.1418 / 180 ) * $SpliceDistance; 2530 $YOffset = sin(($Angle+($Value/2*$SpliceRatio)) * 3.1418 / 180 ) * $SpliceDistance; 2531 2532 $TopPlots[$Key][] = round($XPos + $XOffset); 2533 $TopPlots[$Key][] = round($YPos + $YOffset); 2534 2535 if ( $AllBlack ) 2536 { $Rc = $this->ShadowRColor; $Gc = $this->ShadowGColor; $Bc = $this->ShadowBColor; } 2537 else 2538 { $Rc = $this->Palette[$Key]["R"]; $Gc = $this->Palette[$Key]["G"]; $Bc = $this->Palette[$Key]["B"]; } 2539 2540 $XLineLast = ""; $YLineLast = ""; 2541 2542 /* Process labels position & size */ 2543 $Caption = ""; 2544 if ( !($DrawLabels == PIE_NOLABEL) ) 2545 { 2546 $TAngle = $Angle+($Value*$SpliceRatio/2); 2547 if ($DrawLabels == PIE_PERCENTAGE) 2548 $Caption = (round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%"; 2549 elseif ($DrawLabels == PIE_LABELS) 2550 $Caption = $iLabels[$Key]; 2551 elseif ($DrawLabels == PIE_PERCENTAGE_LABEL) 2552 $Caption = $iLabels[$Key]."\r\n".(round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%"; 2553 elseif ($DrawLabels == PIE_PERCENTAGE_LABEL) 2554 $Caption = $iLabels[$Key]."\r\n".(round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%"; 2555 2556 $Position = imageftbbox($this->FontSize,0,$this->FontName,$Caption); 2557 $TextWidth = $Position[2]-$Position[0]; 2558 $TextHeight = abs($Position[1])+abs($Position[3]); 2559 2560 $TX =