jpgraph.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2013 PHPExcel
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * @category PHPExcel
  22. * @package PHPExcel_Chart_Renderer
  23. * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version 1.7.9, 2013-06-02
  26. */
  27. require_once(PHPExcel_Settings::getChartRendererPath().'/jpgraph.php');
  28. /**
  29. * PHPExcel_Chart_Renderer_jpgraph
  30. *
  31. * @category PHPExcel
  32. * @package PHPExcel_Chart_Renderer
  33. * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel)
  34. */
  35. class PHPExcel_Chart_Renderer_jpgraph
  36. {
  37. private static $_width = 640;
  38. private static $_height = 480;
  39. private static $_colourSet = array( 'mediumpurple1', 'palegreen3', 'gold1', 'cadetblue1',
  40. 'darkmagenta', 'coral', 'dodgerblue3', 'eggplant',
  41. 'mediumblue', 'magenta', 'sandybrown', 'cyan',
  42. 'firebrick1', 'forestgreen', 'deeppink4', 'darkolivegreen',
  43. 'goldenrod2'
  44. );
  45. private static $_markSet = array( 'diamond' => MARK_DIAMOND,
  46. 'square' => MARK_SQUARE,
  47. 'triangle' => MARK_UTRIANGLE,
  48. 'x' => MARK_X,
  49. 'star' => MARK_STAR,
  50. 'dot' => MARK_FILLEDCIRCLE,
  51. 'dash' => MARK_DTRIANGLE,
  52. 'circle' => MARK_CIRCLE,
  53. 'plus' => MARK_CROSS
  54. );
  55. private $_chart = null;
  56. private $_graph = null;
  57. private static $_plotColour = 0;
  58. private static $_plotMark = 0;
  59. private function _formatPointMarker($seriesPlot,$markerID) {
  60. $plotMarkKeys = array_keys(self::$_markSet);
  61. if (is_null($markerID)) {
  62. // Use default plot marker (next marker in the series)
  63. self::$_plotMark %= count(self::$_markSet);
  64. $seriesPlot->mark->SetType(self::$_markSet[$plotMarkKeys[self::$_plotMark++]]);
  65. } elseif ($markerID !== 'none') {
  66. // Use specified plot marker (if it exists)
  67. if (isset(self::$_markSet[$markerID])) {
  68. $seriesPlot->mark->SetType(self::$_markSet[$markerID]);
  69. } else {
  70. // If the specified plot marker doesn't exist, use default plot marker (next marker in the series)
  71. self::$_plotMark %= count(self::$_markSet);
  72. $seriesPlot->mark->SetType(self::$_markSet[$plotMarkKeys[self::$_plotMark++]]);
  73. }
  74. } else {
  75. // Hide plot marker
  76. $seriesPlot->mark->Hide();
  77. }
  78. $seriesPlot->mark->SetColor(self::$_colourSet[self::$_plotColour]);
  79. $seriesPlot->mark->SetFillColor(self::$_colourSet[self::$_plotColour]);
  80. $seriesPlot->SetColor(self::$_colourSet[self::$_plotColour++]);
  81. return $seriesPlot;
  82. } // function _formatPointMarker()
  83. private function _formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation = '') {
  84. $datasetLabelFormatCode = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getFormatCode();
  85. if (!is_null($datasetLabelFormatCode)) {
  86. // Retrieve any label formatting code
  87. $datasetLabelFormatCode = stripslashes($datasetLabelFormatCode);
  88. }
  89. $testCurrentIndex = 0;
  90. foreach($datasetLabels as $i => $datasetLabel) {
  91. if (is_array($datasetLabel)) {
  92. if ($rotation == 'bar') {
  93. $datasetLabels[$i] = implode(" ",$datasetLabel);
  94. } else {
  95. $datasetLabel = array_reverse($datasetLabel);
  96. $datasetLabels[$i] = implode("\n",$datasetLabel);
  97. }
  98. } else {
  99. // Format labels according to any formatting code
  100. if (!is_null($datasetLabelFormatCode)) {
  101. $datasetLabels[$i] = PHPExcel_Style_NumberFormat::toFormattedString($datasetLabel,$datasetLabelFormatCode);
  102. }
  103. }
  104. ++$testCurrentIndex;
  105. }
  106. return $datasetLabels;
  107. } // function _formatDataSetLabels()
  108. private function _percentageSumCalculation($groupID,$seriesCount) {
  109. // Adjust our values to a percentage value across all series in the group
  110. for($i = 0; $i < $seriesCount; ++$i) {
  111. if ($i == 0) {
  112. $sumValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  113. } else {
  114. $nextValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  115. foreach($nextValues as $k => $value) {
  116. if (isset($sumValues[$k])) {
  117. $sumValues[$k] += $value;
  118. } else {
  119. $sumValues[$k] = $value;
  120. }
  121. }
  122. }
  123. }
  124. return $sumValues;
  125. } // function _percentageSumCalculation()
  126. private function _percentageAdjustValues($dataValues,$sumValues) {
  127. foreach($dataValues as $k => $dataValue) {
  128. $dataValues[$k] = $dataValue / $sumValues[$k] * 100;
  129. }
  130. return $dataValues;
  131. } // function _percentageAdjustValues()
  132. private function _getCaption($captionElement) {
  133. // Read any caption
  134. $caption = (!is_null($captionElement)) ? $captionElement->getCaption() : NULL;
  135. // Test if we have a title caption to display
  136. if (!is_null($caption)) {
  137. // If we do, it could be a plain string or an array
  138. if (is_array($caption)) {
  139. // Implode an array to a plain string
  140. $caption = implode('',$caption);
  141. }
  142. }
  143. return $caption;
  144. } // function _getCaption()
  145. private function _renderTitle() {
  146. $title = $this->_getCaption($this->_chart->getTitle());
  147. if (!is_null($title)) {
  148. $this->_graph->title->Set($title);
  149. }
  150. } // function _renderTitle()
  151. private function _renderLegend() {
  152. $legend = $this->_chart->getLegend();
  153. if (!is_null($legend)) {
  154. $legendPosition = $legend->getPosition();
  155. $legendOverlay = $legend->getOverlay();
  156. switch ($legendPosition) {
  157. case 'r' :
  158. $this->_graph->legend->SetPos(0.01,0.5,'right','center'); // right
  159. $this->_graph->legend->SetColumns(1);
  160. break;
  161. case 'l' :
  162. $this->_graph->legend->SetPos(0.01,0.5,'left','center'); // left
  163. $this->_graph->legend->SetColumns(1);
  164. break;
  165. case 't' :
  166. $this->_graph->legend->SetPos(0.5,0.01,'center','top'); // top
  167. break;
  168. case 'b' :
  169. $this->_graph->legend->SetPos(0.5,0.99,'center','bottom'); // bottom
  170. break;
  171. default :
  172. $this->_graph->legend->SetPos(0.01,0.01,'right','top'); // top-right
  173. $this->_graph->legend->SetColumns(1);
  174. break;
  175. }
  176. } else {
  177. $this->_graph->legend->Hide();
  178. }
  179. } // function _renderLegend()
  180. private function _renderCartesianPlotArea($type='textlin') {
  181. $this->_graph = new Graph(self::$_width,self::$_height);
  182. $this->_graph->SetScale($type);
  183. $this->_renderTitle();
  184. // Rotate for bar rather than column chart
  185. $rotation = $this->_chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotDirection();
  186. $reverse = ($rotation == 'bar') ? true : false;
  187. $xAxisLabel = $this->_chart->getXAxisLabel();
  188. if (!is_null($xAxisLabel)) {
  189. $title = $this->_getCaption($xAxisLabel);
  190. if (!is_null($title)) {
  191. $this->_graph->xaxis->SetTitle($title,'center');
  192. $this->_graph->xaxis->title->SetMargin(35);
  193. if ($reverse) {
  194. $this->_graph->xaxis->title->SetAngle(90);
  195. $this->_graph->xaxis->title->SetMargin(90);
  196. }
  197. }
  198. }
  199. $yAxisLabel = $this->_chart->getYAxisLabel();
  200. if (!is_null($yAxisLabel)) {
  201. $title = $this->_getCaption($yAxisLabel);
  202. if (!is_null($title)) {
  203. $this->_graph->yaxis->SetTitle($title,'center');
  204. if ($reverse) {
  205. $this->_graph->yaxis->title->SetAngle(0);
  206. $this->_graph->yaxis->title->SetMargin(-55);
  207. }
  208. }
  209. }
  210. } // function _renderCartesianPlotArea()
  211. private function _renderPiePlotArea($doughnut = False) {
  212. $this->_graph = new PieGraph(self::$_width,self::$_height);
  213. $this->_renderTitle();
  214. } // function _renderPiePlotArea()
  215. private function _renderRadarPlotArea() {
  216. $this->_graph = new RadarGraph(self::$_width,self::$_height);
  217. $this->_graph->SetScale('lin');
  218. $this->_renderTitle();
  219. } // function _renderRadarPlotArea()
  220. private function _renderPlotLine($groupID, $filled = false, $combination = false, $dimensions = '2d') {
  221. $grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
  222. $labelCount = count($this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
  223. if ($labelCount > 0) {
  224. $datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
  225. $datasetLabels = $this->_formatDataSetLabels($groupID, $datasetLabels, $labelCount);
  226. $this->_graph->xaxis->SetTickLabels($datasetLabels);
  227. }
  228. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  229. $seriesPlots = array();
  230. if ($grouping == 'percentStacked') {
  231. $sumValues = $this->_percentageSumCalculation($groupID,$seriesCount);
  232. }
  233. // Loop through each data series in turn
  234. for($i = 0; $i < $seriesCount; ++$i) {
  235. $dataValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  236. $marker = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
  237. if ($grouping == 'percentStacked') {
  238. $dataValues = $this->_percentageAdjustValues($dataValues,$sumValues);
  239. }
  240. // Fill in any missing values in the $dataValues array
  241. $testCurrentIndex = 0;
  242. foreach($dataValues as $k => $dataValue) {
  243. while($k != $testCurrentIndex) {
  244. $dataValues[$testCurrentIndex] = null;
  245. ++$testCurrentIndex;
  246. }
  247. ++$testCurrentIndex;
  248. }
  249. $seriesPlot = new LinePlot($dataValues);
  250. if ($combination) {
  251. $seriesPlot->SetBarCenter();
  252. }
  253. if ($filled) {
  254. $seriesPlot->SetFilled(true);
  255. $seriesPlot->SetColor('black');
  256. $seriesPlot->SetFillColor(self::$_colourSet[self::$_plotColour++]);
  257. } else {
  258. // Set the appropriate plot marker
  259. $this->_formatPointMarker($seriesPlot,$marker);
  260. }
  261. $dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
  262. $seriesPlot->SetLegend($dataLabel);
  263. $seriesPlots[] = $seriesPlot;
  264. }
  265. if ($grouping == 'standard') {
  266. $groupPlot = $seriesPlots;
  267. } else {
  268. $groupPlot = new AccLinePlot($seriesPlots);
  269. }
  270. $this->_graph->Add($groupPlot);
  271. } // function _renderPlotLine()
  272. private function _renderPlotBar($groupID, $dimensions = '2d') {
  273. $rotation = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotDirection();
  274. // Rotate for bar rather than column chart
  275. if (($groupID == 0) && ($rotation == 'bar')) {
  276. $this->_graph->Set90AndMargin();
  277. }
  278. $grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
  279. $labelCount = count($this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
  280. if ($labelCount > 0) {
  281. $datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
  282. $datasetLabels = $this->_formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation);
  283. // Rotate for bar rather than column chart
  284. if ($rotation == 'bar') {
  285. $datasetLabels = array_reverse($datasetLabels);
  286. $this->_graph->yaxis->SetPos('max');
  287. $this->_graph->yaxis->SetLabelAlign('center','top');
  288. $this->_graph->yaxis->SetLabelSide(SIDE_RIGHT);
  289. }
  290. $this->_graph->xaxis->SetTickLabels($datasetLabels);
  291. }
  292. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  293. $seriesPlots = array();
  294. if ($grouping == 'percentStacked') {
  295. $sumValues = $this->_percentageSumCalculation($groupID,$seriesCount);
  296. }
  297. // Loop through each data series in turn
  298. for($j = 0; $j < $seriesCount; ++$j) {
  299. $dataValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues();
  300. if ($grouping == 'percentStacked') {
  301. $dataValues = $this->_percentageAdjustValues($dataValues,$sumValues);
  302. }
  303. // Fill in any missing values in the $dataValues array
  304. $testCurrentIndex = 0;
  305. foreach($dataValues as $k => $dataValue) {
  306. while($k != $testCurrentIndex) {
  307. $dataValues[$testCurrentIndex] = null;
  308. ++$testCurrentIndex;
  309. }
  310. ++$testCurrentIndex;
  311. }
  312. // Reverse the $dataValues order for bar rather than column chart
  313. if ($rotation == 'bar') {
  314. $dataValues = array_reverse($dataValues);
  315. }
  316. $seriesPlot = new BarPlot($dataValues);
  317. $seriesPlot->SetColor('black');
  318. $seriesPlot->SetFillColor(self::$_colourSet[self::$_plotColour++]);
  319. if ($dimensions == '3d') {
  320. $seriesPlot->SetShadow();
  321. }
  322. if (!$this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)) {
  323. $dataLabel = '';
  324. } else {
  325. $dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)->getDataValue();
  326. }
  327. $seriesPlot->SetLegend($dataLabel);
  328. $seriesPlots[] = $seriesPlot;
  329. }
  330. // Reverse the plot order for bar rather than column chart
  331. if (($rotation == 'bar') && (!($grouping == 'percentStacked'))) {
  332. $seriesPlots = array_reverse($seriesPlots);
  333. }
  334. if ($grouping == 'clustered') {
  335. $groupPlot = new GroupBarPlot($seriesPlots);
  336. } elseif ($grouping == 'standard') {
  337. $groupPlot = new GroupBarPlot($seriesPlots);
  338. } else {
  339. $groupPlot = new AccBarPlot($seriesPlots);
  340. if ($dimensions == '3d') {
  341. $groupPlot->SetShadow();
  342. }
  343. }
  344. $this->_graph->Add($groupPlot);
  345. } // function _renderPlotBar()
  346. private function _renderPlotScatter($groupID,$bubble) {
  347. $grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
  348. $scatterStyle = $bubbleSize = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
  349. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  350. $seriesPlots = array();
  351. // Loop through each data series in turn
  352. for($i = 0; $i < $seriesCount; ++$i) {
  353. $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
  354. $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  355. foreach($dataValuesY as $k => $dataValueY) {
  356. $dataValuesY[$k] = $k;
  357. }
  358. $seriesPlot = new ScatterPlot($dataValuesX,$dataValuesY);
  359. if ($scatterStyle == 'lineMarker') {
  360. $seriesPlot->SetLinkPoints();
  361. $seriesPlot->link->SetColor(self::$_colourSet[self::$_plotColour]);
  362. } elseif ($scatterStyle == 'smoothMarker') {
  363. $spline = new Spline($dataValuesY,$dataValuesX);
  364. list($splineDataY,$splineDataX) = $spline->Get(count($dataValuesX) * self::$_width / 20);
  365. $lplot = new LinePlot($splineDataX,$splineDataY);
  366. $lplot->SetColor(self::$_colourSet[self::$_plotColour]);
  367. $this->_graph->Add($lplot);
  368. }
  369. if ($bubble) {
  370. $this->_formatPointMarker($seriesPlot,'dot');
  371. $seriesPlot->mark->SetColor('black');
  372. $seriesPlot->mark->SetSize($bubbleSize);
  373. } else {
  374. $marker = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
  375. $this->_formatPointMarker($seriesPlot,$marker);
  376. }
  377. $dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
  378. $seriesPlot->SetLegend($dataLabel);
  379. $this->_graph->Add($seriesPlot);
  380. }
  381. } // function _renderPlotScatter()
  382. private function _renderPlotRadar($groupID) {
  383. $radarStyle = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
  384. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  385. $seriesPlots = array();
  386. // Loop through each data series in turn
  387. for($i = 0; $i < $seriesCount; ++$i) {
  388. $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
  389. $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  390. $marker = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
  391. $dataValues = array();
  392. foreach($dataValuesY as $k => $dataValueY) {
  393. $dataValues[$k] = implode(' ',array_reverse($dataValueY));
  394. }
  395. $tmp = array_shift($dataValues);
  396. $dataValues[] = $tmp;
  397. $tmp = array_shift($dataValuesX);
  398. $dataValuesX[] = $tmp;
  399. $this->_graph->SetTitles(array_reverse($dataValues));
  400. $seriesPlot = new RadarPlot(array_reverse($dataValuesX));
  401. $dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
  402. $seriesPlot->SetColor(self::$_colourSet[self::$_plotColour++]);
  403. if ($radarStyle == 'filled') {
  404. $seriesPlot->SetFillColor(self::$_colourSet[self::$_plotColour]);
  405. }
  406. $this->_formatPointMarker($seriesPlot,$marker);
  407. $seriesPlot->SetLegend($dataLabel);
  408. $this->_graph->Add($seriesPlot);
  409. }
  410. } // function _renderPlotRadar()
  411. private function _renderPlotContour($groupID) {
  412. $contourStyle = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
  413. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  414. $seriesPlots = array();
  415. $dataValues = array();
  416. // Loop through each data series in turn
  417. for($i = 0; $i < $seriesCount; ++$i) {
  418. $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
  419. $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  420. $dataValues[$i] = $dataValuesX;
  421. }
  422. $seriesPlot = new ContourPlot($dataValues);
  423. $this->_graph->Add($seriesPlot);
  424. } // function _renderPlotContour()
  425. private function _renderPlotStock($groupID) {
  426. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  427. $plotOrder = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder();
  428. $seriesPlots = array();
  429. $dataValues = array();
  430. // Loop through each data series in turn
  431. for($i = 0; $i < $seriesCount; ++$i) {
  432. $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
  433. $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  434. foreach($dataValuesX as $j => $dataValueX)
  435. $dataValues[$j][$plotOrder[$i]] = $dataValueX;
  436. }
  437. $seriesPlot = new StockPlot($dataValues);
  438. $this->_graph->Add($seriesPlot);
  439. } // function _renderPlotStock()
  440. private function _renderAreaChart($groupCount, $dimensions = '2d') {
  441. require_once('jpgraph_line.php');
  442. $this->_renderCartesianPlotArea();
  443. for($i = 0; $i < $groupCount; ++$i) {
  444. $this->_renderPlotLine($i,True,False,$dimensions);
  445. }
  446. } // function _renderAreaChart()
  447. private function _renderLineChart($groupCount, $dimensions = '2d') {
  448. require_once('jpgraph_line.php');
  449. $this->_renderCartesianPlotArea();
  450. for($i = 0; $i < $groupCount; ++$i) {
  451. $this->_renderPlotLine($i,False,False,$dimensions);
  452. }
  453. } // function _renderLineChart()
  454. private function _renderBarChart($groupCount, $dimensions = '2d') {
  455. require_once('jpgraph_bar.php');
  456. $this->_renderCartesianPlotArea();
  457. for($i = 0; $i < $groupCount; ++$i) {
  458. $this->_renderPlotBar($i,$dimensions);
  459. }
  460. } // function _renderBarChart()
  461. private function _renderScatterChart($groupCount) {
  462. require_once('jpgraph_scatter.php');
  463. require_once('jpgraph_regstat.php');
  464. require_once('jpgraph_line.php');
  465. $this->_renderCartesianPlotArea('linlin');
  466. for($i = 0; $i < $groupCount; ++$i) {
  467. $this->_renderPlotScatter($i,false);
  468. }
  469. } // function _renderScatterChart()
  470. private function _renderBubbleChart($groupCount) {
  471. require_once('jpgraph_scatter.php');
  472. $this->_renderCartesianPlotArea('linlin');
  473. for($i = 0; $i < $groupCount; ++$i) {
  474. $this->_renderPlotScatter($i,true);
  475. }
  476. } // function _renderBubbleChart()
  477. private function _renderPieChart($groupCount, $dimensions = '2d', $doughnut = False, $multiplePlots = False) {
  478. require_once('jpgraph_pie.php');
  479. if ($dimensions == '3d') {
  480. require_once('jpgraph_pie3d.php');
  481. }
  482. $this->_renderPiePlotArea($doughnut);
  483. $iLimit = ($multiplePlots) ? $groupCount : 1;
  484. for($groupID = 0; $groupID < $iLimit; ++$groupID) {
  485. $grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
  486. $exploded = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
  487. if ($groupID == 0) {
  488. $labelCount = count($this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
  489. if ($labelCount > 0) {
  490. $datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
  491. $datasetLabels = $this->_formatDataSetLabels($groupID, $datasetLabels, $labelCount);
  492. }
  493. }
  494. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  495. $seriesPlots = array();
  496. // For pie charts, we only display the first series: doughnut charts generally display all series
  497. $jLimit = ($multiplePlots) ? $seriesCount : 1;
  498. // Loop through each data series in turn
  499. for($j = 0; $j < $jLimit; ++$j) {
  500. $dataValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues();
  501. // Fill in any missing values in the $dataValues array
  502. $testCurrentIndex = 0;
  503. foreach($dataValues as $k => $dataValue) {
  504. while($k != $testCurrentIndex) {
  505. $dataValues[$testCurrentIndex] = null;
  506. ++$testCurrentIndex;
  507. }
  508. ++$testCurrentIndex;
  509. }
  510. if ($dimensions == '3d') {
  511. $seriesPlot = new PiePlot3D($dataValues);
  512. } else {
  513. if ($doughnut) {
  514. $seriesPlot = new PiePlotC($dataValues);
  515. } else {
  516. $seriesPlot = new PiePlot($dataValues);
  517. }
  518. }
  519. if ($multiplePlots) {
  520. $seriesPlot->SetSize(($jLimit-$j) / ($jLimit * 4));
  521. }
  522. if ($doughnut) {
  523. $seriesPlot->SetMidColor('white');
  524. }
  525. $seriesPlot->SetColor(self::$_colourSet[self::$_plotColour++]);
  526. if (count($datasetLabels) > 0)
  527. $seriesPlot->SetLabels(array_fill(0,count($datasetLabels),''));
  528. if ($dimensions != '3d') {
  529. $seriesPlot->SetGuideLines(false);
  530. }
  531. if ($j == 0) {
  532. if ($exploded) {
  533. $seriesPlot->ExplodeAll();
  534. }
  535. $seriesPlot->SetLegends($datasetLabels);
  536. }
  537. $this->_graph->Add($seriesPlot);
  538. }
  539. }
  540. } // function _renderPieChart()
  541. private function _renderRadarChart($groupCount) {
  542. require_once('jpgraph_radar.php');
  543. $this->_renderRadarPlotArea();
  544. for($groupID = 0; $groupID < $groupCount; ++$groupID) {
  545. $this->_renderPlotRadar($groupID);
  546. }
  547. } // function _renderRadarChart()
  548. private function _renderStockChart($groupCount) {
  549. require_once('jpgraph_stock.php');
  550. $this->_renderCartesianPlotArea();
  551. for($groupID = 0; $groupID < $groupCount; ++$i) {
  552. $this->_renderPlotStock($groupID);
  553. }
  554. } // function _renderStockChart()
  555. private function _renderContourChart($groupCount,$dimensions) {
  556. require_once('jpgraph_contour.php');
  557. $this->_renderCartesianPlotArea('intint');
  558. for($i = 0; $i < $groupCount; ++$i) {
  559. $this->_renderPlotContour($i);
  560. }
  561. } // function _renderContourChart()
  562. private function _renderCombinationChart($groupCount,$dimensions,$outputDestination) {
  563. require_once('jpgraph_line.php');
  564. require_once('jpgraph_bar.php');
  565. require_once('jpgraph_scatter.php');
  566. require_once('jpgraph_regstat.php');
  567. require_once('jpgraph_line.php');
  568. $this->_renderCartesianPlotArea();
  569. for($i = 0; $i < $groupCount; ++$i) {
  570. $dimensions = null;
  571. $chartType = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType();
  572. switch ($chartType) {
  573. case 'area3DChart' :
  574. $dimensions = '3d';
  575. case 'areaChart' :
  576. $this->_renderPlotLine($i,True,True,$dimensions);
  577. break;
  578. case 'bar3DChart' :
  579. $dimensions = '3d';
  580. case 'barChart' :
  581. $this->_renderPlotBar($i,$dimensions);
  582. break;
  583. case 'line3DChart' :
  584. $dimensions = '3d';
  585. case 'lineChart' :
  586. $this->_renderPlotLine($i,False,True,$dimensions);
  587. break;
  588. case 'scatterChart' :
  589. $this->_renderPlotScatter($i,false);
  590. break;
  591. case 'bubbleChart' :
  592. $this->_renderPlotScatter($i,true);
  593. break;
  594. default :
  595. $this->_graph = null;
  596. return false;
  597. }
  598. }
  599. $this->_renderLegend();
  600. $this->_graph->Stroke($outputDestination);
  601. return true;
  602. } // function _renderCombinationChart()
  603. public function render($outputDestination) {
  604. self::$_plotColour = 0;
  605. $groupCount = $this->_chart->getPlotArea()->getPlotGroupCount();
  606. $dimensions = null;
  607. if ($groupCount == 1) {
  608. $chartType = $this->_chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotType();
  609. } else {
  610. $chartTypes = array();
  611. for($i = 0; $i < $groupCount; ++$i) {
  612. $chartTypes[] = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType();
  613. }
  614. $chartTypes = array_unique($chartTypes);
  615. if (count($chartTypes) == 1) {
  616. $chartType = array_pop($chartTypes);
  617. } elseif (count($chartTypes) == 0) {
  618. echo 'Chart is not yet implemented<br />';
  619. return false;
  620. } else {
  621. return $this->_renderCombinationChart($groupCount,$dimensions,$outputDestination);
  622. }
  623. }
  624. switch ($chartType) {
  625. case 'area3DChart' :
  626. $dimensions = '3d';
  627. case 'areaChart' :
  628. $this->_renderAreaChart($groupCount,$dimensions);
  629. break;
  630. case 'bar3DChart' :
  631. $dimensions = '3d';
  632. case 'barChart' :
  633. $this->_renderBarChart($groupCount,$dimensions);
  634. break;
  635. case 'line3DChart' :
  636. $dimensions = '3d';
  637. case 'lineChart' :
  638. $this->_renderLineChart($groupCount,$dimensions);
  639. break;
  640. case 'pie3DChart' :
  641. $dimensions = '3d';
  642. case 'pieChart' :
  643. $this->_renderPieChart($groupCount,$dimensions,False,False);
  644. break;
  645. case 'doughnut3DChart' :
  646. $dimensions = '3d';
  647. case 'doughnutChart' :
  648. $this->_renderPieChart($groupCount,$dimensions,True,True);
  649. break;
  650. case 'scatterChart' :
  651. $this->_renderScatterChart($groupCount);
  652. break;
  653. case 'bubbleChart' :
  654. $this->_renderBubbleChart($groupCount);
  655. break;
  656. case 'radarChart' :
  657. $this->_renderRadarChart($groupCount);
  658. break;
  659. case 'surface3DChart' :
  660. $dimensions = '3d';
  661. case 'surfaceChart' :
  662. $this->_renderContourChart($groupCount,$dimensions);
  663. break;
  664. case 'stockChart' :
  665. $this->_renderStockChart($groupCount,$dimensions);
  666. break;
  667. default :
  668. echo $chartType.' is not yet implemented<br />';
  669. return false;
  670. }
  671. $this->_renderLegend();
  672. $this->_graph->Stroke($outputDestination);
  673. return true;
  674. } // function render()
  675. /**
  676. * Create a new PHPExcel_Chart_Renderer_jpgraph
  677. */
  678. public function __construct(PHPExcel_Chart $chart)
  679. {
  680. $this->_graph = null;
  681. $this->_chart = $chart;
  682. } // function __construct()
  683. } // PHPExcel_Chart_Renderer_jpgraph