1<?php 2 /* 3 pPie - class to draw pie charts 4 5 Version : 2.1.0 6 Made by : Jean-Damien POGOLOTTI 7 Last Update : 26/01/11 8 9 This file can be distributed under the license you can find at : 10 11 http://www.pchart.net/license 12 13 You can find the whole class documentation on the pChart web site. 14 */ 15 16 /* Class return codes */ 17 define("PIE_NO_ABSCISSA" , 140001); 18 define("PIE_NO_DATASERIE" , 140002); 19 define("PIE_SUMISNULL" , 140003); 20 define("PIE_RENDERED" , 140000); 21 22 define("PIE_LABEL_COLOR_AUTO" , 140010); 23 define("PIE_LABEL_COLOR_MANUAL", 140011); 24 25 define("PIE_VALUE_NATURAL" , 140020); 26 define("PIE_VALUE_PERCENTAGE" , 140021); 27 28 /* pPie class definition */ 29 class pPie 30 { 31 var $pChartObject; 32 var $pDataObject; 33 34 /* Class creator */ 35 function pPie($Object,$pDataObject) 36 { 37 /* Cache the pChart object reference */ 38 $this->pChartObject = $Object; 39 40 /* Cache the pData object reference */ 41 $this->pDataObject = $pDataObject; 42 } 43 44 /* Draw a pie chart */ 45 function draw2DPie($X,$Y,$Format="") 46 { 47 /* Rendering layout */ 48 $Radius = isset($Format["Radius"]) ? $Format["Radius"] : 60; 49 $DataGapAngle = isset($Format["DataGapAngle"]) ? $Format["DataGapAngle"] : 0; 50 $DataGapRadius = isset($Format["DataGapRadius"]) ? $Format["DataGapRadius"] : 0; 51 $SecondPass = isset($Format["SecondPass"]) ? $Format["SecondPass"] : TRUE; 52 $Border = isset($Format["Border"]) ? $Format["Border"] : FALSE; 53 $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255; 54 $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255; 55 $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255; 56 $Shadow = isset($Format["Shadow"]) ? $Format["Shadow"] : FALSE; 57 $DrawLabels = isset($Format["DrawLabels"]) ? $Format["DrawLabels"] : FALSE; 58 $LabelColor = isset($Format["LabelColor"]) ? $Format["LabelColor"] : PIE_LABEL_COLOR_MANUAL; 59 $LabelR = isset($Format["LabelR"]) ? $Format["LabelR"] : 0; 60 $LabelG = isset($Format["LabelG"]) ? $Format["LabelG"] : 0; 61 $LabelB = isset($Format["LabelB"]) ? $Format["LabelB"] : 0; 62 $LabelAlpha = isset($Format["LabelAlpha"]) ? $Format["LabelAlpha"] : 100; 63 64 /* Data Processing */ 65 $Data = $this->pDataObject->getData(); 66 $Palette = $this->pDataObject->getPalette(); 67 68 /* Do we have an abscissa serie defined? */ 69 if ( $Data["Abscissa"] == "" ) { return(PIE_NO_ABSCISSA); } 70 71 /* Try to find the data serie */ 72 $DataSerie = ""; 73 foreach ($Data["Series"] as $SerieName => $SerieData) 74 { if ( $SerieName != $Data["Abscissa"]) { $DataSerie = $SerieName; } } 75 76 /* Do we have data to compute? */ 77 if ( $DataSerie == "" ) { return(PIE_NO_DATASERIE); } 78 79 /* Compute the pie sum */ 80 $SerieSum = $this->pDataObject->getSum($DataSerie); 81 82 /* Do we have data to draw? */ 83 if ( $SerieSum == 0 ) { return(PIE_SUMISNULL); } 84 85 /* Dump the real number of data to draw */ 86 $Values = ""; 87 $PaletteAux = array(); // Fix to store only necesary colors 88 foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value) 89 { if ($Value != 0) { $Values[$Key] = $Value; $PaletteAux[] = $Palette[$Key]; } } 90 91 $Palette = $PaletteAux; 92 93 /* Compute the wasted angular space between series */ 94 if (count($Values)==1) { $WastedAngular = 0; } else { $WastedAngular = count($Values) * $DataGapAngle; } 95 96 /* Compute the scale */ 97 $ScaleFactor = (360 - $WastedAngular) / $SerieSum; 98 99 $RestoreShadow = $this->pChartObject->Shadow; 100 if ( $this->pChartObject->Shadow ) 101 { 102 $this->pChartObject->Shadow = FALSE; 103 104 $ShadowFormat = $Format; $ShadowFormat["Shadow"] = TRUE; 105 $this->draw2DPie($X+$this->pChartObject->ShadowX,$Y+$this->pChartObject->ShadowY,$ShadowFormat); 106 } 107 108 /* Draw the polygon pie elements */ 109 $Step = 360 / (2 * PI * $Radius); 110 $Offset = 0; $ID = 0; 111 foreach($Values as $Key => $Value) 112 { 113 if ( $Shadow ) 114 $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa); 115 else 116 $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]); 117 118 if ( !$SecondPass && !$Shadow ) 119 { 120 if ( !$Border ) 121 $Settings["Surrounding"] = 10; 122 else 123 { $Settings["BorderR"] = $BorderR; $Settings["BorderG"] = $BorderG; $Settings["BorderB"] = $BorderB; } 124 } 125 126 $Plots = ""; 127 $EndAngle = $Offset+($Value*$ScaleFactor); if ( $EndAngle > 360 ) { $EndAngle = 360; } 128 129 $Angle = ($EndAngle - $Offset)/2 + $Offset; 130 if ($DataGapAngle == 0) 131 { $X0 = $X; $Y0 = $Y; } 132 else 133 { 134 $X0 = cos(($Angle-90)*PI/180) * $DataGapRadius + $X; 135 $Y0 = sin(($Angle-90)*PI/180) * $DataGapRadius + $Y; 136 } 137 138 $Plots[] = $X0; $Plots[] = $Y0; 139 140 141 for($i=$Offset;$i<=$EndAngle;$i=$i+$Step) 142 { 143 $Xc = cos(($i-90)*PI/180) * $Radius + $X; 144 $Yc = sin(($i-90)*PI/180) * $Radius + $Y; 145 146 if ( $SecondPass && ( $i<90 )) { $Yc++; } 147 if ( $SecondPass && ( $i>180 && $i<270 )) { $Xc++; } 148 if ( $SecondPass && ( $i>=270 )) { $Xc++; $Yc++; } 149 150 $Plots[] = $Xc; $Plots[] = $Yc; 151 } 152 153 $this->pChartObject->drawPolygon($Plots,$Settings); 154 155 if ( $DrawLabels && !$Shadow && !$SecondPass ) 156 { 157 if ( $LabelColor == PIE_LABEL_COLOR_AUTO ) 158 { $Settings = array("FillR"=>$Palette[$ID]["R"],"FillG"=>$Palette[$ID]["G"],"FillB"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);} 159 else 160 { $Settings = array("FillR"=>$LabelR,"FillG"=>$LabelG,"FillB"=>$LabelB,"Alpha"=>$LabelAlpha); } 161 162 $Angle = ($EndAngle - $Offset)/2 + $Offset; 163 $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; 164 $Yc = sin(($Angle-90)*PI/180) * $Radius + $Y; 165 166 $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$Key]; 167 168 $Settings["Angle"] = 360-$Angle; 169 $Settings["Length"] = 25; 170 $Settings["Size"] = 8; 171 $this->pChartObject->drawArrowLabel($Xc,$Yc," ".$Label." ",$Settings); 172 } 173 174 $Offset = $i + $DataGapAngle; $ID++; 175 } 176 177 /* Second pass to smooth the angles */ 178 if ( $SecondPass ) 179 { 180 $Step = 360 / (2 * PI * $Radius); 181 $Offset = 0; $ID = 0; 182 foreach($Values as $Key => $Value) 183 { 184 $FirstPoint = TRUE; 185 if ( $Shadow ) 186 $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa); 187 else 188 { 189 if ( $Border ) 190 $Settings = array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB); 191 else 192 $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]); 193 } 194 195 $EndAngle = $Offset+($Value*$ScaleFactor); if ( $EndAngle > 360 ) { $EndAngle = 360; } 196 197 if ($DataGapAngle == 0) 198 { $X0 = $X; $Y0 = $Y; } 199 else 200 { 201 $Angle = ($EndAngle - $Offset)/2 + $Offset; 202 $X0 = cos(($Angle-90)*PI/180) * $DataGapRadius + $X; 203 $Y0 = sin(($Angle-90)*PI/180) * $DataGapRadius + $Y; 204 } 205 $Plots[] = $X0; $Plots[] = $Y0; 206 207 for($i=$Offset;$i<=$EndAngle;$i=$i+$Step) 208 { 209 $Xc = cos(($i-90)*PI/180) * $Radius + $X; 210 $Yc = sin(($i-90)*PI/180) * $Radius + $Y; 211 212 if ( $FirstPoint ) { $this->pChartObject->drawLine($Xc,$Yc,$X0,$Y0,$Settings); } { $FirstPoint = FALSE; } 213 214 $this->pChartObject->drawAntialiasPixel($Xc,$Yc,$Settings); 215 } 216 $this->pChartObject->drawLine($Xc,$Yc,$X0,$Y0,$Settings); 217 218 if ( $DrawLabels && !$Shadow ) 219 { 220 if ( $LabelColor == PIE_LABEL_COLOR_AUTO ) 221 { $Settings = array("FillR"=>$Palette[$ID]["R"],"FillG"=>$Palette[$ID]["G"],"FillB"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);} 222 else 223 { $Settings = array("FillR"=>$LabelR,"FillG"=>$LabelG,"FillB"=>$LabelB,"Alpha"=>$LabelAlpha); } 224 225 $Angle = ($EndAngle - $Offset)/2 + $Offset; 226 $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; 227 $Yc = sin(($Angle-90)*PI/180) * $Radius + $Y; 228 229 $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$Key]; 230 231 $Settings["Angle"] = 360-$Angle; 232 $Settings["Length"] = 25; 233 $Settings["Size"] = 8; 234 235 $this->pChartObject->drawArrowLabel($Xc,$Yc," ".$Label." ",$Settings); 236 } 237 238 $Offset = $i + $DataGapAngle; $ID++; 239 } 240 } 241 242 $this->pChartObject->Shadow = $RestoreShadow; 243 244 return(PIE_RENDERED); 245 } 246 247 /* Draw a 3D pie chart */ 248 function draw3DPie($X,$Y,$Format="") 249 { 250 /* Rendering layout */ 251 $Radius = isset($Format["Radius"]) ? $Format["Radius"] : 80; 252 $SkewFactor = isset($Format["SkewFactor"]) ? $Format["SkewFactor"] : .5; 253 $SliceHeight = isset($Format["SliceHeight"]) ? $Format["SliceHeight"] : 20; 254 $DataGapAngle = isset($Format["DataGapAngle"]) ? $Format["DataGapAngle"] : 0; 255 $DataGapRadius = isset($Format["DataGapRadius"]) ? $Format["DataGapRadius"] : 0; 256 $SecondPass = isset($Format["SecondPass"]) ? $Format["SecondPass"] : TRUE; 257 $Border = isset($Format["Border"]) ? $Format["Border"] : FALSE; 258 $Shadow = isset($Format["Shadow"]) ? $Format["Shadow"] : FALSE; 259 $DrawLabels = isset($Format["DrawLabels"]) ? $Format["DrawLabels"] : FALSE; 260 $LabelColor = isset($Format["LabelColor"]) ? $Format["LabelColor"] : PIE_LABEL_COLOR_MANUAL; 261 $LabelR = isset($Format["LabelR"]) ? $Format["LabelR"] : 0; 262 $LabelG = isset($Format["LabelG"]) ? $Format["LabelG"] : 0; 263 $LabelB = isset($Format["LabelB"]) ? $Format["LabelB"] : 0; 264 $LabelAlpha = isset($Format["LabelAlpha"]) ? $Format["LabelAlpha"] : 100; 265 $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : PIE_VALUE_PERCENTAGE; 266 $ValueSuffix = isset($Format["ValueSuffix"]) ? $Format["ValueSuffix"] : ""; 267 $ValueR = isset($Format["ValueR"]) ? $Format["ValueR"] : 255; 268 $ValueG = isset($Format["ValueG"]) ? $Format["ValueG"] : 255; 269 $ValueB = isset($Format["ValueB"]) ? $Format["ValueB"] : 255; 270 $ValueAlpha = isset($Format["ValueAlpha"]) ? $Format["ValueAlpha"] : 100; 271 272 /* Error correction for overlaying rounded corners */ 273 if ( $SkewFactor < .5 ) { $SkewFactor = .5; } 274 275 /* Data Processing */ 276 $Data = $this->pDataObject->getData(); 277 $Palette = $this->pDataObject->getPalette(); 278 279 /* Do we have an abscissa serie defined? */ 280 if ( $Data["Abscissa"] == "" ) { return(PIE_NO_ABSCISSA); } 281 282 /* Try to find the data serie */ 283 $DataSerie = ""; 284 foreach ($Data["Series"] as $SerieName => $SerieData) 285 { if ( $SerieName != $Data["Abscissa"]) { $DataSerie = $SerieName; } } 286 287 /* Do we have data to compute? */ 288 if ( $DataSerie == "" ) { return(PIE_NO_DATASERIE); } 289 290 /* Compute the pie sum */ 291 $SerieSum = $this->pDataObject->getSum($DataSerie); 292 293 /* Do we have data to draw? */ 294 if ( $SerieSum == 0 ) { return(PIE_SUMISNULL); } 295 296 /* Dump the real number of data to draw */ 297 $Values = ""; 298 $PaletteAux = array(); // Fix to store only necesary colors 299 foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value) 300 { if ($Value != 0) { $Values[$Key] = $Value; $PaletteAux[] = $Palette[$Key]; } } 301 302 $Palette = $PaletteAux; 303 304 /* Compute the wasted angular space between series */ 305 if (count($Values)==1) { $WastedAngular = 0; } else { $WastedAngular = count($Values) * $DataGapAngle; } 306 307 /* Compute the scale */ 308 $ScaleFactor = (360 - $WastedAngular) / $SerieSum; 309 310 $RestoreShadow = $this->pChartObject->Shadow; 311 if ( $this->pChartObject->Shadow ) { $this->pChartObject->Shadow = FALSE; } 312 313 /* Draw the polygon pie elements */ 314 $Step = 360 / (2 * PI * $Radius); 315 $Offset = 360; 316 317 $ID = count($Values)-1; 318 319 $Values = array_reverse($Values); 320 $Slice = 0; $Slices = ""; $SliceColors = ""; $Visible = ""; $SliceAngle = ""; 321 foreach($Values as $Key => $Value) 322 { 323 324 $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]); 325 $SliceColors[$Slice] = $Settings; 326 327 $StartAngle = $Offset; 328 $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; } 329 330 if ( $StartAngle > 180 ) { $Visible[$Slice]["Start"] = TRUE; } else { $Visible[$Slice]["Start"] = TRUE; } 331 if ( $EndAngle < 180 ) { $Visible[$Slice]["End"] = FALSE; } else { $Visible[$Slice]["End"] = TRUE; } 332 333 if ($DataGapAngle == 0) 334 { $X0 = $X; $Y0 = $Y; } 335 else 336 { 337 $Angle = ($EndAngle - $Offset)/2 + $Offset; 338 $X0 = cos(($Angle-90)*PI/180) * $DataGapRadius + $X; 339 $Y0 = sin(($Angle-90)*PI/180) * $DataGapRadius*$SkewFactor + $Y; 340 } 341 $Slices[$Slice][] = $X0; $Slices[$Slice][] = $Y0; $SliceAngle[$Slice][] = 0; 342 343 for($i=$Offset;$i>=$EndAngle;$i=$i-$Step) 344 { 345 $Xc = cos(($i-90)*PI/180) * $Radius + $X; 346 $Yc = sin(($i-90)*PI/180) * $Radius*$SkewFactor + $Y; 347 348 if ( ($SecondPass || $RestoreShadow ) && ( $i<90 )) { $Yc++; } 349 if ( ($SecondPass || $RestoreShadow ) && ( $i>90 && $i<180 )) { $Xc++; } 350 if ( ($SecondPass || $RestoreShadow ) && ( $i>180 && $i<270 )) { $Xc++; } 351 if ( ($SecondPass || $RestoreShadow ) && ( $i>=270 )) { $Xc++; $Yc++; } 352 353 $Slices[$Slice][] = $Xc; $Slices[$Slice][] = $Yc; $SliceAngle[$Slice][] = $i; 354 } 355 356 $Offset = $i - $DataGapAngle; $ID--; $Slice++; 357 } 358 359 /* Draw the bottom shadow if needed */ 360 if ( $RestoreShadow && ($this->pChartObject->ShadowX != 0 || $this->pChartObject->ShadowY !=0 )) 361 { 362 foreach($Slices as $SliceID => $Plots) 363 { 364 $ShadowPie = ""; 365 for($i=0;$i<count($Plots);$i=$i+2) 366 { $ShadowPie[] = $Plots[$i]+$this->pChartObject->ShadowX; $ShadowPie[] = $Plots[$i+1]+$this->pChartObject->ShadowY; } 367 368 $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa,"NoBorder"=>TRUE); 369 $this->pChartObject->drawPolygon($ShadowPie,$Settings); 370 } 371 372 $Step = 360 / (2 * PI * $Radius); 373 $Offset = 360; 374 foreach($Values as $Key => $Value) 375 { 376 $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; } 377 378 for($i=$Offset;$i>=$EndAngle;$i=$i-$Step) 379 { 380 $Xc = cos(($i-90)*PI/180) * $Radius + $X + $this->pChartObject->ShadowX; 381 $Yc = sin(($i-90)*PI/180) * $Radius*$SkewFactor + $Y + $this->pChartObject->ShadowY; 382 383 $this->pChartObject->drawAntialiasPixel($Xc,$Yc,$Settings); 384 } 385 386 $Offset = $i - $DataGapAngle; $ID--; 387 } 388 } 389 390 /* Draw the bottom pie splice */ 391 foreach($Slices as $SliceID => $Plots) 392 { 393 $Settings = $SliceColors[$SliceID]; $Settings["NoBorder"] = TRUE; 394 $this->pChartObject->drawPolygon($Plots,$Settings); 395 396 if ( $SecondPass ) 397 { 398 $Settings = $SliceColors[$SliceID]; 399 if ( $Border ) 400 { $Settings["R"]+= 30; $Settings["G"]+= 30; $Settings["B"]+= 30;; } 401 402 $Angle = $SliceAngle[$SliceID][1]; 403 $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; 404 $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y; 405 $this->pChartObject->drawLine($Plots[0],$Plots[1],$Xc,$Yc,$Settings); 406 407 $Angle = $SliceAngle[$SliceID][count($SliceAngle[$SliceID])-1]; 408 $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; 409 $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y; 410 $this->pChartObject->drawLine($Plots[0],$Plots[1],$Xc,$Yc,$Settings); 411 } 412 } 413 414 /* Draw the two vertical edges */ 415 $Slices = array_reverse($Slices); 416 $SliceColors = array_reverse($SliceColors); 417 foreach($Slices as $SliceID => $Plots) 418 { 419 $Settings = $SliceColors[$SliceID]; 420 $Settings["R"]+= 10; $Settings["G"]+= 10; $Settings["B"]+= 10; $Settings["NoBorder"] = TRUE; 421 422 if ( $Visible[$SliceID]["Start"] ) 423 { 424 $this->pChartObject->drawLine($Plots[2],$Plots[3],$Plots[2],$Plots[3]- $SliceHeight,array("R"=>255,"G"=>255,"B"=>255)); 425 $Border = ""; 426 $Border[] = $Plots[0]; $Border[] = $Plots[1]; $Border[] = $Plots[0]; $Border[] = $Plots[1] - $SliceHeight; 427 $Border[] = $Plots[2]; $Border[] = $Plots[3] - $SliceHeight; $Border[] = $Plots[2]; $Border[] = $Plots[3]; 428 $this->pChartObject->drawPolygon($Border,$Settings); 429 } 430 } 431 432 $Slices = array_reverse($Slices); 433 $SliceColors = array_reverse($SliceColors); 434 foreach($Slices as $SliceID => $Plots) 435 { 436 $Settings = $SliceColors[$SliceID]; 437 $Settings["R"]+= 10; $Settings["G"]+= 10; $Settings["B"]+= 10; $Settings["NoBorder"] = TRUE; 438 if ( $Visible[$SliceID]["End"] ) 439 { 440 $this->pChartObject->drawLine($Plots[count($Plots)-2],$Plots[count($Plots)-1],$Plots[count($Plots)-2],$Plots[count($Plots)-1]- $SliceHeight,array("R"=>255,"G"=>255,"B"=>255)); 441 442 $Border = ""; 443 $Border[] = $Plots[0]; $Border[] = $Plots[1]; $Border[] = $Plots[0]; $Border[] = $Plots[1] - $SliceHeight; 444 $Border[] = $Plots[count($Plots)-2]; $Border[] = $Plots[count($Plots)-1] - $SliceHeight; $Border[] = $Plots[count($Plots)-2]; $Border[] = $Plots[count($Plots)-1]; 445 $this->pChartObject->drawPolygon($Border,$Settings); 446 } 447 } 448 449 /* Draw the rounded edges */ 450 foreach($Slices as $SliceID => $Plots) 451 { 452 $Settings = $SliceColors[$SliceID]; 453 $Settings["R"]+= 10; $Settings["G"]+= 10; $Settings["B"]+= 10; $Settings["NoBorder"] = TRUE; 454 455 for ($j=2;$j<count($Plots)-2;$j=$j+2) 456 { 457 $Angle = $SliceAngle[$SliceID][$j/2]; 458 if ( $Angle < 270 && $Angle > 90 ) 459 { 460 $Border = ""; 461 $Border[] = $Plots[$j]; $Border[] = $Plots[$j+1]; 462 $Border[] = $Plots[$j+2]; $Border[] = $Plots[$j+3]; 463 $Border[] = $Plots[$j+2]; $Border[] = $Plots[$j+3] - $SliceHeight; 464 $Border[] = $Plots[$j]; $Border[] = $Plots[$j+1] - $SliceHeight; 465 $this->pChartObject->drawPolygon($Border,$Settings); 466 } 467 } 468 469 if ( $SecondPass ) 470 { 471 $Settings = $SliceColors[$SliceID]; 472 if ( $Border ) 473 { $Settings["R"]+= 30; $Settings["G"]+= 30; $Settings["B"]+= 30; } 474 475 $Angle = $SliceAngle[$SliceID][1]; 476 if ( $Angle < 270 && $Angle > 90 ) 477 { 478 $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; 479 $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y; 480 $this->pChartObject->drawLine($Xc,$Yc,$Xc,$Yc-$SliceHeight,$Settings); 481 } 482 483 $Angle = $SliceAngle[$SliceID][count($SliceAngle[$SliceID])-1]; 484 if ( $Angle < 270 && $Angle > 90 ) 485 { 486 $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; 487 $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y; 488 $this->pChartObject->drawLine($Xc,$Yc,$Xc,$Yc-$SliceHeight,$Settings); 489 } 490 491 if ( $SliceAngle[$SliceID][1] > 270 && $SliceAngle[$SliceID][count($SliceAngle[$SliceID])-1] < 270 ) 492 { 493 $Xc = cos((270-90)*PI/180) * $Radius + $X; 494 $Yc = sin((270-90)*PI/180) * $Radius*$SkewFactor + $Y; 495 $this->pChartObject->drawLine($Xc,$Yc,$Xc,$Yc-$SliceHeight,$Settings); 496 } 497 498 if ( $SliceAngle[$SliceID][1] > 90 && $SliceAngle[$SliceID][count($SliceAngle[$SliceID])-1] < 90 ) 499 { 500 $Xc = cos((0)*PI/180) * $Radius + $X; 501 $Yc = sin((0)*PI/180) * $Radius*$SkewFactor + $Y; 502 $this->pChartObject->drawLine($Xc,$Yc,$Xc,$Yc-$SliceHeight,$Settings); 503 } 504 505 } 506 } 507 508 /* Draw the top splice */ 509 foreach($Slices as $SliceID => $Plots) 510 { 511 $Settings = $SliceColors[$SliceID]; 512 $Settings["R"]+= 20; $Settings["G"]+= 20; $Settings["B"]+= 20; 513 514 $Top = ""; 515 for($j=0;$j<count($Plots);$j=$j+2) { $Top[] = $Plots[$j]; $Top[] = $Plots[$j+1]- $SliceHeight; } 516 $this->pChartObject->drawPolygon($Top,$Settings); 517 } 518 519 520 /* Second pass to smooth the angles */ 521 if ( $SecondPass ) 522 { 523 $Step = 360 / (2 * PI * $Radius); 524 $Offset = 360; 525 $ID = count($Values)-1; 526 foreach($Values as $Key => $Value) 527 { 528 $FirstPoint = TRUE; 529 if ( $Shadow ) 530 $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa); 531 else 532 { 533 if ( $Border ) 534 { 535 $Settings = array( 536 "R" => $Palette[$ID]["R"] + 30, 537 "G" => $Palette[$ID]["G"] + 30, 538 "B" => $Palette[$ID]["B"] + 30, 539 "Alpha" => $Palette[$ID]["Alpha"]); 540 } 541 else 542 $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]); 543 } 544 545 $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; } 546 547 if ($DataGapAngle == 0) 548 { $X0 = $X; $Y0 = $Y- $SliceHeight; } 549 else 550 { 551 $Angle = ($EndAngle - $Offset)/2 + $Offset; 552 $X0 = cos(($Angle-90)*PI/180) * $DataGapRadius + $X; 553 $Y0 = sin(($Angle-90)*PI/180) * $DataGapRadius*$SkewFactor + $Y - $SliceHeight; 554 } 555 $Plots[] = $X0; $Plots[] = $Y0; 556 557 for ($i=$Offset;$i>=$EndAngle;$i=$i-$Step) 558 { 559 $Xc = cos(($i-90)*PI/180) * $Radius + $X; 560 $Yc = sin(($i-90)*PI/180) * $Radius*$SkewFactor + $Y - $SliceHeight; 561 562 if ( $FirstPoint ) 563 { $this->pChartObject->drawLine($Xc,$Yc,$X0,$Y0,$Settings); } 564 else 565 { $FirstPoint = FALSE; } 566 567 $this->pChartObject->drawAntialiasPixel($Xc,$Yc,$Settings); 568 if ($i < 270 && $i > 90 ) 569 { $this->pChartObject->drawAntialiasPixel($Xc,$Yc+$SliceHeight,$Settings); } 570 } 571 $this->pChartObject->drawLine($Xc,$Yc,$X0,$Y0,$Settings); 572 573 $Offset = $i - $DataGapAngle; $ID--; 574 } 575 } 576 577 if ( $WriteValues != NULL ) 578 { 579 $Step = 360 / (2 * PI * $Radius); 580 $Offset = 360; $ID = count($Values)-1; 581 $Settings = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"R"=>$ValueR,"G"=>$ValueG,"B"=>$ValueB,"Alpha"=>$ValueAlpha); 582 foreach($Values as $Key => $Value) 583 { 584 $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; } 585 586 $Angle = ($EndAngle - $Offset)/2 + $Offset; 587 $Xc = cos(($Angle-90)*PI/180) * ($Radius)/2 + $X; 588 $Yc = sin(($Angle-90)*PI/180) * ($Radius*$SkewFactor)/2 + $Y - $SliceHeight; 589 590 if ( $WriteValues == PIE_VALUE_PERCENTAGE ) 591 $Display = round(( 100 / $SerieSum ) * $Value)."%"; 592 elseif ( $WriteValues == PIE_VALUE_NATURAL ) 593 $Display = $Value.$ValueSuffix; 594 595 $this->pChartObject->drawText($Xc,$Yc,$Display,$Settings); 596 597 $Offset = $EndAngle - $DataGapAngle; $ID--; 598 } 599 } 600 601 if ( $DrawLabels ) 602 { 603 $Step = 360 / (2 * PI * $Radius); 604 $Offset = 360; $ID = count($Values)-1; 605 foreach($Values as $Key => $Value) 606 { 607 if ( $LabelColor == PIE_LABEL_COLOR_AUTO ) 608 { $Settings = array("FillR"=>$Palette[$ID]["R"],"FillG"=>$Palette[$ID]["G"],"FillB"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);} 609 else 610 { $Settings = array("FillR"=>$LabelR,"FillG"=>$LabelG,"FillB"=>$LabelB,"Alpha"=>$LabelAlpha); } 611 612 $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; } 613 614 $Angle = ($EndAngle - $Offset)/2 + $Offset; 615 $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; 616 $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y - $SliceHeight; 617 618 if ( isset($Data["Series"][$Data["Abscissa"]]["Data"][$ID]) ) 619 { 620 $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$ID]; 621 622 $Settings["Angle"] = 360-$Angle; 623 $Settings["Length"] = 25; 624 $Settings["Size"] = 8; 625 $this->pChartObject->drawArrowLabel($Xc,$Yc," ".$Label." ",$Settings); 626 } 627 628 $Offset = $EndAngle - $DataGapAngle; $ID--; 629 } 630 } 631 632 $this->pChartObject->Shadow = $RestoreShadow; 633 634 return(PIE_RENDERED); 635 } 636 637 /* Draw the legend of pie chart */ 638 function drawPieLegend($X,$Y,$Format="") 639 { 640 $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName; 641 $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize; 642 $FontR = isset($Format["FontR"]) ? $Format["FontR"] : $this->pChartObject->FontColorR; 643 $FontG = isset($Format["FontG"]) ? $Format["FontG"] : $this->pChartObject->FontColorG; 644 $FontB = isset($Format["FontB"]) ? $Format["FontB"] : $this->pChartObject->FontColorB; 645 $BoxSize = isset($Format["BoxSize"]) ? $Format["BoxSize"] : 5; 646 $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5; 647 $R = isset($Format["R"]) ? $Format["R"] : 200; 648 $G = isset($Format["G"]) ? $Format["G"] : 200; 649 $B = isset($Format["B"]) ? $Format["B"] : 200; 650 $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; 651 $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255; 652 $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255; 653 $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255; 654 $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; 655 $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND; 656 $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL; 657 658 if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; } 659 660 $YStep = max($this->pChartObject->FontSize,$BoxSize) + 5; 661 $XStep = $BoxSize + 5; 662 663 /* Data Processing */ 664 $Data = $this->pDataObject->getData(); 665 $Palette = $this->pDataObject->getPalette(); 666 667 /* Do we have an abscissa serie defined? */ 668 if ( $Data["Abscissa"] == "" ) { return(PIE_NO_ABSCISSA); } 669 670 $Boundaries = ""; $Boundaries["L"] = $X; $Boundaries["T"] = $Y; $Boundaries["R"] = 0; $Boundaries["B"] = 0; $vY = $Y; $vX = $X; 671 foreach($Data["Series"][$Data["Abscissa"]]["Data"] as $Key => $Value) 672 { 673 $BoxArray = $this->pChartObject->getTextBox($vX+$BoxSize+4,$vY+$BoxSize/2,$FontName,$FontSize,0,$Value); 674 675 if ( $Mode == LEGEND_VERTICAL ) 676 { 677 if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$BoxSize/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$BoxSize/2; } 678 if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } 679 if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$BoxSize/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$BoxSize/2; } 680 $vY=$vY+$YStep; 681 } 682 elseif ( $Mode == LEGEND_HORIZONTAL ) 683 { 684 if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$BoxSize/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$BoxSize/2; } 685 if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } 686 if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$BoxSize/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$BoxSize/2; } 687 $vX=$Boundaries["R"]+$XStep; 688 } 689 } 690 $vY=$vY-$YStep; $vX=$vX-$XStep; 691 692 $TopOffset = $Y - $Boundaries["T"]; 693 if ( $Boundaries["B"]-($vY+$BoxSize) < $TopOffset ) { $Boundaries["B"] = $vY+$BoxSize+$TopOffset; } 694 695 if ( $Style == LEGEND_ROUND ) 696 $this->pChartObject->drawRoundedFilledRectangle($Boundaries["L"]-$Margin,$Boundaries["T"]-$Margin,$Boundaries["R"]+$Margin,$Boundaries["B"]+$Margin,$Margin,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); 697 elseif ( $Style == LEGEND_BOX ) 698 $this->pChartObject->drawFilledRectangle($Boundaries["L"]-$Margin,$Boundaries["T"]-$Margin,$Boundaries["R"]+$Margin,$Boundaries["B"]+$Margin,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); 699 700 $RestoreShadow = $this->pChartObject->Shadow; $this->pChartObject->Shadow = FALSE; 701 foreach($Data["Series"][$Data["Abscissa"]]["Data"] as $Key => $Value) 702 { 703 $R = $Palette[$Key]["R"]; $G = $Palette[$Key]["G"]; $B = $Palette[$Key]["B"]; 704 705 $this->pChartObject->drawFilledRectangle($X+1,$Y+1,$X+$BoxSize+1,$Y+$BoxSize+1,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20)); 706 $this->pChartObject->drawFilledRectangle($X,$Y,$X+$BoxSize,$Y+$BoxSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Surrounding"=>20)); 707 if ( $Mode == LEGEND_VERTICAL ) 708 { 709 $this->pChartObject->drawText($X+$BoxSize+4,$Y+$BoxSize/2,$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT)); 710 $Y=$Y+$YStep; 711 } 712 elseif ( $Mode == LEGEND_HORIZONTAL ) 713 { 714 $BoxArray = $this->pChartObject->drawText($X+$BoxSize+4,$Y+$BoxSize/2,$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT)); 715 $X=$BoxArray[1]["X"]+2+$XStep; 716 } 717 } 718 719 $this->Shadow = $RestoreShadow; 720 } 721 722 /* Set the color of the specified slice */ 723 function setSliceColor($SliceID,$Format="") 724 { 725 $R = isset($Format["R"]) ? $Format["R"] : 0; 726 $G = isset($Format["G"]) ? $Format["G"] : 0; 727 $B = isset($Format["B"]) ? $Format["B"] : 0; 728 $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; 729 730 $this->pDataObject->Palette[$SliceID]["R"] = $R; 731 $this->pDataObject->Palette[$SliceID]["G"] = $G; 732 $this->pDataObject->Palette[$SliceID]["B"] = $B; 733 $this->pDataObject->Palette[$SliceID]["Alpha"] = $Alpha; 734 } 735 } 736?> 737