PageRenderTime 139ms CodeModel.GetById 44ms RepoModel.GetById 2ms app.codeStats 1ms

/TEMPLATE/Reports/class/pchart2/class/pPie.class.php

https://bitbucket.org/Lahiru_LCB/sep_wd_07
PHP | 1457 lines | 1109 code | 259 blank | 89 comment | 346 complexity | eff789e37a8b431b73122f80601c0b7b MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1

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

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