1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
<?php
/**
* Piwik - free/libre analytics platform
*
* @link https://matomo.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\ImageGraph\StaticGraph;
use CpChart\Chart\Pie;
use Piwik\Plugins\ImageGraph\StaticGraph;
/**
*
*/
abstract class PieGraph extends StaticGraph
{
const RADIUS_MARGIN = 40;
const PIE_RIGHT_MARGIN = 20;
const SECTOR_GAP = 2.5;
const SLICE_COLOR_KEY = "SLICE_COLOR";
/**
* @var Pie
*/
protected $pieChart;
protected $xPosition;
protected $yPosition;
protected $pieConfig;
protected function getDefaultColors()
{
return array(
self::SLICE_COLOR_KEY . '1' => '3C5A69',
self::SLICE_COLOR_KEY . '2' => '679BB5',
self::SLICE_COLOR_KEY . '3' => '695A3C',
self::SLICE_COLOR_KEY . '4' => 'B58E67',
self::SLICE_COLOR_KEY . '5' => '8AA68A',
self::SLICE_COLOR_KEY . '6' => 'A4D2A6',
);
}
protected function initPieGraph($showLegend)
{
$this->truncateSmallValues();
$this->initpData();
$this->initpImage();
if ($this->height > $this->width) {
$radius = ($this->width / 2) - self::RADIUS_MARGIN;
} else {
$radius = ($this->height / 2) - self::RADIUS_MARGIN;
}
$this->pieChart = new Pie($this->pImage, $this->pData);
$numberOfSlices = count($this->abscissaSeries);
$numberOfAvailableColors = count($this->colors);
for ($i = 0; $i < $numberOfSlices; $i++) {
$this->pieChart->setSliceColor($i, $this->colors[self::SLICE_COLOR_KEY . (($i % $numberOfAvailableColors) + 1)]);
}
// max abscissa label width is used to set the pie right margin
list($abscissaMaxWidth, $abscissaMaxHeight) = $this->getMaximumTextWidthHeight($this->abscissaSeries);
$this->xPosition = $this->width - $radius - $abscissaMaxWidth - self::PIE_RIGHT_MARGIN;
$this->yPosition = $this->height / 2;
if ($showLegend) {
$this->pieChart->drawPieLegend(15, 40, array("Alpha" => 20));
}
$this->pieConfig =
array(
'Radius' => $radius,
'DrawLabels' => true,
'DataGapAngle' => self::SECTOR_GAP,
'DataGapRadius' => self::SECTOR_GAP,
);
}
/**
* this method logic is close to Piwik's core filter_truncate.
* it uses a threshold to determine if an abscissa value should be drawn on the PIE
* discarded abscissa values are summed in the 'other' abscissa value
*
* if this process is not perform, CpChart will draw pie slices that are too small to see
*/
private function truncateSmallValues()
{
$metricColumns = array_keys($this->ordinateSeries);
$metricColumn = $metricColumns[0];
$ordinateValuesSum = 0;
foreach ($this->ordinateSeries[$metricColumn] as $ordinateValue) {
$ordinateValuesSum += $ordinateValue;
}
$truncatedOrdinateSeries[$metricColumn] = array();
$truncatedAbscissaSeries = array();
$smallValuesSum = 0;
$ordinateValuesCount = count($this->ordinateSeries[$metricColumn]);
for ($i = 0; $i < $ordinateValuesCount - 1; $i++) {
$ordinateValue = $this->ordinateSeries[$metricColumn][$i];
if ($ordinateValue / $ordinateValuesSum > 0.01) {
$truncatedOrdinateSeries[$metricColumn][] = $ordinateValue;
$truncatedAbscissaSeries[] = $this->abscissaSeries[$i];
} else {
$smallValuesSum += $ordinateValue;
}
}
$smallValuesSum += $this->ordinateSeries[$metricColumn][$ordinateValuesCount - 1];
if (($smallValuesSum / $ordinateValuesSum) > 0.01) {
$truncatedOrdinateSeries[$metricColumn][] = $smallValuesSum;
$truncatedAbscissaSeries[] = end($this->abscissaSeries);
}
$this->ordinateSeries = $truncatedOrdinateSeries;
$this->abscissaSeries = $truncatedAbscissaSeries;
}
}
|