PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Classes/PHPExcel/Chart/Renderer/jpgraph.php

#
PHP | 831 lines | 614 code | 153 blank | 64 comment | 123 complexity | 6f6bbf350b95d53b62ee60d3777687d6 MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0
  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2012 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
  23. * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version ##VERSION##, ##DATE##
  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 - 2012 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,$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. // Fill in any missing values in the $datasetLabels array
  92. while ($i != $testCurrentIndex) {
  93. $datasetLabels[$testCurrentIndex] = '';
  94. ++$testCurrentIndex;
  95. }
  96. if (is_array($datasetLabel)) {
  97. if ($rotation == 'bar') {
  98. $datasetLabel = array_reverse($datasetLabel);
  99. $datasetLabels[$i] = implode(" ",$datasetLabel);
  100. } else {
  101. $datasetLabels[$i] = implode("\n",$datasetLabel);
  102. }
  103. } else {
  104. // Format labels according to any formatting code
  105. if (!is_null($datasetLabelFormatCode)) {
  106. $datasetLabels[$i] = PHPExcel_Style_NumberFormat::toFormattedString($datasetLabel,$datasetLabelFormatCode);
  107. }
  108. }
  109. ++$testCurrentIndex;
  110. }
  111. return $datasetLabels;
  112. } // function _formatDataSetLabels()
  113. private function _percentageSumCalculation($groupID,$seriesCount) {
  114. // Adjust our values to a percentage value across all series in the group
  115. for($i = 0; $i < $seriesCount; ++$i) {
  116. if ($i == 0) {
  117. $sumValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  118. } else {
  119. $nextValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  120. foreach($nextValues as $k => $value) {
  121. if (isset($sumValues[$k])) {
  122. $sumValues[$k] += $value;
  123. } else {
  124. $sumValues[$k] = $value;
  125. }
  126. }
  127. }
  128. }
  129. return $sumValues;
  130. } // function _percentageSumCalculation()
  131. private function _percentageAdjustValues($dataValues,$sumValues) {
  132. foreach($dataValues as $k => $dataValue) {
  133. $dataValues[$k] = $dataValue / $sumValues[$k] * 100;
  134. }
  135. return $dataValues;
  136. } // function _percentageAdjustValues()
  137. private function _getCaption($captionElement) {
  138. // Read any caption
  139. $caption = (!is_null($captionElement)) ? $captionElement->getCaption() : NULL;
  140. // Test if we have a title caption to display
  141. if (!is_null($caption)) {
  142. // If we do, it could be a plain string or an array
  143. if (is_array($caption)) {
  144. // Implode an array to a plain string
  145. $caption = implode('',$caption);
  146. }
  147. }
  148. return $caption;
  149. } // function _getCaption()
  150. private function _renderTitle() {
  151. $title = $this->_getCaption($this->_chart->getTitle());
  152. if (!is_null($title)) {
  153. $this->_graph->title->Set($title);
  154. }
  155. } // function _renderTitle()
  156. private function _renderLegend() {
  157. $legend = $this->_chart->getLegend();
  158. if (!is_null($legend)) {
  159. $legendPosition = $legend->getPosition();
  160. $legendOverlay = $legend->getOverlay();
  161. switch ($legendPosition) {
  162. case 'r' :
  163. $this->_graph->legend->SetPos(0.01,0.5,'right','center'); // right
  164. break;
  165. case 'l' :
  166. $this->_graph->legend->SetPos(0.01,0.5,'left','center'); // left
  167. break;
  168. case 't' :
  169. $this->_graph->legend->SetPos(0.5,0.01,'center','top'); // top
  170. break;
  171. case 'b' :
  172. $this->_graph->legend->SetPos(0.5,0.99,'center','bottom'); // bottom
  173. break;
  174. default :
  175. $this->_graph->legend->SetPos(0.01,0.01,'right','top'); // top-right
  176. break;
  177. }
  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. $datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
  223. if (count($datasetLabels) > 0) {
  224. $datasetLabels = $this->_formatDataSetLabels($groupID,$datasetLabels);
  225. $this->_graph->xaxis->SetTickLabels($datasetLabels);
  226. }
  227. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  228. $seriesPlots = array();
  229. if ($grouping == 'percentStacked') {
  230. $sumValues = $this->_percentageSumCalculation($groupID,$seriesCount);
  231. }
  232. // Loop through each data series in turn
  233. for($i = 0; $i < $seriesCount; ++$i) {
  234. $dataValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  235. $marker = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
  236. if ($grouping == 'percentStacked') {
  237. $dataValues = $this->_percentageAdjustValues($dataValues,$sumValues);
  238. }
  239. // Fill in any missing values in the $dataValues array
  240. $testCurrentIndex = 0;
  241. foreach($dataValues as $k => $dataValue) {
  242. while($k != $testCurrentIndex) {
  243. $dataValues[$testCurrentIndex] = null;
  244. ++$testCurrentIndex;
  245. }
  246. ++$testCurrentIndex;
  247. }
  248. $seriesPlot = new LinePlot($dataValues);
  249. if ($combination) {
  250. $seriesPlot->SetBarCenter();
  251. }
  252. if ($filled) {
  253. $seriesPlot->SetFilled(true);
  254. $seriesPlot->SetColor('black');
  255. $seriesPlot->SetFillColor(self::$_colourSet[self::$_plotColour++]);
  256. } else {
  257. // Set the appropriate plot marker
  258. $this->_formatPointMarker($seriesPlot,$marker);
  259. }
  260. $dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
  261. $seriesPlot->SetLegend($dataLabel);
  262. $seriesPlots[] = $seriesPlot;
  263. }
  264. if ($grouping == 'standard') {
  265. $groupPlot = $seriesPlots;
  266. } else {
  267. $groupPlot = new AccLinePlot($seriesPlots);
  268. }
  269. $this->_graph->Add($groupPlot);
  270. } // function _renderPlotLine()
  271. private function _renderPlotBar($groupID, $dimensions = '2d') {
  272. $rotation = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotDirection();
  273. // Rotate for bar rather than column chart
  274. if (($groupID == 0) && ($rotation == 'bar')) {
  275. $this->_graph->Set90AndMargin();
  276. }
  277. $grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
  278. $datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
  279. if (count($datasetLabels) > 0) {
  280. $datasetLabels = $this->_formatDataSetLabels($groupID,$datasetLabels,$rotation);
  281. // Rotate for bar rather than column chart
  282. if ($rotation == 'bar') {
  283. $datasetLabels = array_reverse($datasetLabels);
  284. $this->_graph->yaxis->SetPos('max');
  285. $this->_graph->yaxis->SetLabelAlign('center','top');
  286. $this->_graph->yaxis->SetLabelSide(SIDE_RIGHT);
  287. }
  288. $this->_graph->xaxis->SetTickLabels($datasetLabels);
  289. }
  290. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  291. $seriesPlots = array();
  292. if ($grouping == 'percentStacked') {
  293. $sumValues = $this->_percentageSumCalculation($groupID,$seriesCount);
  294. }
  295. // Loop through each data series in turn
  296. for($j = 0; $j < $seriesCount; ++$j) {
  297. $dataValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues();
  298. if ($grouping == 'percentStacked') {
  299. $dataValues = $this->_percentageAdjustValues($dataValues,$sumValues);
  300. }
  301. // Fill in any missing values in the $dataValues array
  302. $testCurrentIndex = 0;
  303. foreach($dataValues as $k => $dataValue) {
  304. while($k != $testCurrentIndex) {
  305. $dataValues[$testCurrentIndex] = null;
  306. ++$testCurrentIndex;
  307. }
  308. ++$testCurrentIndex;
  309. }
  310. // Reverse the $dataValues order for bar rather than column chart
  311. if ($rotation == 'bar') {
  312. $dataValues = array_reverse($dataValues);
  313. }
  314. $seriesPlot = new BarPlot($dataValues);
  315. $seriesPlot->SetColor('black');
  316. $seriesPlot->SetFillColor(self::$_colourSet[self::$_plotColour++]);
  317. if ($dimensions == '3d') {
  318. $seriesPlot->SetShadow();
  319. }
  320. if (!$this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)) {
  321. $dataLabel = '';
  322. } else {
  323. $dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)->getDataValue();
  324. }
  325. $seriesPlot->SetLegend($dataLabel);
  326. $seriesPlots[] = $seriesPlot;
  327. }
  328. // Reverse the plot order for bar rather than column chart
  329. if (($rotation == 'bar') && (!($grouping == 'percentStacked'))) {
  330. $seriesPlots = array_reverse($seriesPlots);
  331. }
  332. if ($grouping == 'clustered') {
  333. $groupPlot = new GroupBarPlot($seriesPlots);
  334. } elseif ($grouping == 'standard') {
  335. $groupPlot = new GroupBarPlot($seriesPlots);
  336. } else {
  337. $groupPlot = new AccBarPlot($seriesPlots);
  338. if ($dimensions == '3d') {
  339. $groupPlot->SetShadow();
  340. }
  341. }
  342. $this->_graph->Add($groupPlot);
  343. } // function _renderPlotBar()
  344. private function _renderPlotScatter($groupID,$bubble) {
  345. $grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
  346. $scatterStyle = $bubbleSize = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
  347. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  348. $seriesPlots = array();
  349. // Loop through each data series in turn
  350. for($i = 0; $i < $seriesCount; ++$i) {
  351. $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
  352. $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  353. foreach($dataValuesY as $k => $dataValueY) {
  354. $dataValuesY[$k] = $k;
  355. }
  356. $seriesPlot = new ScatterPlot($dataValuesX,$dataValuesY);
  357. if ($scatterStyle == 'lineMarker') {
  358. $seriesPlot->SetLinkPoints();
  359. $seriesPlot->link->SetColor(self::$_colourSet[self::$_plotColour]);
  360. } elseif ($scatterStyle == 'smoothMarker') {
  361. $spline = new Spline($dataValuesY,$dataValuesX);
  362. list($splineDataY,$splineDataX) = $spline->Get(count($dataValuesX) * self::$_width / 20);
  363. $lplot = new LinePlot($splineDataX,$splineDataY);
  364. $lplot->SetColor(self::$_colourSet[self::$_plotColour]);
  365. $this->_graph->Add($lplot);
  366. }
  367. if ($bubble) {
  368. $this->_formatPointMarker($seriesPlot,'dot');
  369. $seriesPlot->mark->SetColor('black');
  370. $seriesPlot->mark->SetSize($bubbleSize);
  371. } else {
  372. $marker = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
  373. $this->_formatPointMarker($seriesPlot,$marker);
  374. }
  375. $dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
  376. $seriesPlot->SetLegend($dataLabel);
  377. $this->_graph->Add($seriesPlot);
  378. }
  379. } // function _renderPlotScatter()
  380. private function _renderPlotRadar($groupID) {
  381. $radarStyle = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
  382. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  383. $seriesPlots = array();
  384. // Loop through each data series in turn
  385. for($i = 0; $i < $seriesCount; ++$i) {
  386. $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
  387. $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  388. $marker = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
  389. $dataValues = array();
  390. foreach($dataValuesY as $k => $dataValueY) {
  391. $dataValues[$k] = implode(' ',array_reverse($dataValueY));
  392. }
  393. $tmp = array_shift($dataValues);
  394. $dataValues[] = $tmp;
  395. $tmp = array_shift($dataValuesX);
  396. $dataValuesX[] = $tmp;
  397. $this->_graph->SetTitles(array_reverse($dataValues));
  398. $seriesPlot = new RadarPlot(array_reverse($dataValuesX));
  399. $dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
  400. $seriesPlot->SetColor(self::$_colourSet[self::$_plotColour++]);
  401. if ($radarStyle == 'filled') {
  402. $seriesPlot->SetFillColor(self::$_colourSet[self::$_plotColour]);
  403. }
  404. $this->_formatPointMarker($seriesPlot,$marker);
  405. $seriesPlot->SetLegend($dataLabel);
  406. $this->_graph->Add($seriesPlot);
  407. }
  408. } // function _renderPlotRadar()
  409. private function _renderPlotContour($groupID) {
  410. $contourStyle = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
  411. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  412. $seriesPlots = array();
  413. $dataValues = array();
  414. // Loop through each data series in turn
  415. for($i = 0; $i < $seriesCount; ++$i) {
  416. $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
  417. $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  418. $dataValues[$i] = $dataValuesX;
  419. }
  420. $seriesPlot = new ContourPlot($dataValues);
  421. $this->_graph->Add($seriesPlot);
  422. } // function _renderPlotContour()
  423. private function _renderPlotStock($groupID) {
  424. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
  425. $plotOrder = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder();
  426. $seriesPlots = array();
  427. $dataValues = array();
  428. // Loop through each data series in turn
  429. for($i = 0; $i < $seriesCount; ++$i) {
  430. $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
  431. $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
  432. foreach($dataValuesX as $j => $dataValueX)
  433. $dataValues[$j][$plotOrder[$i]] = $dataValueX;
  434. }
  435. $seriesPlot = new StockPlot($dataValues);
  436. $this->_graph->Add($seriesPlot);
  437. } // function _renderPlotStock()
  438. private function _renderAreaChart($groupCount, $dimensions = '2d') {
  439. require_once('jpgraph_line.php');
  440. $this->_renderCartesianPlotArea();
  441. for($i = 0; $i < $groupCount; ++$i) {
  442. $this->_renderPlotLine($i,True,False,$dimensions);
  443. }
  444. } // function _renderAreaChart()
  445. private function _renderLineChart($groupCount, $dimensions = '2d') {
  446. require_once('jpgraph_line.php');
  447. $this->_renderCartesianPlotArea();
  448. for($i = 0; $i < $groupCount; ++$i) {
  449. $this->_renderPlotLine($i,False,False,$dimensions);
  450. }
  451. } // function _renderLineChart()
  452. private function _renderBarChart($groupCount, $dimensions = '2d') {
  453. require_once('jpgraph_bar.php');
  454. $this->_renderCartesianPlotArea();
  455. for($i = 0; $i < $groupCount; ++$i) {
  456. $this->_renderPlotBar($i,$dimensions);
  457. }
  458. } // function _renderBarChart()
  459. private function _renderScatterChart($groupCount) {
  460. require_once('jpgraph_scatter.php');
  461. require_once('jpgraph_regstat.php');
  462. require_once('jpgraph_line.php');
  463. $this->_renderCartesianPlotArea('linlin');
  464. for($i = 0; $i < $groupCount; ++$i) {
  465. $this->_renderPlotScatter($i,false);
  466. }
  467. } // function _renderScatterChart()
  468. private function _renderBubbleChart($groupCount) {
  469. require_once('jpgraph_scatter.php');
  470. $this->_renderCartesianPlotArea('linlin');
  471. for($i = 0; $i < $groupCount; ++$i) {
  472. $this->_renderPlotScatter($i,true);
  473. }
  474. } // function _renderBubbleChart()
  475. private function _renderPieChart($groupCount, $dimensions = '2d', $doughnut = False, $multiplePlots = False) {
  476. require_once('jpgraph_pie.php');
  477. if ($dimensions == '3d') {
  478. require_once('jpgraph_pie3d.php');
  479. }
  480. $this->_renderPiePlotArea($doughnut);
  481. $iLimit = ($multiplePlots) ? $groupCount : 1;
  482. for($i = 0; $i < $iLimit; ++$i) {
  483. $grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotGrouping();
  484. $exploded = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotStyle();
  485. if ($i == 0) {
  486. $datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotCategoryByIndex(0)->getDataValues();
  487. if (count($datasetLabels) > 0) {
  488. $datasetLabels = $this->_formatDataSetLabels($i,$datasetLabels);
  489. }
  490. }
  491. $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotSeriesCount();
  492. $seriesPlots = array();
  493. // For pie charts, we only display the first series: doughnut charts generally display all series
  494. $jLimit = ($multiplePlots) ? $seriesCount : 1;
  495. // Loop through each data series in turn
  496. for($j = 0; $j < $jLimit; ++$j) {
  497. $dataValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotValuesByIndex($j)->getDataValues();
  498. // Fill in any missing values in the $dataValues array
  499. $testCurrentIndex = 0;
  500. foreach($dataValues as $k => $dataValue) {
  501. while($k != $testCurrentIndex) {
  502. $dataValues[$testCurrentIndex] = null;
  503. ++$testCurrentIndex;
  504. }
  505. ++$testCurrentIndex;
  506. }
  507. if ($dimensions == '3d') {
  508. $seriesPlot = new PiePlot3D($dataValues);
  509. } else {
  510. if ($doughnut) {
  511. $seriesPlot = new PiePlotC($dataValues);
  512. } else {
  513. $seriesPlot = new PiePlot($dataValues);
  514. }
  515. }
  516. if ($multiplePlots) {
  517. $seriesPlot->SetSize(($jLimit-$j) / ($jLimit * 4));
  518. }
  519. if ($doughnut) {
  520. $seriesPlot->SetMidColor('white');
  521. }
  522. $seriesPlot->SetColor(self::$_colourSet[self::$_plotColour++]);
  523. $seriesPlot->SetLabels(array_fill(0,count($datasetLabels),''));
  524. if ($dimensions != '3d') {
  525. $seriesPlot->SetGuideLines(false);
  526. }
  527. if ($j == 0) {
  528. if ($exploded) {
  529. $seriesPlot->ExplodeAll();
  530. }
  531. $seriesPlot->SetLegends($datasetLabels);
  532. }
  533. $this->_graph->Add($seriesPlot);
  534. }
  535. }
  536. } // function _renderPieChart()
  537. private function _renderRadarChart($groupCount) {
  538. require_once('jpgraph_radar.php');
  539. $this->_renderRadarPlotArea();
  540. for($i = 0; $i < $groupCount; ++$i) {
  541. $this->_renderPlotRadar($i);
  542. }
  543. } // function _renderRadarChart()
  544. private function _renderStockChart($groupCount) {
  545. require_once('jpgraph_stock.php');
  546. $this->_renderCartesianPlotArea();
  547. for($i = 0; $i < $groupCount; ++$i) {
  548. $this->_renderPlotStock($i);
  549. }
  550. } // function _renderStockChart()
  551. private function _renderContourChart($groupCount,$dimensions) {
  552. require_once('jpgraph_contour.php');
  553. $this->_renderCartesianPlotArea('intint');
  554. for($i = 0; $i < $groupCount; ++$i) {
  555. $this->_renderPlotContour($i);
  556. }
  557. } // function _renderContourChart()
  558. private function _renderCombinationChart($groupCount,$dimensions,$outputDestination) {
  559. require_once('jpgraph_line.php');
  560. require_once('jpgraph_bar.php');
  561. require_once('jpgraph_scatter.php');
  562. require_once('jpgraph_regstat.php');
  563. require_once('jpgraph_line.php');
  564. $this->_renderCartesianPlotArea();
  565. for($i = 0; $i < $groupCount; ++$i) {
  566. $dimensions = null;
  567. $chartType = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType();
  568. switch ($chartType) {
  569. case 'area3DChart' :
  570. $dimensions = '3d';
  571. case 'areaChart' :
  572. $this->_renderPlotLine($i,True,True,$dimensions);
  573. break;
  574. case 'bar3DChart' :
  575. $dimensions = '3d';
  576. case 'barChart' :
  577. $this->_renderPlotBar($i,$dimensions);
  578. break;
  579. case 'line3DChart' :
  580. $dimensions = '3d';
  581. case 'lineChart' :
  582. $this->_renderPlotLine($i,False,True,$dimensions);
  583. break;
  584. case 'scatterChart' :
  585. $this->_renderPlotScatter($i,false);
  586. break;
  587. case 'bubbleChart' :
  588. $this->_renderPlotScatter($i,true);
  589. break;
  590. default :
  591. $this->_graph = null;
  592. return false;
  593. }
  594. }
  595. $this->_renderLegend();
  596. $this->_graph->Stroke($outputDestination);
  597. return true;
  598. } // function _renderCombinationChart()
  599. public function render($outputDestination) {
  600. $groupCount = $this->_chart->getPlotArea()->getPlotGroupCount();
  601. $dimensions = null;
  602. if ($groupCount == 1) {
  603. $chartType = $this->_chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotType();
  604. } else {
  605. $chartTypes = array();
  606. for($i = 0; $i < $groupCount; ++$i) {
  607. $chartTypes[] = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType();
  608. }
  609. $chartTypes = array_unique($chartTypes);
  610. if (count($chartTypes) == 1) {
  611. $chartType = array_pop($chartTypes);
  612. } elseif (count($chartTypes) == 0) {
  613. echo 'Chart is not yet implemented<br />';
  614. return false;
  615. } else {
  616. return $this->_renderCombinationChart($groupCount,$dimensions,$outputDestination);
  617. }
  618. }
  619. switch ($chartType) {
  620. case 'area3DChart' :
  621. $dimensions = '3d';
  622. case 'areaChart' :
  623. $this->_renderAreaChart($groupCount,$dimensions);
  624. break;
  625. case 'bar3DChart' :
  626. $dimensions = '3d';
  627. case 'barChart' :
  628. $this->_renderBarChart($groupCount,$dimensions);
  629. break;
  630. case 'line3DChart' :
  631. $dimensions = '3d';
  632. case 'lineChart' :
  633. $this->_renderLineChart($groupCount,$dimensions);
  634. break;
  635. case 'pie3DChart' :
  636. $dimensions = '3d';
  637. case 'pieChart' :
  638. $this->_renderPieChart($groupCount,$dimensions,False,False);
  639. break;
  640. case 'doughnut3DChart' :
  641. $dimensions = '3d';
  642. case 'doughnutChart' :
  643. $this->_renderPieChart($groupCount,$dimensions,True,True);
  644. break;
  645. case 'scatterChart' :
  646. $this->_renderScatterChart($groupCount);
  647. break;
  648. case 'bubbleChart' :
  649. $this->_renderBubbleChart($groupCount);
  650. break;
  651. case 'radarChart' :
  652. $this->_renderRadarChart($groupCount);
  653. break;
  654. case 'surface3DChart' :
  655. $dimensions = '3d';
  656. case 'surfaceChart' :
  657. $this->_renderContourChart($groupCount,$dimensions);
  658. break;
  659. case 'stockChart' :
  660. $this->_renderStockChart($groupCount,$dimensions);
  661. break;
  662. default :
  663. echo $chartType.' is not yet implemented<br />';
  664. return false;
  665. }
  666. $this->_renderLegend();
  667. $this->_graph->Stroke($outputDestination);
  668. return true;
  669. } // function render()
  670. /**
  671. * Create a new PHPExcel_Chart_Renderer_jpgraph
  672. */
  673. public function __construct(PHPExcel_Chart $chart)
  674. {
  675. $this->_graph = null;
  676. $this->_chart = $chart;
  677. } // function __construct()
  678. } // PHPExcel_Chart_Renderer_jpgraph