PageRenderTime 57ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/protected/components/pPie.php

https://bitbucket.org/y_widyatama/ijepa2
PHP | 1500 lines | 1137 code | 266 blank | 97 comment | 354 complexity | 0917d4f5b386c55a580cda966730e5f9 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. pPie - class to draw pie charts
  4. Version : 2.1.3
  5. Made by : Jean-Damien POGOLOTTI
  6. Last Update : 09/09/11
  7. This file can be distributed under the license you can find at :
  8. http://www.pchart.net/license
  9. You can find the whole class documentation on the pChart web site.
  10. */
  11. /* Class return codes */
  12. define("PIE_NO_ABSCISSA" , 140001);
  13. define("PIE_NO_DATASERIE" , 140002);
  14. define("PIE_SUMISNULL" , 140003);
  15. define("PIE_RENDERED" , 140000);
  16. define("PIE_LABEL_COLOR_AUTO" , 140010);
  17. define("PIE_LABEL_COLOR_MANUAL", 140011);
  18. define("PIE_VALUE_NATURAL" , 140020);
  19. define("PIE_VALUE_PERCENTAGE" , 140021);
  20. define("PIE_VALUE_INSIDE" , 140030);
  21. define("PIE_VALUE_OUTSIDE" , 140031);
  22. /* pPie class definition */
  23. class pPie
  24. {
  25. var $pChartObject;
  26. var $pDataObject;
  27. var $LabelPos = "" ;
  28. /* Class creator */
  29. function pPie($Object,$pDataObject)
  30. {
  31. /* Cache the pChart object reference */
  32. $this->pChartObject = $Object;
  33. /* Cache the pData object reference */
  34. $this->pDataObject = $pDataObject;
  35. }
  36. /* Draw a pie chart */
  37. function draw2DPie($X,$Y,$Format="")
  38. {
  39. $Radius = isset($Format["Radius"]) ? $Format["Radius"] : 60;
  40. $Precision = isset($Format["Precision"]) ? $Format["Precision"] : 0;
  41. $DataGapAngle = isset($Format["DataGapAngle"]) ? $Format["DataGapAngle"] : 0;
  42. $DataGapRadius = isset($Format["DataGapRadius"]) ? $Format["DataGapRadius"] : 0;
  43. $SecondPass = isset($Format["SecondPass"]) ? $Format["SecondPass"] : TRUE;
  44. $Border = isset($Format["Border"]) ? $Format["Border"] : FALSE;
  45. $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255;
  46. $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255;
  47. $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255;
  48. $Shadow = isset($Format["Shadow"]) ? $Format["Shadow"] : FALSE;
  49. $DrawLabels = isset($Format["DrawLabels"]) ? $Format["DrawLabels"] : FALSE;
  50. $LabelStacked = isset($Format["LabelStacked"]) ? $Format["LabelStacked"] : FALSE;
  51. $LabelColor = isset($Format["LabelColor"]) ? $Format["LabelColor"] : PIE_LABEL_COLOR_MANUAL;
  52. $LabelR = isset($Format["LabelR"]) ? $Format["LabelR"] : 0;
  53. $LabelG = isset($Format["LabelG"]) ? $Format["LabelG"] : 0;
  54. $LabelB = isset($Format["LabelB"]) ? $Format["LabelB"] : 0;
  55. $LabelAlpha = isset($Format["LabelAlpha"]) ? $Format["LabelAlpha"] : 100;
  56. $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : NULL;
  57. $ValuePosition = isset($Format["ValuePosition"]) ? $Format["ValuePosition"] : PIE_VALUE_OUTSIDE;
  58. $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 15;
  59. $ValueSuffix = isset($Format["ValueSuffix"]) ? $Format["ValueSuffix"] : "";
  60. $ValueR = isset($Format["ValueR"]) ? $Format["ValueR"] : 255;
  61. $ValueG = isset($Format["ValueG"]) ? $Format["ValueG"] : 255;
  62. $ValueB = isset($Format["ValueB"]) ? $Format["ValueB"] : 255;
  63. $ValueAlpha = isset($Format["ValueAlpha"]) ? $Format["ValueAlpha"] : 100;
  64. $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE;
  65. /* Data Processing */
  66. $Data = $this->pDataObject->getData();
  67. $Palette = $this->pDataObject->getPalette();
  68. /* Do we have an abscissa serie defined? */
  69. if ( $Data["Abscissa"] == "" ) { return(PIE_NO_ABSCISSA); }
  70. /* Try to find the data serie */
  71. $DataSerie = "";
  72. foreach ($Data["Series"] as $SerieName => $SerieData)
  73. { if ( $SerieName != $Data["Abscissa"]) { $DataSerie = $SerieName; } }
  74. /* Do we have data to compute? */
  75. if ( $DataSerie == "" ) { return(PIE_NO_DATASERIE); }
  76. /* Remove unused data */
  77. list($Data,$Palette) = $this->clean0Values($Data,$Palette,$DataSerie,$Data["Abscissa"]);
  78. /* Compute the pie sum */
  79. $SerieSum = $this->pDataObject->getSum($DataSerie);
  80. /* Do we have data to draw? */
  81. if ( $SerieSum == 0 ) { return(PIE_SUMISNULL); }
  82. /* Dump the real number of data to draw */
  83. $Values = "";
  84. foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value)
  85. { if ($Value != 0) { $Values[] = $Value; } }
  86. /* Compute the wasted angular space between series */
  87. if (count($Values)==1) { $WastedAngular = 0; } else { $WastedAngular = count($Values) * $DataGapAngle; }
  88. /* Compute the scale */
  89. $ScaleFactor = (360 - $WastedAngular) / $SerieSum;
  90. $RestoreShadow = $this->pChartObject->Shadow;
  91. if ( $this->pChartObject->Shadow )
  92. {
  93. $this->pChartObject->Shadow = FALSE;
  94. $ShadowFormat = $Format; $ShadowFormat["Shadow"] = TRUE;
  95. $this->draw2DPie($X+$this->pChartObject->ShadowX,$Y+$this->pChartObject->ShadowY,$ShadowFormat);
  96. }
  97. /* Draw the polygon pie elements */
  98. $Step = 360 / (2 * PI * $Radius);
  99. $Offset = 0; $ID = 0;
  100. foreach($Values as $Key => $Value)
  101. {
  102. if ( $Shadow )
  103. $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa);
  104. else
  105. {
  106. if ( !isset($Palette[$ID]["R"]) ) { $Color = $this->pChartObject->getRandomColor(); $Palette[$ID] = $Color; $this->pDataObject->savePalette($ID,$Color); }
  107. $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);
  108. }
  109. if ( !$SecondPass && !$Shadow )
  110. {
  111. if ( !$Border )
  112. $Settings["Surrounding"] = 10;
  113. else
  114. { $Settings["BorderR"] = $BorderR; $Settings["BorderG"] = $BorderG; $Settings["BorderB"] = $BorderB; }
  115. }
  116. $Plots = "";
  117. $EndAngle = $Offset+($Value*$ScaleFactor); if ( $EndAngle > 360 ) { $EndAngle = 360; }
  118. $Angle = ($EndAngle - $Offset)/2 + $Offset;
  119. if ($DataGapAngle == 0)
  120. { $X0 = $X; $Y0 = $Y; }
  121. else
  122. {
  123. $X0 = cos(($Angle-90)*PI/180) * $DataGapRadius + $X;
  124. $Y0 = sin(($Angle-90)*PI/180) * $DataGapRadius + $Y;
  125. }
  126. $Plots[] = $X0; $Plots[] = $Y0;
  127. for($i=$Offset;$i<=$EndAngle;$i=$i+$Step)
  128. {
  129. $Xc = cos(($i-90)*PI/180) * $Radius + $X;
  130. $Yc = sin(($i-90)*PI/180) * $Radius + $Y;
  131. if ( $SecondPass && ( $i<90 )) { $Yc++; }
  132. if ( $SecondPass && ( $i>180 && $i<270 )) { $Xc++; }
  133. if ( $SecondPass && ( $i>=270 )) { $Xc++; $Yc++; }
  134. $Plots[] = $Xc; $Plots[] = $Yc;
  135. }
  136. $this->pChartObject->drawPolygon($Plots,$Settings);
  137. if ( $RecordImageMap && !$Shadow ) { $this->pChartObject->addToImageMap("POLY",$this->arraySerialize($Plots),$this->pChartObject->toHTMLColor($Palette[$ID]["R"],$Palette[$ID]["G"],$Palette[$ID]["B"]),$Data["Series"][$Data["Abscissa"]]["Data"][$Key],$Value); }
  138. if ( $DrawLabels && !$Shadow && !$SecondPass )
  139. {
  140. if ( $LabelColor == PIE_LABEL_COLOR_AUTO )
  141. { $Settings = array("FillR"=>$Palette[$ID]["R"],"FillG"=>$Palette[$ID]["G"],"FillB"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);}
  142. else
  143. { $Settings = array("FillR"=>$LabelR,"FillG"=>$LabelG,"FillB"=>$LabelB,"Alpha"=>$LabelAlpha); }
  144. $Angle = ($EndAngle - $Offset)/2 + $Offset;
  145. $Xc = cos(($Angle-90)*PI/180) * $Radius + $X;
  146. $Yc = sin(($Angle-90)*PI/180) * $Radius + $Y;
  147. $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$Key];
  148. if ( $LabelStacked )
  149. $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,TRUE,$X,$Y,$Radius);
  150. else
  151. $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,FALSE);
  152. }
  153. $Offset = $i + $DataGapAngle; $ID++;
  154. }
  155. /* Second pass to smooth the angles */
  156. if ( $SecondPass )
  157. {
  158. $Step = 360 / (2 * PI * $Radius);
  159. $Offset = 0; $ID = 0;
  160. foreach($Values as $Key => $Value)
  161. {
  162. $FirstPoint = TRUE;
  163. if ( $Shadow )
  164. $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa);
  165. else
  166. {
  167. if ( $Border )
  168. $Settings = array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB);
  169. else
  170. $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);
  171. }
  172. $EndAngle = $Offset+($Value*$ScaleFactor); if ( $EndAngle > 360 ) { $EndAngle = 360; }
  173. if ($DataGapAngle == 0)
  174. { $X0 = $X; $Y0 = $Y; }
  175. else
  176. {
  177. $Angle = ($EndAngle - $Offset)/2 + $Offset;
  178. $X0 = cos(($Angle-90)*PI/180) * $DataGapRadius + $X;
  179. $Y0 = sin(($Angle-90)*PI/180) * $DataGapRadius + $Y;
  180. }
  181. $Plots[] = $X0; $Plots[] = $Y0;
  182. for($i=$Offset;$i<=$EndAngle;$i=$i+$Step)
  183. {
  184. $Xc = cos(($i-90)*PI/180) * $Radius + $X;
  185. $Yc = sin(($i-90)*PI/180) * $Radius + $Y;
  186. if ( $FirstPoint ) { $this->pChartObject->drawLine($Xc,$Yc,$X0,$Y0,$Settings); } { $FirstPoint = FALSE; }
  187. $this->pChartObject->drawAntialiasPixel($Xc,$Yc,$Settings);
  188. }
  189. $this->pChartObject->drawLine($Xc,$Yc,$X0,$Y0,$Settings);
  190. if ( $DrawLabels && !$Shadow )
  191. {
  192. if ( $LabelColor == PIE_LABEL_COLOR_AUTO )
  193. { $Settings = array("FillR"=>$Palette[$ID]["R"],"FillG"=>$Palette[$ID]["G"],"FillB"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);}
  194. else
  195. { $Settings = array("FillR"=>$LabelR,"FillG"=>$LabelG,"FillB"=>$LabelB,"Alpha"=>$LabelAlpha); }
  196. $Angle = ($EndAngle - $Offset)/2 + $Offset;
  197. $Xc = cos(($Angle-90)*PI/180) * $Radius + $X;
  198. $Yc = sin(($Angle-90)*PI/180) * $Radius + $Y;
  199. $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$Key];
  200. if ( $LabelStacked )
  201. $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,TRUE,$X,$Y,$Radius);
  202. else
  203. $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,FALSE);
  204. }
  205. $Offset = $i + $DataGapAngle; $ID++;
  206. }
  207. }
  208. if ( $WriteValues != NULL && !$Shadow )
  209. {
  210. $Step = 360 / (2 * PI * $Radius);
  211. $Offset = 0; $ID = count($Values)-1;
  212. $Settings = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"R"=>$ValueR,"G"=>$ValueG,"B"=>$ValueB,"Alpha"=>$ValueAlpha);
  213. foreach($Values as $Key => $Value)
  214. {
  215. $EndAngle = ($Value*$ScaleFactor) + $Offset; if ( $EndAngle > 360 ) { $EndAngle = 0; }
  216. $Angle = ($EndAngle - $Offset)/2 + $Offset;
  217. if ( $ValuePosition == PIE_VALUE_OUTSIDE )
  218. {
  219. $Xc = cos(($Angle-90)*PI/180) * ($Radius+$ValuePadding) + $X;
  220. $Yc = sin(($Angle-90)*PI/180) * ($Radius+$ValuePadding) + $Y;
  221. }
  222. else
  223. {
  224. $Xc = cos(($Angle-90)*PI/180) * ($Radius)/2 + $X;
  225. $Yc = sin(($Angle-90)*PI/180) * ($Radius)/2 + $Y;
  226. }
  227. if ( $WriteValues == PIE_VALUE_PERCENTAGE )
  228. $Display = round(( 100 / $SerieSum ) * $Value,$Precision)."%";
  229. elseif ( $WriteValues == PIE_VALUE_NATURAL )
  230. $Display = $Value.$ValueSuffix;
  231. $this->pChartObject->drawText($Xc,$Yc,$Display,$Settings);
  232. $Offset = $EndAngle + $DataGapAngle; $ID--;
  233. }
  234. }
  235. if ( $DrawLabels && $LabelStacked ) { $this->writeShiftedLabels(); }
  236. $this->pChartObject->Shadow = $RestoreShadow;
  237. return(PIE_RENDERED);
  238. }
  239. /* Draw a 3D pie chart */
  240. function draw3DPie($X,$Y,$Format="")
  241. {
  242. /* Rendering layout */
  243. $Radius = isset($Format["Radius"]) ? $Format["Radius"] : 80;
  244. $Precision = isset($Format["Precision"]) ? $Format["Precision"] : 0;
  245. $SkewFactor = isset($Format["SkewFactor"]) ? $Format["SkewFactor"] : .5;
  246. $SliceHeight = isset($Format["SliceHeight"]) ? $Format["SliceHeight"] : 20;
  247. $DataGapAngle = isset($Format["DataGapAngle"]) ? $Format["DataGapAngle"] : 0;
  248. $DataGapRadius = isset($Format["DataGapRadius"]) ? $Format["DataGapRadius"] : 0;
  249. $SecondPass = isset($Format["SecondPass"]) ? $Format["SecondPass"] : TRUE;
  250. $Border = isset($Format["Border"]) ? $Format["Border"] : FALSE;
  251. $Shadow = isset($Format["Shadow"]) ? $Format["Shadow"] : FALSE;
  252. $DrawLabels = isset($Format["DrawLabels"]) ? $Format["DrawLabels"] : FALSE;
  253. $LabelStacked = isset($Format["LabelStacked"]) ? $Format["LabelStacked"] : FALSE;
  254. $LabelColor = isset($Format["LabelColor"]) ? $Format["LabelColor"] : PIE_LABEL_COLOR_MANUAL;
  255. $LabelR = isset($Format["LabelR"]) ? $Format["LabelR"] : 0;
  256. $LabelG = isset($Format["LabelG"]) ? $Format["LabelG"] : 0;
  257. $LabelB = isset($Format["LabelB"]) ? $Format["LabelB"] : 0;
  258. $LabelAlpha = isset($Format["LabelAlpha"]) ? $Format["LabelAlpha"] : 100;
  259. $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : NULL; //PIE_VALUE_PERCENTAGE
  260. $ValuePosition = isset($Format["ValuePosition"]) ? $Format["ValuePosition"] : PIE_VALUE_INSIDE;
  261. $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 15;
  262. $ValueSuffix = isset($Format["ValueSuffix"]) ? $Format["ValueSuffix"] : "";
  263. $ValueR = isset($Format["ValueR"]) ? $Format["ValueR"] : 255;
  264. $ValueG = isset($Format["ValueG"]) ? $Format["ValueG"] : 255;
  265. $ValueB = isset($Format["ValueB"]) ? $Format["ValueB"] : 255;
  266. $ValueAlpha = isset($Format["ValueAlpha"]) ? $Format["ValueAlpha"] : 100;
  267. $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE;
  268. /* Error correction for overlaying rounded corners */
  269. if ( $SkewFactor < .5 ) { $SkewFactor = .5; }
  270. /* Data Processing */
  271. $Data = $this->pDataObject->getData();
  272. $Palette = $this->pDataObject->getPalette();
  273. /* Do we have an abscissa serie defined? */
  274. if ( $Data["Abscissa"] == "" ) { return(PIE_NO_ABSCISSA); }
  275. /* Try to find the data serie */
  276. $DataSerie = "";
  277. foreach ($Data["Series"] as $SerieName => $SerieData)
  278. { if ( $SerieName != $Data["Abscissa"]) { $DataSerie = $SerieName; } }
  279. /* Do we have data to compute? */
  280. if ( $DataSerie == "" ) { return(PIE_NO_DATASERIE); }
  281. /* Remove unused data */
  282. list($Data,$Palette) = $this->clean0Values($Data,$Palette,$DataSerie,$Data["Abscissa"]);
  283. /* Compute the pie sum */
  284. $SerieSum = $this->pDataObject->getSum($DataSerie);
  285. /* Do we have data to draw? */
  286. if ( $SerieSum == 0 ) { return(PIE_SUMISNULL); }
  287. /* Dump the real number of data to draw */
  288. $Values = "";
  289. foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value)
  290. { if ($Value != 0) { $Values[] = $Value; } }
  291. /* Compute the wasted angular space between series */
  292. if (count($Values)==1) { $WastedAngular = 0; } else { $WastedAngular = count($Values) * $DataGapAngle; }
  293. /* Compute the scale */
  294. $ScaleFactor = (360 - $WastedAngular) / $SerieSum;
  295. $RestoreShadow = $this->pChartObject->Shadow;
  296. if ( $this->pChartObject->Shadow ) { $this->pChartObject->Shadow = FALSE; }
  297. /* Draw the polygon pie elements */
  298. $Step = 360 / (2 * PI * $Radius);
  299. $Offset = 360; $ID = count($Values)-1;
  300. $Values = array_reverse($Values);
  301. $Slice = 0; $Slices = ""; $SliceColors = ""; $Visible = ""; $SliceAngle = "";
  302. foreach($Values as $Key => $Value)
  303. {
  304. if ( !isset($Palette[$ID]["R"]) ) { $Color = $this->pChartObject->getRandomColor(); $Palette[$ID] = $Color; $this->pDataObject->savePalette($ID,$Color); }
  305. $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);
  306. $SliceColors[$Slice] = $Settings;
  307. $StartAngle = $Offset;
  308. $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; }
  309. if ( $StartAngle > 180 ) { $Visible[$Slice]["Start"] = TRUE; } else { $Visible[$Slice]["Start"] = TRUE; }
  310. if ( $EndAngle < 180 ) { $Visible[$Slice]["End"] = FALSE; } else { $Visible[$Slice]["End"] = TRUE; }
  311. if ($DataGapAngle == 0)
  312. { $X0 = $X; $Y0 = $Y; }
  313. else
  314. {
  315. $Angle = ($EndAngle - $Offset)/2 + $Offset;
  316. $X0 = cos(($Angle-90)*PI/180) * $DataGapRadius + $X;
  317. $Y0 = sin(($Angle-90)*PI/180) * $DataGapRadius*$SkewFactor + $Y;
  318. }
  319. $Slices[$Slice][] = $X0; $Slices[$Slice][] = $Y0; $SliceAngle[$Slice][] = 0;
  320. for($i=$Offset;$i>=$EndAngle;$i=$i-$Step)
  321. {
  322. $Xc = cos(($i-90)*PI/180) * $Radius + $X;
  323. $Yc = sin(($i-90)*PI/180) * $Radius*$SkewFactor + $Y;
  324. if ( ($SecondPass || $RestoreShadow ) && ( $i<90 )) { $Yc++; }
  325. if ( ($SecondPass || $RestoreShadow ) && ( $i>90 && $i<180 )) { $Xc++; }
  326. if ( ($SecondPass || $RestoreShadow ) && ( $i>180 && $i<270 )) { $Xc++; }
  327. if ( ($SecondPass || $RestoreShadow ) && ( $i>=270 )) { $Xc++; $Yc++; }
  328. $Slices[$Slice][] = $Xc; $Slices[$Slice][] = $Yc; $SliceAngle[$Slice][] = $i;
  329. }
  330. $Offset = $i - $DataGapAngle; $ID--; $Slice++;
  331. }
  332. /* Draw the bottom shadow if needed */
  333. if ( $RestoreShadow && ($this->pChartObject->ShadowX != 0 || $this->pChartObject->ShadowY !=0 ))
  334. {
  335. foreach($Slices as $SliceID => $Plots)
  336. {
  337. $ShadowPie = "";
  338. for($i=0;$i<count($Plots);$i=$i+2)
  339. { $ShadowPie[] = $Plots[$i]+$this->pChartObject->ShadowX; $ShadowPie[] = $Plots[$i+1]+$this->pChartObject->ShadowY; }
  340. $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa,"NoBorder"=>TRUE);
  341. $this->pChartObject->drawPolygon($ShadowPie,$Settings);
  342. }
  343. $Step = 360 / (2 * PI * $Radius);
  344. $Offset = 360;
  345. foreach($Values as $Key => $Value)
  346. {
  347. $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; }
  348. for($i=$Offset;$i>=$EndAngle;$i=$i-$Step)
  349. {
  350. $Xc = cos(($i-90)*PI/180) * $Radius + $X + $this->pChartObject->ShadowX;
  351. $Yc = sin(($i-90)*PI/180) * $Radius*$SkewFactor + $Y + $this->pChartObject->ShadowY;
  352. $this->pChartObject->drawAntialiasPixel($Xc,$Yc,$Settings);
  353. }
  354. $Offset = $i - $DataGapAngle; $ID--;
  355. }
  356. }
  357. /* Draw the bottom pie splice */
  358. foreach($Slices as $SliceID => $Plots)
  359. {
  360. $Settings = $SliceColors[$SliceID]; $Settings["NoBorder"] = TRUE;
  361. $this->pChartObject->drawPolygon($Plots,$Settings);
  362. if ( $SecondPass )
  363. {
  364. $Settings = $SliceColors[$SliceID];
  365. if ( $Border )
  366. { $Settings["R"]+= 30; $Settings["G"]+= 30; $Settings["B"]+= 30;; }
  367. if ( isset($SliceAngle[$SliceID][1]) ) /* Empty error handling */
  368. {
  369. $Angle = $SliceAngle[$SliceID][1];
  370. $Xc = cos(($Angle-90)*PI/180) * $Radius + $X;
  371. $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y;
  372. $this->pChartObject->drawLine($Plots[0],$Plots[1],$Xc,$Yc,$Settings);
  373. $Angle = $SliceAngle[$SliceID][count($SliceAngle[$SliceID])-1];
  374. $Xc = cos(($Angle-90)*PI/180) * $Radius + $X;
  375. $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y;
  376. $this->pChartObject->drawLine($Plots[0],$Plots[1],$Xc,$Yc,$Settings);
  377. }
  378. }
  379. }
  380. /* Draw the two vertical edges */
  381. $Slices = array_reverse($Slices);
  382. $SliceColors = array_reverse($SliceColors);
  383. foreach($Slices as $SliceID => $Plots)
  384. {
  385. $Settings = $SliceColors[$SliceID];
  386. $Settings["R"]+= 10; $Settings["G"]+= 10; $Settings["B"]+= 10; $Settings["NoBorder"] = TRUE;
  387. if ( $Visible[$SliceID]["Start"] && isset($Plots[2])) /* Empty error handling */
  388. {
  389. $this->pChartObject->drawLine($Plots[2],$Plots[3],$Plots[2],$Plots[3]- $SliceHeight,array("R"=>$Settings["R"],"G"=>$Settings["G"],"B"=>$Settings["B"]));
  390. $Border = "";
  391. $Border[] = $Plots[0]; $Border[] = $Plots[1]; $Border[] = $Plots[0]; $Border[] = $Plots[1] - $SliceHeight;
  392. $Border[] = $Plots[2]; $Border[] = $Plots[3] - $SliceHeight; $Border[] = $Plots[2]; $Border[] = $Plots[3];
  393. $this->pChartObject->drawPolygon($Border,$Settings);
  394. }
  395. }
  396. $Slices = array_reverse($Slices);
  397. $SliceColors = array_reverse($SliceColors);
  398. foreach($Slices as $SliceID => $Plots)
  399. {
  400. $Settings = $SliceColors[$SliceID];
  401. $Settings["R"]+= 10; $Settings["G"]+= 10; $Settings["B"]+= 10; $Settings["NoBorder"] = TRUE;
  402. if ( $Visible[$SliceID]["End"] )
  403. {
  404. $this->pChartObject->drawLine($Plots[count($Plots)-2],$Plots[count($Plots)-1],$Plots[count($Plots)-2],$Plots[count($Plots)-1]- $SliceHeight,array("R"=>$Settings["R"],"G"=>$Settings["G"],"B"=>$Settings["B"]));
  405. $Border = "";
  406. $Border[] = $Plots[0]; $Border[] = $Plots[1]; $Border[] = $Plots[0]; $Border[] = $Plots[1] - $SliceHeight;
  407. $Border[] = $Plots[count($Plots)-2]; $Border[] = $Plots[count($Plots)-1] - $SliceHeight; $Border[] = $Plots[count($Plots)-2]; $Border[] = $Plots[count($Plots)-1];
  408. $this->pChartObject->drawPolygon($Border,$Settings);
  409. }
  410. }
  411. /* Draw the rounded edges */
  412. foreach($Slices as $SliceID => $Plots)
  413. {
  414. $Settings = $SliceColors[$SliceID];
  415. $Settings["R"]+= 10; $Settings["G"]+= 10; $Settings["B"]+= 10; $Settings["NoBorder"] = TRUE;
  416. for ($j=2;$j<count($Plots)-2;$j=$j+2)
  417. {
  418. $Angle = $SliceAngle[$SliceID][$j/2];
  419. if ( $Angle < 270 && $Angle > 90 )
  420. {
  421. $Border = "";
  422. $Border[] = $Plots[$j]; $Border[] = $Plots[$j+1];
  423. $Border[] = $Plots[$j+2]; $Border[] = $Plots[$j+3];
  424. $Border[] = $Plots[$j+2]; $Border[] = $Plots[$j+3] - $SliceHeight;
  425. $Border[] = $Plots[$j]; $Border[] = $Plots[$j+1] - $SliceHeight;
  426. $this->pChartObject->drawPolygon($Border,$Settings);
  427. }
  428. }
  429. if ( $SecondPass )
  430. {
  431. $Settings = $SliceColors[$SliceID];
  432. if ( $Border )
  433. { $Settings["R"]+= 30; $Settings["G"]+= 30; $Settings["B"]+= 30; }
  434. if ( isset($SliceAngle[$SliceID][1]) ) /* Empty error handling */
  435. {
  436. $Angle = $SliceAngle[$SliceID][1];
  437. if ( $Angle < 270 && $Angle > 90 )
  438. {
  439. $Xc = cos(($Angle-90)*PI/180) * $Radius + $X;
  440. $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y;
  441. $this->pChartObject->drawLine($Xc,$Yc,$Xc,$Yc-$SliceHeight,$Settings);
  442. }
  443. }
  444. $Angle = $SliceAngle[$SliceID][count($SliceAngle[$SliceID])-1];
  445. if ( $Angle < 270 && $Angle > 90 )
  446. {
  447. $Xc = cos(($Angle-90)*PI/180) * $Radius + $X;
  448. $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y;
  449. $this->pChartObject->drawLine($Xc,$Yc,$Xc,$Yc-$SliceHeight,$Settings);
  450. }
  451. if ( isset($SliceAngle[$SliceID][1]) && $SliceAngle[$SliceID][1] > 270 && $SliceAngle[$SliceID][count($SliceAngle[$SliceID])-1] < 270 )
  452. {
  453. $Xc = cos((270-90)*PI/180) * $Radius + $X;
  454. $Yc = sin((270-90)*PI/180) * $Radius*$SkewFactor + $Y;
  455. $this->pChartObject->drawLine($Xc,$Yc,$Xc,$Yc-$SliceHeight,$Settings);
  456. }
  457. if ( isset($SliceAngle[$SliceID][1]) && $SliceAngle[$SliceID][1] > 90 && $SliceAngle[$SliceID][count($SliceAngle[$SliceID])-1] < 90 )
  458. {
  459. $Xc = cos((0)*PI/180) * $Radius + $X;
  460. $Yc = sin((0)*PI/180) * $Radius*$SkewFactor + $Y;
  461. $this->pChartObject->drawLine($Xc,$Yc,$Xc,$Yc-$SliceHeight,$Settings);
  462. }
  463. }
  464. }
  465. /* Draw the top splice */
  466. foreach($Slices as $SliceID => $Plots)
  467. {
  468. $Settings = $SliceColors[$SliceID];
  469. $Settings["R"]+= 20; $Settings["G"]+= 20; $Settings["B"]+= 20;
  470. $Top = "";
  471. for($j=0;$j<count($Plots);$j=$j+2) { $Top[] = $Plots[$j]; $Top[] = $Plots[$j+1]- $SliceHeight; }
  472. $this->pChartObject->drawPolygon($Top,$Settings);
  473. if ( $RecordImageMap && !$Shadow ) { $this->pChartObject->addToImageMap("POLY",$this->arraySerialize($Top),$this->pChartObject->toHTMLColor($Settings["R"],$Settings["G"],$Settings["B"]),$Data["Series"][$Data["Abscissa"]]["Data"][count($Slices)-$SliceID-1],$Values[$SliceID]); }
  474. }
  475. /* Second pass to smooth the angles */
  476. if ( $SecondPass )
  477. {
  478. $Step = 360 / (2 * PI * $Radius);
  479. $Offset = 360; $ID = count($Values)-1;
  480. foreach($Values as $Key => $Value)
  481. {
  482. $FirstPoint = TRUE;
  483. if ( $Shadow )
  484. $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa);
  485. else
  486. {
  487. if ( $Border )
  488. { $Settings = array("R"=>$Palette[$ID]["R"]+30,"G"=>$Palette[$ID]["G"]+30,"B"=>$Palette[$ID]["B"]+30,"Alpha"=>$Palette[$ID]["Alpha"]); }
  489. else
  490. $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);
  491. }
  492. $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; }
  493. if ($DataGapAngle == 0)
  494. { $X0 = $X; $Y0 = $Y- $SliceHeight; }
  495. else
  496. {
  497. $Angle = ($EndAngle - $Offset)/2 + $Offset;
  498. $X0 = cos(($Angle-90)*PI/180) * $DataGapRadius + $X;
  499. $Y0 = sin(($Angle-90)*PI/180) * $DataGapRadius*$SkewFactor + $Y - $SliceHeight;
  500. }
  501. $Plots[] = $X0; $Plots[] = $Y0;
  502. for($i=$Offset;$i>=$EndAngle;$i=$i-$Step)
  503. {
  504. $Xc = cos(($i-90)*PI/180) * $Radius + $X;
  505. $Yc = sin(($i-90)*PI/180) * $Radius*$SkewFactor + $Y - $SliceHeight;
  506. if ( $FirstPoint ) { $this->pChartObject->drawLine($Xc,$Yc,$X0,$Y0,$Settings); } { $FirstPoint = FALSE; }
  507. $this->pChartObject->drawAntialiasPixel($Xc,$Yc,$Settings);
  508. if ($i < 270 && $i > 90 ) { $this->pChartObject->drawAntialiasPixel($Xc,$Yc+$SliceHeight,$Settings); }
  509. }
  510. $this->pChartObject->drawLine($Xc,$Yc,$X0,$Y0,$Settings);
  511. $Offset = $i - $DataGapAngle; $ID--;
  512. }
  513. }
  514. if ( $WriteValues != NULL )
  515. {
  516. $Step = 360 / (2 * PI * $Radius);
  517. $Offset = 360; $ID = count($Values)-1;
  518. $Settings = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"R"=>$ValueR,"G"=>$ValueG,"B"=>$ValueB,"Alpha"=>$ValueAlpha);
  519. foreach($Values as $Key => $Value)
  520. {
  521. $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; }
  522. $Angle = ($EndAngle - $Offset)/2 + $Offset;
  523. if ( $ValuePosition == PIE_VALUE_OUTSIDE )
  524. {
  525. $Xc = cos(($Angle-90)*PI/180) * ($Radius+$ValuePadding) + $X;
  526. $Yc = sin(($Angle-90)*PI/180) * (($Radius*$SkewFactor)+$ValuePadding) + $Y - $SliceHeight;
  527. }
  528. else
  529. {
  530. $Xc = cos(($Angle-90)*PI/180) * ($Radius)/2 + $X;
  531. $Yc = sin(($Angle-90)*PI/180) * ($Radius*$SkewFactor)/2 + $Y - $SliceHeight;
  532. }
  533. if ( $WriteValues == PIE_VALUE_PERCENTAGE )
  534. $Display = round(( 100 / $SerieSum ) * $Value,$Precision)."%";
  535. elseif ( $WriteValues == PIE_VALUE_NATURAL )
  536. $Display = $Value.$ValueSuffix;
  537. $this->pChartObject->drawText($Xc,$Yc,$Display,$Settings);
  538. $Offset = $EndAngle - $DataGapAngle; $ID--;
  539. }
  540. }
  541. if ( $DrawLabels )
  542. {
  543. $Step = 360 / (2 * PI * $Radius);
  544. $Offset = 360; $ID = count($Values)-1;
  545. foreach($Values as $Key => $Value)
  546. {
  547. if ( $LabelColor == PIE_LABEL_COLOR_AUTO )
  548. { $Settings = array("FillR"=>$Palette[$ID]["R"],"FillG"=>$Palette[$ID]["G"],"FillB"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);}
  549. else
  550. { $Settings = array("FillR"=>$LabelR,"FillG"=>$LabelG,"FillB"=>$LabelB,"Alpha"=>$LabelAlpha); }
  551. $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; }
  552. $Angle = ($EndAngle - $Offset)/2 + $Offset;
  553. $Xc = cos(($Angle-90)*PI/180) * $Radius + $X;
  554. $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y - $SliceHeight;
  555. if ( isset($Data["Series"][$Data["Abscissa"]]["Data"][$ID]) )
  556. {
  557. $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$ID];
  558. if ( $LabelStacked )
  559. $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,TRUE,$X,$Y,$Radius,TRUE);
  560. else
  561. $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,FALSE);
  562. }
  563. $Offset = $EndAngle - $DataGapAngle; $ID--;
  564. }
  565. }
  566. if ( $DrawLabels && $LabelStacked ) { $this->writeShiftedLabels(); }
  567. $this->pChartObject->Shadow = $RestoreShadow;
  568. return(PIE_RENDERED);
  569. }
  570. /* Draw the legend of pie chart */
  571. function drawPieLegend($X,$Y,$Format="")
  572. {
  573. $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName;
  574. $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize;
  575. $FontR = isset($Format["FontR"]) ? $Format["FontR"] : $this->pChartObject->FontColorR;
  576. $FontG = isset($Format["FontG"]) ? $Format["FontG"] : $this->pChartObject->FontColorG;
  577. $FontB = isset($Format["FontB"]) ? $Format["FontB"] : $this->pChartObject->FontColorB;
  578. $BoxSize = isset($Format["BoxSize"]) ? $Format["BoxSize"] : 5;
  579. $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5;
  580. $R = isset($Format["R"]) ? $Format["R"] : 200;
  581. $G = isset($Format["G"]) ? $Format["G"] : 200;
  582. $B = isset($Format["B"]) ? $Format["B"] : 200;
  583. $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
  584. $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255;
  585. $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255;
  586. $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255;
  587. $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
  588. $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND;
  589. $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL;
  590. if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; }
  591. $YStep = max($this->pChartObject->FontSize,$BoxSize) + 5;
  592. $XStep = $BoxSize + 5;
  593. /* Data Processing */
  594. $Data = $this->pDataObject->getData();
  595. $Palette = $this->pDataObject->getPalette();
  596. /* Do we have an abscissa serie defined? */
  597. if ( $Data["Abscissa"] == "" ) { return(PIE_NO_ABSCISSA); }
  598. $Boundaries = ""; $Boundaries["L"] = $X; $Boundaries["T"] = $Y; $Boundaries["R"] = 0; $Boundaries["B"] = 0; $vY = $Y; $vX = $X;
  599. foreach($Data["Series"][$Data["Abscissa"]]["Data"] as $Key => $Value)
  600. {
  601. $BoxArray = $this->pChartObject->getTextBox($vX+$BoxSize+4,$vY+$BoxSize/2,$FontName,$FontSize,0,$Value);
  602. if ( $Mode == LEGEND_VERTICAL )
  603. {
  604. if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$BoxSize/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$BoxSize/2; }
  605. if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; }
  606. if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$BoxSize/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$BoxSize/2; }
  607. $vY=$vY+$YStep;
  608. }
  609. elseif ( $Mode == LEGEND_HORIZONTAL )
  610. {
  611. if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$BoxSize/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$BoxSize/2; }
  612. if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; }
  613. if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$BoxSize/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$BoxSize/2; }
  614. $vX=$Boundaries["R"]+$XStep;
  615. }
  616. }
  617. $vY=$vY-$YStep; $vX=$vX-$XStep;
  618. $TopOffset = $Y - $Boundaries["T"];
  619. if ( $Boundaries["B"]-($vY+$BoxSize) < $TopOffset ) { $Boundaries["B"] = $vY+$BoxSize+$TopOffset; }
  620. if ( $Style == LEGEND_ROUND )
  621. $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));
  622. elseif ( $Style == LEGEND_BOX )
  623. $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));
  624. $RestoreShadow = $this->pChartObject->Shadow; $this->pChartObject->Shadow = FALSE;
  625. foreach($Data["Series"][$Data["Abscissa"]]["Data"] as $Key => $Value)
  626. {
  627. $R = $Palette[$Key]["R"]; $G = $Palette[$Key]["G"]; $B = $Palette[$Key]["B"];
  628. $this->pChartObject->drawFilledRectangle($X+1,$Y+1,$X+$BoxSize+1,$Y+$BoxSize+1,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20));
  629. $this->pChartObject->drawFilledRectangle($X,$Y,$X+$BoxSize,$Y+$BoxSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Surrounding"=>20));
  630. if ( $Mode == LEGEND_VERTICAL )
  631. {
  632. $this->pChartObject->drawText($X+$BoxSize+4,$Y+$BoxSize/2,$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT,"FontName"=>$FontName,"FontSize"=>$FontSize));
  633. $Y=$Y+$YStep;
  634. }
  635. elseif ( $Mode == LEGEND_HORIZONTAL )
  636. {
  637. $BoxArray = $this->pChartObject->drawText($X+$BoxSize+4,$Y+$BoxSize/2,$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT,"FontName"=>$FontName,"FontSize"=>$FontSize));
  638. $X=$BoxArray[1]["X"]+2+$XStep;
  639. }
  640. }
  641. $this->Shadow = $RestoreShadow;
  642. }
  643. /* Set the color of the specified slice */
  644. function setSliceColor($SliceID,$Format="")
  645. {
  646. $R = isset($Format["R"]) ? $Format["R"] : 0;
  647. $G = isset($Format["G"]) ? $Format["G"] : 0;
  648. $B = isset($Format["B"]) ? $Format["B"] : 0;
  649. $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
  650. $this->pDataObject->Palette[$SliceID]["R"] = $R;
  651. $this->pDataObject->Palette[$SliceID]["G"] = $G;
  652. $this->pDataObject->Palette[$SliceID]["B"] = $B;
  653. $this->pDataObject->Palette[$SliceID]["Alpha"] = $Alpha;
  654. }
  655. /* Internally used compute the label positions */
  656. function writePieLabel($X,$Y,$Label,$Angle,$Settings,$Stacked,$Xc=0,$Yc=0,$Radius=0,$Reversed=FALSE)
  657. {
  658. $LabelOffset = 30;
  659. $FontName = $this->pChartObject->FontName;
  660. $FontSize = $this->pChartObject->FontSize;
  661. if ( !$Stacked )
  662. {
  663. $Settings["Angle"] = 360-$Angle;
  664. $Settings["Length"] = 25;
  665. $Settings["Size"] = 8;
  666. $this->pChartObject->drawArrowLabel($X,$Y," ".$Label." ",$Settings);
  667. }
  668. else
  669. {
  670. $X2 = cos(deg2rad($Angle-90))*20+$X;
  671. $Y2 = sin(deg2rad($Angle-90))*20+$Y;
  672. $TxtPos = $this->pChartObject->getTextBox($X,$Y,$FontName,$FontSize,0,$Label);
  673. $Height = $TxtPos[0]["Y"] - $TxtPos[2]["Y"];
  674. $YTop = $Y2 - $Height/2 - 2;
  675. $YBottom = $Y2 + $Height/2 + 2;
  676. if ( $this->LabelPos != "" )
  677. {
  678. $Done = FALSE;
  679. foreach($this->LabelPos as $Key => $Settings)
  680. {
  681. if ( !$Done )
  682. {
  683. if ( $Angle <= 90 && (($YTop >= $Settings["YTop"] && $YTop <= $Settings["YBottom"]) || ($YBottom >= $Settings["YTop"] && $YBottom <= $Settings["YBottom"])))
  684. { $this->shift(0,180,-($Height+2),$Reversed); $Done = TRUE; }
  685. if ( $Angle > 90 && $Angle <= 180 && (($YTop >= $Settings["YTop"] && $YTop <= $Settings["YBottom"]) || ($YBottom >= $Settings["YTop"] && $YBottom <= $Settings["YBottom"])))
  686. { $this->shift(0,180,-($Height+2),$Reversed); $Done = TRUE; }
  687. if ( $Angle > 180 && $Angle <= 270 && (($YTop >= $Settings["YTop"] && $YTop <= $Settings["YBottom"]) || ($YBottom >= $Settings["YTop"] && $YBottom <= $Settings["YBottom"])))
  688. { $this->shift(180,360,($Height+2),$Reversed); $Done = TRUE; }
  689. if ( $Angle > 270 && $Angle <= 360 && (($YTop >= $Settings["YTop"] && $YTop <= $Settings["YBottom"]) || ($YBottom >= $Settings["YTop"] && $YBottom <= $Settings["YBottom"])))
  690. { $this->shift(180,360,($Height+2),$Reversed); $Done = TRUE; }
  691. }
  692. }
  693. }
  694. $LabelSettings = array("YTop"=>$YTop,"YBottom"=>$YBottom,"Label"=>$Label,"Angle"=>$Angle,"X1"=>$X,"Y1"=>$Y,"X2"=>$X2,"Y2"=>$Y2);
  695. if ( $Angle <= 180 ) { $LabelSettings["X3"] = $Xc+$Radius+$LabelOffset; }
  696. if ( $Angle > 180 ) { $LabelSettings["X3"] = $Xc-$Radius-$LabelOffset; }
  697. $this->LabelPos[] = $LabelSettings;
  698. }
  699. }
  700. /* Internally used to shift label positions */
  701. function shift($StartAngle,$EndAngle,$Offset,$Reversed)
  702. {
  703. if ( $Reversed ) { $Offset = -$Offset; }
  704. foreach($this->LabelPos as $Key => $Settings)
  705. {
  706. if ( $Settings["Angle"] > $StartAngle && $Settings["Angle"] <= $EndAngle ) { $this->LabelPos[$Key]["YTop"] = $Settings["YTop"] + $Offset; $this->LabelPos[$Key]["YBottom"] = $Settings["YBottom"] + $Offset; $this->LabelPos[$Key]["Y2"] = $Settings["Y2"] + $Offset; }
  707. }
  708. }
  709. /* Internally used to write the re-computed labels */
  710. function writeShiftedLabels()
  711. {
  712. if ( $this->LabelPos == "" ) { return(0); }
  713. foreach($this->LabelPos as $Key => $Settings)
  714. {
  715. $X1 = $Settings["X1"]; $Y1 = $Settings["Y1"];
  716. $X2 = $Settings["X2"]; $Y2 = $Settings["Y2"];
  717. $X3 = $Settings["X3"];
  718. $Angle = $Settings["Angle"];
  719. $Label = $Settings["Label"];
  720. $this->pChartObject->drawArrow($X2,$Y2,$X1,$Y1,array("Size"=>8));
  721. if ( $Angle <= 180 )
  722. {
  723. $this->pChartObject->drawLine($X2,$Y2,$X3,$Y2);
  724. $this->pChartObject->drawText($X3+2,$Y2,$Label,array("Align"=>TEXT_ALIGN_MIDDLELEFT));
  725. }
  726. else
  727. {
  728. $this->pChartObject->drawLine($X2,$Y2,$X3,$Y2);
  729. $this->pChartObject->drawText($X3-2,$Y2,$Label,array("Align"=>TEXT_ALIGN_MIDDLERIGHT));
  730. }
  731. }
  732. }
  733. /* Draw a ring chart */
  734. function draw2DRing($X,$Y,$Format="")
  735. {
  736. $OuterRadius = isset($Format["Radius"]) ? $Format["Radius"] : 60;
  737. $Precision = isset($Format["Precision"]) ? $Format["Precision"] : 0;
  738. $InnerRadius = isset($Format["Radius"]) ? $Format["Radius"] : 30;
  739. $Border = isset($Format["Border"]) ? $Format["Border"] : FALSE;
  740. $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255;
  741. $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255;
  742. $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255;
  743. $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 100;
  744. $Shadow = isset($Format["Shadow"]) ? $Format["Shadow"] : FALSE;
  745. $DrawLabels = isset($Format["DrawLabels"]) ? $Format["DrawLabels"] : FALSE;
  746. $LabelStacked = isset($Format["LabelStacked"]) ? $Format["LabelStacked"] : FALSE;
  747. $LabelColor = isset($Format["LabelColor"]) ? $Format["LabelColor"] : PIE_LABEL_COLOR_MANUAL;
  748. $LabelR = isset($Format["LabelR"]) ? $Format["LabelR"] : 0;
  749. $LabelG = isset($Format["LabelG"]) ? $Format["LabelG"] : 0;
  750. $LabelB = isset($Format["LabelB"]) ? $Format["LabelB"] : 0;
  751. $LabelAlpha = isset($Format["LabelAlpha"]) ? $Format["LabelAlpha"] : 100;
  752. $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : NULL; //PIE_VALUE_PERCENTAGE
  753. $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 5;
  754. $ValuePosition = isset($Format["ValuePosition"]) ? $Format["ValuePosition"] : PIE_VALUE_OUTSIDE;
  755. $ValueSuffix = isset($Format["ValueSuffix"]) ? $Format["ValueSuffix"] : "";
  756. $ValueR = isset($Format["ValueR"]) ? $Format["ValueR"] : 255;
  757. $ValueG = isset($Format["ValueG"]) ? $Format["ValueG"] : 255;
  758. $ValueB = isset($Format["ValueB"]) ? $Format["ValueB"] : 255;
  759. $ValueAlpha = isset($Format["ValueAlpha"]) ? $Format["ValueAlpha"] : 100;
  760. $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE;
  761. /* Data Processing */
  762. $Data = $this->pDataObject->getData();
  763. $Palette = $this->pDataObject->getPalette();
  764. /* Do we have an abscissa serie defined? */
  765. if ( $Data["Abscissa"] == "" ) { return(PIE_NO_ABSCISSA); }
  766. /* Try to find the data serie */
  767. $DataSerie = "";
  768. foreach ($Data["Series"] as $SerieName => $SerieData)
  769. { if ( $SerieName != $Data["Abscissa"]) { $DataSerie = $SerieName; } }
  770. /* Do we have data to compute? */
  771. if ( $DataSerie == "" ) { return(PIE_NO_DATASERIE); }
  772. /* Remove unused data */
  773. list($Data,$Palette) = $this->clean0Values($Data,$Palette,$DataSerie,$Data["Abscissa"]);
  774. /* Compute the pie sum */
  775. $SerieSum = $this->pDataObject->getSum($DataSerie);
  776. /* Do we have data to draw? */
  777. if ( $SerieSum == 0 ) { return(PIE_SUMISNULL); }
  778. /* Dump the real number of data to draw */
  779. $Values = "";
  780. foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value)
  781. { if ($Value != 0) { $Values[] = $Value; } }
  782. /* Compute the wasted angular space between series */
  783. if (count($Values)==1) { $WastedAngular = 0; } else { $WastedAngular = 0; } // count($Values)
  784. /* Compute the scale */
  785. $ScaleFactor = (360 - $WastedAngular) / $SerieSum;
  786. $RestoreShadow = $this->pChartObject->Shadow;
  787. if ( $this->pChartObject->Shadow )
  788. {
  789. $this->pChartObject->Shadow = FALSE;
  790. $ShadowFormat = $Format; $ShadowFormat["Shadow"] = TRUE;
  791. $this->draw2DRing($X+$this->pChartObject->ShadowX,$Y+$this->pChartObject->ShadowY,$ShadowFormat);
  792. }
  793. /* Draw the polygon pie elements */
  794. $Step = 360 / (2 * PI * $OuterRadius);
  795. $Offset = 0; $ID = 0;
  796. foreach($Values as $Key => $Value)
  797. {
  798. if ( $Shadow )
  799. {
  800. $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa);
  801. $BorderColor = $Settings;
  802. }
  803. else
  804. {
  805. if ( !isset($Palette[$ID]["R"]) ) { $Color = $this->pChartObject->getRandomColor(); $Palette[$ID] = $Color; $this->pDataObject->savePalette($ID,$Color); }
  806. $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);
  807. if ( $Border )
  808. $BorderColor = array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha);
  809. else
  810. $BorderColor = $Settings;
  811. }
  812. $Plots = ""; $Boundaries = ""; $AAPixels = "";
  813. $EndAngle = $Offset+($Value*$ScaleFactor); if ( $EndAngle > 360 ) { $EndAngle = 360; }
  814. for($i=$Offset;$i<=$EndAngle;$i=$i+$Step)
  815. {
  816. $Xc = cos(($i-90)*PI/180) * $OuterRadius + $X;
  817. $Yc = sin(($i-90)*PI/180) * $OuterRadius + $Y;
  818. if ( !isset($Boundaries[0]["X1"]) ) { $Boundaries[0]["X1"] = $Xc; $Boundaries[0]["Y1"] = $Yc; }
  819. $AAPixels[] = array($Xc,$Yc);
  820. if ( $i<90 ) { $Yc++; }
  821. if ( $i>180 && $i<270 ) { $Xc++; }
  822. if ( $i>=270 ) { $Xc++; $Yc++; }
  823. $Plots[] = $Xc; $Plots[] = $Yc;
  824. }
  825. $Boundaries[1]["X1"] = $Xc; $Boundaries[1]["Y1"] = $Yc;
  826. $Lasti = $EndAngle;
  827. for($i=$EndAngle;$i>=$Offset;$i=$i-$Step)
  828. {
  829. $Xc = cos(($i-90)*PI/180) * ($InnerRadius-1) + $X;
  830. $Yc = sin(($i-90)*PI/180) * ($InnerRadius-1) + $Y;
  831. if ( !isset($Boundaries[1]["X2"]) ) { $Boundaries[1]["X2"] = $Xc; $Boundaries[1]["Y2"] = $Yc; }
  832. $AAPixels[] = array($Xc,$Yc);
  833. $Xc = cos(($i-90)*PI/180) * $InnerRadius + $X;
  834. $Yc = sin(($i-90)*PI/180) * $InnerRadius + $Y;
  835. if ( $i<90 ) { $Yc++; }
  836. if ( $i>180 && $i<270 ) { $Xc++; }
  837. if ( $i>=270 ) { $Xc++; $Yc++; }
  838. $Plots[] = $Xc; $Plots[] = $Yc;
  839. }
  840. $Boundaries[0]["X2"] = $Xc; $Boundaries[0]["Y2"] = $Yc;
  841. /* Draw the polygon */
  842. $this->pChartObject->drawPolygon($Plots,$Settings);
  843. if ( $RecordImageMap && !$Shadow ) { $this->pChartObject->addToImageMap("POLY",$this->arraySerialize($Plots),$this->pChartObject->toHTMLColor($Palette[$ID]["R"],$Palette[$ID]["G"],$Palette[$ID]["B"]),$Data["Series"][$Data["Abscissa"]]["Data"][$Key],$Value); }
  844. /* Smooth the edges using AA */
  845. foreach($AAPixels as $iKey => $Pos ) { $this->pChartObject->drawAntialiasPixel($Pos[0],$Pos[1],$BorderColor); }
  846. $this->pChartObject->drawLine($Boundaries[0]["X1"],$Boundaries[0]["Y1"],$Boundaries[0]["X2"],$Boundaries[0]["Y2"],$BorderColor);
  847. $this->pChartObject->drawLine($Boundaries[1]["X1"],$Boundaries[1]["Y1"],$Boundaries[1]["X2"],$Boundaries[1]["Y2"],$BorderColor);
  848. if ( $DrawLabels && !$Shadow )
  849. {
  850. if ( $LabelColor == PIE_LABEL_COLOR_AUTO )
  851. { $Settings = array("FillR"=>$Palette[$ID]["R"],"FillG"=>$Palette[$ID]["G"],"FillB"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);}
  852. else
  853. { $Settings = array("FillR"=>$LabelR,"FillG"=>$LabelG,"FillB"=>$LabelB,"Alpha"=>$LabelAlpha); }
  854. $Angle = ($EndAngle - $Offset)/2 + $Offset;
  855. $Xc = cos(($Angle-90)*PI/180) * $OuterRadius + $X;
  856. $Yc = sin(($Angle-90)*PI/180) * $OuterRadius + $Y;
  857. $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$Key];
  858. if ( $LabelStacked )
  859. $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,TRUE,$X,$Y,$OuterRadius);
  860. else
  861. $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,FALSE);
  862. }
  863. $Offset = $Lasti; $ID++;
  864. }
  865. if ( $DrawLabels && $LabelStacked ) { $this->writeShiftedLabels(); }
  866. if ( $WriteValues && !$Shadow )
  867. {
  868. $Step = 360 / (2 * PI * $OuterRadius);
  869. $Offset = 0;
  870. foreach($Values as $Key => $Value)
  871. {
  872. $EndAngle = $Offset+($Value*$ScaleFactor);
  873. if ( $EndAngle > 360 ) { $EndAngle = 360; }
  874. $Angle = $Offset+($Value*$ScaleFactor)/2;
  875. if ( $ValuePosition == PIE_VALUE_OUTSIDE )
  876. {
  877. $Xc = cos(($Angle-90)*PI/180) * ($OuterRadius+$ValuePadding) + $X;
  878. $Yc = sin(($Angle-90)*PI/180) * ($OuterRadius+$ValuePadding) + $Y;
  879. if ( $Angle >=0 && $Angle <= 90 ) { $Align = TEXT_ALIGN_BOTTOMLEFT; }
  880. if ( $Angle > 90 && $Angle <= 180 ) { $Align = TEXT_ALIGN_TOPLEFT; }
  881. if ( $Angle > 180 && $Angle <= 270 ) { $Align = TEXT_ALIGN_TOPRIGHT; }
  882. if ( $Angle > 270 ) { $Align = TEXT_ALIGN_BOTTOMRIGHT; }
  883. }
  884. else
  885. {
  886. $Xc = cos(($Angle-90)*PI/180) * (($OuterRadius-$InnerRadius)/2+$InnerRadius) + $X;
  887. $Yc = sin(($Angle-90)*PI/180) * (($OuterRadius-$InnerRadius)/2+$InnerRadius) + $Y;
  888. $Align = TEXT_ALIGN_MIDDLEMIDDLE;
  889. }
  890. if ( $WriteValues == PIE_VALUE_PERCENTAGE )
  891. $Display = round(( 100 / $SerieSum ) * $Value,$Precision)."%";
  892. elseif ( $WriteValues == PIE_VALUE_NATURAL )
  893. $Display = $Value.$ValueSuffix;
  894. else
  895. $Label = "";
  896. $this->pChartObject->drawText($Xc,$Yc,$Display,array("Align"=>$Align,"R"=>$ValueR,"G"=>$ValueG,"B"=>$ValueB));
  897. $Offset = $EndAngle;
  898. }
  899. }
  900. $this->pChartObject->Shadow = $RestoreShadow;
  901. return(PIE_RENDERED);
  902. }
  903. /* Draw a 3D ring chart */
  904. function draw3DRing($X,$Y,$Format="")
  905. {
  906. $OuterRadius = isset($Format["OuterRadius"]) ? $Format["OuterRadius"] : 100;
  907. $Precision = isset($Format["Precision"]) ? $Format["Precision"] : 0;
  908. $InnerRadius = isset($Format["InnerRadius"]) ? $Format["InnerRadius"] : 30;
  909. $SkewFactor = isset($Format["SkewFactor"]) ? $Format["SkewFactor"] : .6;
  910. $SliceHeight = isset($Format["SliceHeight"]) ? $Format["SliceHeight"] : 10;
  911. $DataGapAngle = isset($Format["DataGapAngle"]) ? $Format["DataGapAngle"] : 10;
  912. $DataGapRadius = isset($Format["DataGapRadius"]) ? $Format["DataGapRadius"] : 10;
  913. $Border = isset($Format["Border"]) ? $Format["Border"] : FALSE;
  914. $Shadow = isset($Format["Shadow"]) ? $Format["Shadow"] : FALSE;
  915. $DrawLabels = isset($Format["DrawLabels"]) ? $Format["DrawLabels"] : FALSE;
  916. $LabelStacked = isset($Format["LabelStacked"]) ? $Format["LabelStacked"] : FALSE;
  917. $LabelColor = isset($Format["LabelColor"]) ? $Format["LabelColor"] : PIE_LABEL_

Large files files are truncated, but you can click here to view the full file