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