PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.12.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.12.1
5.12.1 5.12.0 5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / vendor / szymach / c-pchart / src / Chart / Radar.php
matomo / app / vendor / szymach / c-pchart / src / Chart Last commit date
Bubble.php 1 year ago Indicator.php 1 year ago Pie.php 1 year ago Radar.php 1 year ago Scatter.php 1 year ago Split.php 1 year ago Spring.php 1 year ago Stock.php 1 year ago Surface.php 1 year ago
Radar.php
617 lines
1 <?php
2
3 namespace CpChart\Chart;
4
5 use CpChart\Data;
6 use CpChart\Image;
7 /**
8 * Radar - class to draw radar charts
9 *
10 * Version : 2.1.4
11 * Made by : Jean-Damien POGOLOTTI
12 * Last Update : 19/01/2014
13 *
14 * This file can be distributed under the license you can find at :
15 *
16 * http://www.pchart.net/license
17 *
18 * You can find the whole class documentation on the pChart web site.
19 */
20 class Radar
21 {
22 /**
23 * @var Image
24 */
25 public $pChartObject;
26 /**
27 * Draw a radar chart
28 * @param Image $Object
29 * @param Data $Values
30 * @param array $Format
31 */
32 public function drawRadar(Image $Object, Data $Values, array $Format = [])
33 {
34 $this->pChartObject = $Object;
35 $FixedMax = isset($Format["FixedMax"]) ? $Format["FixedMax"] : VOID;
36 $AxisR = isset($Format["AxisR"]) ? $Format["AxisR"] : 60;
37 $AxisG = isset($Format["AxisG"]) ? $Format["AxisG"] : 60;
38 $AxisB = isset($Format["AxisB"]) ? $Format["AxisB"] : 60;
39 $AxisAlpha = isset($Format["AxisAlpha"]) ? $Format["AxisAlpha"] : 50;
40 $AxisRotation = isset($Format["AxisRotation"]) ? $Format["AxisRotation"] : 0;
41 $DrawTicks = isset($Format["DrawTicks"]) ? $Format["DrawTicks"] : \true;
42 $TicksLength = isset($Format["TicksLength"]) ? $Format["TicksLength"] : 2;
43 $DrawAxisValues = isset($Format["DrawAxisValues"]) ? $Format["DrawAxisValues"] : \true;
44 $AxisBoxRounded = isset($Format["AxisBoxRounded"]) ? $Format["AxisBoxRounded"] : \true;
45 $AxisFontName = isset($Format["AxisFontName"]) ? $Format["AxisFontName"] : $this->pChartObject->FontName;
46 $AxisFontSize = isset($Format["AxisFontSize"]) ? $Format["AxisFontSize"] : $this->pChartObject->FontSize;
47 $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : \false;
48 $WriteValuesInBubble = isset($Format["WriteValuesInBubble"]) ? $Format["WriteValuesInBubble"] : \true;
49 $ValueFontName = isset($Format["ValueFontName"]) ? $Format["ValueFontName"] : $this->pChartObject->FontName;
50 $ValueFontSize = isset($Format["ValueFontSize"]) ? $Format["ValueFontSize"] : $this->pChartObject->FontSize;
51 $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 4;
52 $OuterBubbleRadius = isset($Format["OuterBubbleRadius"]) ? $Format["OuterBubbleRadius"] : 2;
53 $OuterBubbleR = isset($Format["OuterBubbleR"]) ? $Format["OuterBubbleR"] : VOID;
54 $OuterBubbleG = isset($Format["OuterBubbleG"]) ? $Format["OuterBubbleG"] : VOID;
55 $OuterBubbleB = isset($Format["OuterBubbleB"]) ? $Format["OuterBubbleB"] : VOID;
56 $OuterBubbleAlpha = isset($Format["OuterBubbleAlpha"]) ? $Format["OuterBubbleAlpha"] : 100;
57 $InnerBubbleR = isset($Format["InnerBubbleR"]) ? $Format["InnerBubbleR"] : 255;
58 $InnerBubbleG = isset($Format["InnerBubbleG"]) ? $Format["InnerBubbleG"] : 255;
59 $InnerBubbleB = isset($Format["InnerBubbleB"]) ? $Format["InnerBubbleB"] : 255;
60 $InnerBubbleAlpha = isset($Format["InnerBubbleAlpha"]) ? $Format["InnerBubbleAlpha"] : 100;
61 $DrawBackground = isset($Format["DrawBackground"]) ? $Format["DrawBackground"] : \true;
62 $BackgroundR = isset($Format["BackgroundR"]) ? $Format["BackgroundR"] : 255;
63 $BackgroundG = isset($Format["BackgroundG"]) ? $Format["BackgroundG"] : 255;
64 $BackgroundB = isset($Format["BackgroundB"]) ? $Format["BackgroundB"] : 255;
65 $BackgroundAlpha = isset($Format["BackgroundAlpha"]) ? $Format["BackgroundAlpha"] : 50;
66 $BackgroundGradient = isset($Format["BackgroundGradient"]) ? $Format["BackgroundGradient"] : null;
67 $Layout = isset($Format["Layout"]) ? $Format["Layout"] : RADAR_LAYOUT_STAR;
68 $SegmentHeight = isset($Format["SegmentHeight"]) ? $Format["SegmentHeight"] : SEGMENT_HEIGHT_AUTO;
69 $Segments = isset($Format["Segments"]) ? $Format["Segments"] : 4;
70 $WriteLabels = isset($Format["WriteLabels"]) ? $Format["WriteLabels"] : \true;
71 $SkipLabels = isset($Format["SkipLabels"]) ? $Format["SkipLabels"] : 1;
72 $LabelMiddle = isset($Format["LabelMiddle"]) ? $Format["LabelMiddle"] : \false;
73 $LabelsBackground = isset($Format["LabelsBackground"]) ? $Format["LabelsBackground"] : \true;
74 $LabelsBGR = isset($Format["LabelsBGR"]) ? $Format["LabelsBGR"] : 255;
75 $LabelsBGG = isset($Format["LabelsBGR"]) ? $Format["LabelsBGG"] : 255;
76 $LabelsBGB = isset($Format["LabelsBGR"]) ? $Format["LabelsBGB"] : 255;
77 $LabelsBGAlpha = isset($Format["LabelsBGAlpha"]) ? $Format["LabelsBGAlpha"] : 50;
78 $LabelPos = isset($Format["LabelPos"]) ? $Format["LabelPos"] : RADAR_LABELS_ROTATED;
79 $LabelPadding = isset($Format["LabelPadding"]) ? $Format["LabelPadding"] : 4;
80 $DrawPoints = isset($Format["DrawPoints"]) ? $Format["DrawPoints"] : \true;
81 $PointRadius = isset($Format["PointRadius"]) ? $Format["PointRadius"] : 4;
82 $PointSurrounding = isset($Format["PointRadius"]) ? $Format["PointRadius"] : -30;
83 $DrawLines = isset($Format["DrawLines"]) ? $Format["DrawLines"] : \true;
84 $LineLoopStart = isset($Format["LineLoopStart"]) ? $Format["LineLoopStart"] : \true;
85 $DrawPoly = isset($Format["DrawPoly"]) ? $Format["DrawPoly"] : \false;
86 $PolyAlpha = isset($Format["PolyAlpha"]) ? $Format["PolyAlpha"] : 40;
87 $FontSize = $Object->FontSize;
88 $X1 = $Object->GraphAreaX1;
89 $Y1 = $Object->GraphAreaY1;
90 $X2 = $Object->GraphAreaX2;
91 $Y2 = $Object->GraphAreaY2;
92 $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : \false;
93 /* Cancel default tick length if ticks not enabled */
94 if ($DrawTicks == \false) {
95 $TicksLength = 0;
96 }
97 /* Data Processing */
98 $Data = $Values->getData();
99 $Palette = $Values->getPalette();
100 /* Catch the number of required axis */
101 $LabelSerie = $Data["Abscissa"];
102 if ($LabelSerie) {
103 $Points = count($Data["Series"][$LabelSerie]["Data"]);
104 } else {
105 $Points = 0;
106 foreach ($Data["Series"] as $SerieName => $DataArray) {
107 if (count($DataArray["Data"]) > $Points) {
108 $Points = count($DataArray["Data"]);
109 }
110 }
111 }
112 /* Draw the axis */
113 $CenterX = ($X2 - $X1) / 2 + $X1;
114 $CenterY = ($Y2 - $Y1) / 2 + $Y1;
115 $EdgeHeight = min(($X2 - $X1) / 2, ($Y2 - $Y1) / 2);
116 if ($WriteLabels) {
117 $EdgeHeight = $EdgeHeight - $FontSize - $LabelPadding - $TicksLength;
118 }
119 /* Determine the scale if set to automatic */
120 if ($SegmentHeight == SEGMENT_HEIGHT_AUTO) {
121 if ($FixedMax != VOID) {
122 $Max = $FixedMax;
123 } else {
124 $Max = 0;
125 foreach ($Data["Series"] as $SerieName => $DataArray) {
126 if ($SerieName != $LabelSerie) {
127 if (max($DataArray["Data"]) > $Max) {
128 $Max = max($DataArray["Data"]);
129 }
130 }
131 }
132 }
133 $MaxSegments = $EdgeHeight / 20;
134 $Scale = $Object->computeScale(0, $Max, $MaxSegments, [1, 2, 5]);
135 $Segments = $Scale["Rows"];
136 $SegmentHeight = $Scale["RowHeight"];
137 }
138 if ($LabelMiddle && $SkipLabels == 1) {
139 $Axisoffset = 360 / $Points / 2;
140 } elseif ($LabelMiddle && $SkipLabels != 1) {
141 $Axisoffset = 360 / ($Points / $SkipLabels) / 2;
142 } elseif (!$LabelMiddle) {
143 $Axisoffset = 0;
144 }
145 /* Background processing */
146 if ($DrawBackground) {
147 $RestoreShadow = $Object->Shadow;
148 $Object->Shadow = \false;
149 if ($BackgroundGradient == null) {
150 if ($Layout == RADAR_LAYOUT_STAR) {
151 $Color = ["R" => $BackgroundR, "G" => $BackgroundG, "B" => $BackgroundB, "Alpha" => $BackgroundAlpha];
152 $PointArray = [];
153 for ($i = 0; $i <= 360; $i = $i + 360 / $Points) {
154 $PointArray[] = cos(deg2rad($i + $AxisRotation)) * $EdgeHeight + $CenterX;
155 $PointArray[] = sin(deg2rad($i + $AxisRotation)) * $EdgeHeight + $CenterY;
156 }
157 $Object->drawPolygon($PointArray, $Color);
158 } elseif ($Layout == RADAR_LAYOUT_CIRCLE) {
159 $Color = ["R" => $BackgroundR, "G" => $BackgroundG, "B" => $BackgroundB, "Alpha" => $BackgroundAlpha];
160 $Object->drawFilledCircle($CenterX, $CenterY, $EdgeHeight, $Color);
161 }
162 } else {
163 $GradientROffset = ($BackgroundGradient["EndR"] - $BackgroundGradient["StartR"]) / $Segments;
164 $GradientGOffset = ($BackgroundGradient["EndG"] - $BackgroundGradient["StartG"]) / $Segments;
165 $GradientBOffset = ($BackgroundGradient["EndB"] - $BackgroundGradient["StartB"]) / $Segments;
166 $GradientAlphaOffset = ($BackgroundGradient["EndAlpha"] - $BackgroundGradient["StartAlpha"]) / $Segments;
167 if ($Layout == RADAR_LAYOUT_STAR) {
168 for ($j = $Segments; $j >= 1; $j--) {
169 $Color = ["R" => $BackgroundGradient["StartR"] + $GradientROffset * $j, "G" => $BackgroundGradient["StartG"] + $GradientGOffset * $j, "B" => $BackgroundGradient["StartB"] + $GradientBOffset * $j, "Alpha" => $BackgroundGradient["StartAlpha"] + $GradientAlphaOffset * $j];
170 $PointArray = [];
171 for ($i = 0; $i <= 360; $i = $i + 360 / $Points) {
172 $PointArray[] = cos(deg2rad($i + $AxisRotation)) * ($EdgeHeight / $Segments) * $j + $CenterX;
173 $PointArray[] = sin(deg2rad($i + $AxisRotation)) * ($EdgeHeight / $Segments) * $j + $CenterY;
174 }
175 $Object->drawPolygon($PointArray, $Color);
176 }
177 } elseif ($Layout == RADAR_LAYOUT_CIRCLE) {
178 for ($j = $Segments; $j >= 1; $j--) {
179 $Color = ["R" => $BackgroundGradient["StartR"] + $GradientROffset * $j, "G" => $BackgroundGradient["StartG"] + $GradientGOffset * $j, "B" => $BackgroundGradient["StartB"] + $GradientBOffset * $j, "Alpha" => $BackgroundGradient["StartAlpha"] + $GradientAlphaOffset * $j];
180 $Object->drawFilledCircle($CenterX, $CenterY, $EdgeHeight / $Segments * $j, $Color);
181 }
182 }
183 }
184 $Object->Shadow = $RestoreShadow;
185 }
186 /* Axis to axis lines */
187 $Color = ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha];
188 $ColorDotted = ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha * 0.8, "Ticks" => 2];
189 if ($Layout == RADAR_LAYOUT_STAR) {
190 for ($j = 1; $j <= $Segments; $j++) {
191 for ($i = 0; $i < 360; $i = $i + 360 / $Points) {
192 $EdgeX1 = cos(deg2rad($i + $AxisRotation)) * ($EdgeHeight / $Segments) * $j + $CenterX;
193 $EdgeY1 = sin(deg2rad($i + $AxisRotation)) * ($EdgeHeight / $Segments) * $j + $CenterY;
194 $EdgeX2 = cos(deg2rad($i + $AxisRotation + 360 / $Points)) * ($EdgeHeight / $Segments) * $j + $CenterX;
195 $EdgeY2 = sin(deg2rad($i + $AxisRotation + 360 / $Points)) * ($EdgeHeight / $Segments) * $j + $CenterY;
196 $Object->drawLine($EdgeX1, $EdgeY1, $EdgeX2, $EdgeY2, $Color);
197 }
198 }
199 } elseif ($Layout == RADAR_LAYOUT_CIRCLE) {
200 for ($j = 1; $j <= $Segments; $j++) {
201 $Radius = $EdgeHeight / $Segments * $j;
202 $Object->drawCircle($CenterX, $CenterY, $Radius, $Radius, $Color);
203 }
204 }
205 if ($DrawAxisValues) {
206 if ($LabelsBackground) {
207 $Options = ["DrawBox" => \true, "Align" => TEXT_ALIGN_MIDDLEMIDDLE, "BoxR" => $LabelsBGR, "BoxG" => $LabelsBGG, "BoxB" => $LabelsBGB, "BoxAlpha" => $LabelsBGAlpha];
208 } else {
209 $Options = ["Align" => TEXT_ALIGN_MIDDLEMIDDLE];
210 }
211 if ($AxisBoxRounded) {
212 $Options["BoxRounded"] = \true;
213 }
214 $Options["FontName"] = $AxisFontName;
215 $Options["FontSize"] = $AxisFontSize;
216 $Angle = 360 / ($Points * 2);
217 for ($j = 1; $j <= $Segments; $j++) {
218 $Label = $j * $SegmentHeight;
219 if ($Layout == RADAR_LAYOUT_CIRCLE) {
220 $EdgeX1 = cos(deg2rad($Angle + $AxisRotation)) * ($EdgeHeight / $Segments) * $j + $CenterX;
221 $EdgeY1 = sin(deg2rad($Angle + $AxisRotation)) * ($EdgeHeight / $Segments) * $j + $CenterY;
222 } elseif ($Layout == RADAR_LAYOUT_STAR) {
223 $EdgeX1 = cos(deg2rad($AxisRotation)) * ($EdgeHeight / $Segments) * $j + $CenterX;
224 $EdgeY1 = sin(deg2rad($AxisRotation)) * ($EdgeHeight / $Segments) * $j + $CenterY;
225 $EdgeX2 = cos(deg2rad(360 / $Points + $AxisRotation)) * ($EdgeHeight / $Segments) * $j + $CenterX;
226 $EdgeY2 = sin(deg2rad(360 / $Points + $AxisRotation)) * ($EdgeHeight / $Segments) * $j + $CenterY;
227 $EdgeX1 = ($EdgeX2 - $EdgeX1) / 2 + $EdgeX1;
228 $EdgeY1 = ($EdgeY2 - $EdgeY1) / 2 + $EdgeY1;
229 }
230 $Object->drawText($EdgeX1, $EdgeY1, $Label, $Options);
231 }
232 }
233 /* Axis lines */
234 $ID = 0;
235 for ($i = 0; $i < 360; $i = $i + 360 / $Points) {
236 $EdgeX = cos(deg2rad($i + $AxisRotation)) * ($EdgeHeight + $TicksLength) + $CenterX;
237 $EdgeY = sin(deg2rad($i + $AxisRotation)) * ($EdgeHeight + $TicksLength) + $CenterY;
238 if ($ID % $SkipLabels == 0) {
239 $Object->drawLine($CenterX, $CenterY, $EdgeX, $EdgeY, $Color);
240 } else {
241 $Object->drawLine($CenterX, $CenterY, $EdgeX, $EdgeY, $ColorDotted);
242 }
243 if ($WriteLabels) {
244 $LabelX = cos(deg2rad($i + $AxisRotation + $Axisoffset)) * ($EdgeHeight + $LabelPadding + $TicksLength) + $CenterX;
245 $LabelY = sin(deg2rad($i + $AxisRotation + $Axisoffset)) * ($EdgeHeight + $LabelPadding + $TicksLength) + $CenterY;
246 if ($LabelSerie) {
247 $Label = isset($Data["Series"][$LabelSerie]["Data"][$ID]) ? $Data["Series"][$LabelSerie]["Data"][$ID] : "";
248 } else {
249 $Label = $ID;
250 }
251 if ($ID % $SkipLabels == 0) {
252 if ($LabelPos == RADAR_LABELS_ROTATED) {
253 $Object->drawText($LabelX, $LabelY, $Label, ["Angle" => 360 - ($i + $AxisRotation + $Axisoffset) - 90, "Align" => TEXT_ALIGN_BOTTOMMIDDLE]);
254 } else {
255 if (floor($LabelX) == floor($CenterX) && floor($LabelY) < floor($CenterY)) {
256 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_BOTTOMMIDDLE]);
257 }
258 if (floor($LabelX) > floor($CenterX) && floor($LabelY) < floor($CenterY)) {
259 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_BOTTOMLEFT]);
260 }
261 if (floor($LabelX) > floor($CenterX) && floor($LabelY) == floor($CenterY)) {
262 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_MIDDLELEFT]);
263 }
264 if (floor($LabelX) > floor($CenterX) && floor($LabelY) > floor($CenterY)) {
265 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_TOPLEFT]);
266 }
267 if (floor($LabelX) < floor($CenterX) && floor($LabelY) < floor($CenterY)) {
268 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_BOTTOMRIGHT]);
269 }
270 if (floor($LabelX) < floor($CenterX) && floor($LabelY) == floor($CenterY)) {
271 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_MIDDLERIGHT]);
272 }
273 if (floor($LabelX) < floor($CenterX) && floor($LabelY) > floor($CenterY)) {
274 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_TOPRIGHT]);
275 }
276 if (floor($LabelX) == floor($CenterX) && floor($LabelY) > floor($CenterY)) {
277 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_TOPMIDDLE]);
278 }
279 }
280 }
281 }
282 $ID++;
283 }
284 /* Compute the plots position */
285 $ID = 0;
286 $Plot = [];
287 foreach ($Data["Series"] as $SerieName => $DataS) {
288 if ($SerieName != $LabelSerie) {
289 $Color = ["R" => $Palette[$ID]["R"], "G" => $Palette[$ID]["G"], "B" => $Palette[$ID]["B"], "Alpha" => $Palette[$ID]["Alpha"], "Surrounding" => $PointSurrounding];
290 foreach ($DataS["Data"] as $Key => $Value) {
291 $Angle = 360 / $Points * $Key;
292 $Length = $EdgeHeight / ($Segments * $SegmentHeight) * $Value;
293 $X = cos(deg2rad($Angle + $AxisRotation)) * $Length + $CenterX;
294 $Y = sin(deg2rad($Angle + $AxisRotation)) * $Length + $CenterY;
295 $Plot[$ID][] = [$X, $Y, $Value];
296 if ($RecordImageMap) {
297 $this->pChartObject->addToImageMap("CIRCLE", sprintf("%s,%s,%s", floor($X), floor($Y), floor($PointRadius)), $this->pChartObject->toHTMLColor($Palette[$ID]["R"], $Palette[$ID]["G"], $Palette[$ID]["B"]), $DataS["Description"], $Data["Series"][$LabelSerie]["Data"][$Key] . " = " . $Value);
298 }
299 }
300 $ID++;
301 }
302 }
303 /* Draw all that stuff! */
304 foreach ($Plot as $ID => $Points) {
305 $Color = ["R" => $Palette[$ID]["R"], "G" => $Palette[$ID]["G"], "B" => $Palette[$ID]["B"], "Alpha" => $Palette[$ID]["Alpha"], "Surrounding" => $PointSurrounding];
306 /* Draw the polygons */
307 if ($DrawPoly) {
308 if ($PolyAlpha != null) {
309 $Color = ["R" => $Palette[$ID]["R"], "G" => $Palette[$ID]["G"], "B" => $Palette[$ID]["B"], "Alpha" => $PolyAlpha, "Surrounding" => $PointSurrounding];
310 }
311 $PointsArray = [];
312 for ($i = 0; $i < count($Points); $i++) {
313 $PointsArray[] = $Points[$i][0];
314 $PointsArray[] = $Points[$i][1];
315 }
316 $Object->drawPolygon($PointsArray, $Color);
317 }
318 $Color = ["R" => $Palette[$ID]["R"], "G" => $Palette[$ID]["G"], "B" => $Palette[$ID]["B"], "Alpha" => $Palette[$ID]["Alpha"], "Surrounding" => $PointSurrounding];
319 /* Bubble and labels settings */
320 $TextSettings = ["Align" => TEXT_ALIGN_MIDDLEMIDDLE, "FontName" => $ValueFontName, "FontSize" => $ValueFontSize, "R" => $Palette[$ID]["R"], "G" => $Palette[$ID]["G"], "B" => $Palette[$ID]["B"]];
321 $InnerColor = ["R" => $InnerBubbleR, "G" => $InnerBubbleG, "B" => $InnerBubbleB, "Alpha" => $InnerBubbleAlpha];
322 if ($OuterBubbleR != VOID) {
323 $OuterColor = ["R" => $OuterBubbleR, "G" => $OuterBubbleG, "B" => $OuterBubbleB, "Alpha" => $OuterBubbleAlpha];
324 } else {
325 $OuterColor = ["R" => $Palette[$ID]["R"] + 20, "G" => $Palette[$ID]["G"] + 20, "B" => $Palette[$ID]["B"] + 20, "Alpha" => $Palette[$ID]["Alpha"]];
326 }
327 /* Loop to the starting points if asked */
328 if ($LineLoopStart && $DrawLines) {
329 $Object->drawLine($Points[count($Points) - 1][0], $Points[count($Points) - 1][1], $Points[0][0], $Points[0][1], $Color);
330 }
331 /* Draw the lines & points */
332 for ($i = 0; $i < count($Points); $i++) {
333 if ($DrawLines && $i < count($Points) - 1) {
334 $Object->drawLine($Points[$i][0], $Points[$i][1], $Points[$i + 1][0], $Points[$i + 1][1], $Color);
335 }
336 if ($DrawPoints) {
337 $Object->drawFilledCircle($Points[$i][0], $Points[$i][1], $PointRadius, $Color);
338 }
339 if ($WriteValuesInBubble && $WriteValues) {
340 $TxtPos = $this->pChartObject->getTextBox($Points[$i][0], $Points[$i][1], $ValueFontName, $ValueFontSize, 0, $Points[$i][2]);
341 $Radius = floor(($TxtPos[1]["X"] - $TxtPos[0]["X"] + $ValuePadding * 2) / 2);
342 $this->pChartObject->drawFilledCircle($Points[$i][0], $Points[$i][1], $Radius + $OuterBubbleRadius, $OuterColor);
343 $this->pChartObject->drawFilledCircle($Points[$i][0], $Points[$i][1], $Radius, $InnerColor);
344 }
345 if ($WriteValues) {
346 $this->pChartObject->drawText($Points[$i][0] - 1, $Points[$i][1] - 1, $Points[$i][2], $TextSettings);
347 }
348 }
349 }
350 }
351 /**
352 * Draw a radar chart
353 * @param Image $Object
354 * @param Data $Values
355 * @param array $Format
356 */
357 public function drawPolar(Image $Object, Data $Values, array $Format = [])
358 {
359 $this->pChartObject = $Object;
360 $FixedMax = isset($Format["FixedMax"]) ? $Format["FixedMax"] : VOID;
361 $AxisR = isset($Format["AxisR"]) ? $Format["AxisR"] : 60;
362 $AxisG = isset($Format["AxisG"]) ? $Format["AxisG"] : 60;
363 $AxisB = isset($Format["AxisB"]) ? $Format["AxisB"] : 60;
364 $AxisAlpha = isset($Format["AxisAlpha"]) ? $Format["AxisAlpha"] : 50;
365 $AxisRotation = isset($Format["AxisRotation"]) ? $Format["AxisRotation"] : -90;
366 $DrawTicks = isset($Format["DrawTicks"]) ? $Format["DrawTicks"] : \true;
367 $TicksLength = isset($Format["TicksLength"]) ? $Format["TicksLength"] : 2;
368 $DrawAxisValues = isset($Format["DrawAxisValues"]) ? $Format["DrawAxisValues"] : \true;
369 $AxisBoxRounded = isset($Format["AxisBoxRounded"]) ? $Format["AxisBoxRounded"] : \true;
370 $AxisFontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName;
371 $AxisFontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize;
372 $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : \false;
373 $WriteValuesInBubble = isset($Format["WriteValuesInBubble"]) ? $Format["WriteValuesInBubble"] : \true;
374 $ValueFontName = isset($Format["ValueFontName"]) ? $Format["ValueFontName"] : $this->pChartObject->FontName;
375 $ValueFontSize = isset($Format["ValueFontSize"]) ? $Format["ValueFontSize"] : $this->pChartObject->FontSize;
376 $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 4;
377 $OuterBubbleRadius = isset($Format["OuterBubbleRadius"]) ? $Format["OuterBubbleRadius"] : 2;
378 $OuterBubbleR = isset($Format["OuterBubbleR"]) ? $Format["OuterBubbleR"] : VOID;
379 $OuterBubbleG = isset($Format["OuterBubbleG"]) ? $Format["OuterBubbleG"] : VOID;
380 $OuterBubbleB = isset($Format["OuterBubbleB"]) ? $Format["OuterBubbleB"] : VOID;
381 $OuterBubbleAlpha = isset($Format["OuterBubbleAlpha"]) ? $Format["OuterBubbleAlpha"] : 100;
382 $InnerBubbleR = isset($Format["InnerBubbleR"]) ? $Format["InnerBubbleR"] : 255;
383 $InnerBubbleG = isset($Format["InnerBubbleG"]) ? $Format["InnerBubbleG"] : 255;
384 $InnerBubbleB = isset($Format["InnerBubbleB"]) ? $Format["InnerBubbleB"] : 255;
385 $InnerBubbleAlpha = isset($Format["InnerBubbleAlpha"]) ? $Format["InnerBubbleAlpha"] : 100;
386 $DrawBackground = isset($Format["DrawBackground"]) ? $Format["DrawBackground"] : \true;
387 $BackgroundR = isset($Format["BackgroundR"]) ? $Format["BackgroundR"] : 255;
388 $BackgroundG = isset($Format["BackgroundG"]) ? $Format["BackgroundG"] : 255;
389 $BackgroundB = isset($Format["BackgroundB"]) ? $Format["BackgroundB"] : 255;
390 $BackgroundAlpha = isset($Format["BackgroundAlpha"]) ? $Format["BackgroundAlpha"] : 50;
391 $BackgroundGradient = isset($Format["BackgroundGradient"]) ? $Format["BackgroundGradient"] : null;
392 $AxisSteps = isset($Format["AxisSteps"]) ? $Format["AxisSteps"] : 20;
393 $SegmentHeight = isset($Format["SegmentHeight"]) ? $Format["SegmentHeight"] : SEGMENT_HEIGHT_AUTO;
394 $Segments = isset($Format["Segments"]) ? $Format["Segments"] : 4;
395 $WriteLabels = isset($Format["WriteLabels"]) ? $Format["WriteLabels"] : \true;
396 $LabelsBackground = isset($Format["LabelsBackground"]) ? $Format["LabelsBackground"] : \true;
397 $LabelsBGR = isset($Format["LabelsBGR"]) ? $Format["LabelsBGR"] : 255;
398 $LabelsBGG = isset($Format["LabelsBGR"]) ? $Format["LabelsBGG"] : 255;
399 $LabelsBGB = isset($Format["LabelsBGR"]) ? $Format["LabelsBGB"] : 255;
400 $LabelsBGAlpha = isset($Format["LabelsBGAlpha"]) ? $Format["LabelsBGAlpha"] : 50;
401 $LabelPos = isset($Format["LabelPos"]) ? $Format["LabelPos"] : RADAR_LABELS_ROTATED;
402 $LabelPadding = isset($Format["LabelPadding"]) ? $Format["LabelPadding"] : 4;
403 $DrawPoints = isset($Format["DrawPoints"]) ? $Format["DrawPoints"] : \true;
404 $PointRadius = isset($Format["PointRadius"]) ? $Format["PointRadius"] : 4;
405 $PointSurrounding = isset($Format["PointRadius"]) ? $Format["PointRadius"] : -30;
406 $DrawLines = isset($Format["DrawLines"]) ? $Format["DrawLines"] : \true;
407 $LineLoopStart = isset($Format["LineLoopStart"]) ? $Format["LineLoopStart"] : \false;
408 $DrawPoly = isset($Format["DrawPoly"]) ? $Format["DrawPoly"] : \false;
409 $PolyAlpha = isset($Format["PolyAlpha"]) ? $Format["PolyAlpha"] : null;
410 $FontSize = $Object->FontSize;
411 $X1 = $Object->GraphAreaX1;
412 $Y1 = $Object->GraphAreaY1;
413 $X2 = $Object->GraphAreaX2;
414 $Y2 = $Object->GraphAreaY2;
415 $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : \false;
416 if ($AxisBoxRounded) {
417 $DrawAxisValues = \true;
418 }
419 /* Cancel default tick length if ticks not enabled */
420 if ($DrawTicks == \false) {
421 $TicksLength = 0;
422 }
423 /* Data Processing */
424 $Data = $Values->getData();
425 $Palette = $Values->getPalette();
426 /* Catch the number of required axis */
427 $LabelSerie = $Data["Abscissa"];
428 if ($LabelSerie) {
429 $Points = count($Data["Series"][$LabelSerie]["Data"]);
430 } else {
431 $Points = 0;
432 foreach ($Data["Series"] as $SerieName => $DataArray) {
433 if (count($DataArray["Data"]) > $Points) {
434 $Points = count($DataArray["Data"]);
435 }
436 }
437 }
438 /* Draw the axis */
439 $CenterX = ($X2 - $X1) / 2 + $X1;
440 $CenterY = ($Y2 - $Y1) / 2 + $Y1;
441 $EdgeHeight = min(($X2 - $X1) / 2, ($Y2 - $Y1) / 2);
442 if ($WriteLabels) {
443 $EdgeHeight = $EdgeHeight - $FontSize - $LabelPadding - $TicksLength;
444 }
445 /* Determine the scale if set to automatic */
446 if ($SegmentHeight == SEGMENT_HEIGHT_AUTO) {
447 if ($FixedMax != VOID) {
448 $Max = $FixedMax;
449 } else {
450 $Max = 0;
451 foreach ($Data["Series"] as $SerieName => $DataArray) {
452 if ($SerieName != $LabelSerie) {
453 if (max($DataArray["Data"]) > $Max) {
454 $Max = max($DataArray["Data"]);
455 }
456 }
457 }
458 }
459 $MaxSegments = $EdgeHeight / 20;
460 $Scale = $Object->computeScale(0, $Max, $MaxSegments, [1, 2, 5]);
461 $Segments = $Scale["Rows"];
462 $SegmentHeight = $Scale["RowHeight"];
463 }
464 /* Background processing */
465 if ($DrawBackground) {
466 $RestoreShadow = $Object->Shadow;
467 $Object->Shadow = \false;
468 if ($BackgroundGradient == null) {
469 $Color = ["R" => $BackgroundR, "G" => $BackgroundG, "B" => $BackgroundB, "Alpha" => $BackgroundAlpha];
470 $Object->drawFilledCircle($CenterX, $CenterY, $EdgeHeight, $Color);
471 } else {
472 $GradientROffset = ($BackgroundGradient["EndR"] - $BackgroundGradient["StartR"]) / $Segments;
473 $GradientGOffset = ($BackgroundGradient["EndG"] - $BackgroundGradient["StartG"]) / $Segments;
474 $GradientBOffset = ($BackgroundGradient["EndB"] - $BackgroundGradient["StartB"]) / $Segments;
475 $GradientAlphaOffset = ($BackgroundGradient["EndAlpha"] - $BackgroundGradient["StartAlpha"]) / $Segments;
476 for ($j = $Segments; $j >= 1; $j--) {
477 $Color = ["R" => $BackgroundGradient["StartR"] + $GradientROffset * $j, "G" => $BackgroundGradient["StartG"] + $GradientGOffset * $j, "B" => $BackgroundGradient["StartB"] + $GradientBOffset * $j, "Alpha" => $BackgroundGradient["StartAlpha"] + $GradientAlphaOffset * $j];
478 $Object->drawFilledCircle($CenterX, $CenterY, $EdgeHeight / $Segments * $j, $Color);
479 }
480 }
481 $Object->Shadow = $RestoreShadow;
482 }
483 /* Axis to axis lines */
484 $Color = ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha];
485 for ($j = 1; $j <= $Segments; $j++) {
486 $Radius = $EdgeHeight / $Segments * $j;
487 $Object->drawCircle($CenterX, $CenterY, $Radius, $Radius, $Color);
488 }
489 if ($DrawAxisValues) {
490 if ($LabelsBackground) {
491 $Options = ["DrawBox" => \true, "Align" => TEXT_ALIGN_MIDDLEMIDDLE, "BoxR" => $LabelsBGR, "BoxG" => $LabelsBGG, "BoxB" => $LabelsBGB, "BoxAlpha" => $LabelsBGAlpha];
492 } else {
493 $Options = ["Align" => TEXT_ALIGN_MIDDLEMIDDLE];
494 }
495 if ($AxisBoxRounded) {
496 $Options["BoxRounded"] = \true;
497 }
498 $Options["FontName"] = $AxisFontName;
499 $Options["FontSize"] = $AxisFontSize;
500 $Angle = 360 / ($Points * 2);
501 for ($j = 1; $j <= $Segments; $j++) {
502 $EdgeX1 = cos(deg2rad($Angle + $AxisRotation)) * ($EdgeHeight / $Segments) * $j + $CenterX;
503 $EdgeY1 = sin(deg2rad($Angle + $AxisRotation)) * ($EdgeHeight / $Segments) * $j + $CenterY;
504 $Label = $j * $SegmentHeight;
505 $Object->drawText($EdgeX1, $EdgeY1, $Label, $Options);
506 }
507 }
508 /* Axis lines */
509 $ID = 0;
510 for ($i = 0; $i <= 359; $i = $i + $AxisSteps) {
511 $EdgeX = cos(deg2rad($i + $AxisRotation)) * ($EdgeHeight + $TicksLength) + $CenterX;
512 $EdgeY = sin(deg2rad($i + $AxisRotation)) * ($EdgeHeight + $TicksLength) + $CenterY;
513 $Object->drawLine($CenterX, $CenterY, $EdgeX, $EdgeY, $Color);
514 if ($WriteLabels) {
515 $LabelX = cos(deg2rad($i + $AxisRotation)) * ($EdgeHeight + $LabelPadding + $TicksLength) + $CenterX;
516 $LabelY = sin(deg2rad($i + $AxisRotation)) * ($EdgeHeight + $LabelPadding + $TicksLength) + $CenterY;
517 $Label = $i . "°";
518 if ($LabelPos == RADAR_LABELS_ROTATED) {
519 $Object->drawText($LabelX, $LabelY, $Label, ["Angle" => 360 - $i, "Align" => TEXT_ALIGN_BOTTOMMIDDLE]);
520 } else {
521 if (floor($LabelX) == floor($CenterX) && floor($LabelY) < floor($CenterY)) {
522 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_BOTTOMMIDDLE]);
523 }
524 if (floor($LabelX) > floor($CenterX) && floor($LabelY) < floor($CenterY)) {
525 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_BOTTOMLEFT]);
526 }
527 if (floor($LabelX) > floor($CenterX) && floor($LabelY) == floor($CenterY)) {
528 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_MIDDLELEFT]);
529 }
530 if (floor($LabelX) > floor($CenterX) && floor($LabelY) > floor($CenterY)) {
531 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_TOPLEFT]);
532 }
533 if (floor($LabelX) < floor($CenterX) && floor($LabelY) < floor($CenterY)) {
534 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_BOTTOMRIGHT]);
535 }
536 if (floor($LabelX) < floor($CenterX) && floor($LabelY) == floor($CenterY)) {
537 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_MIDDLERIGHT]);
538 }
539 if (floor($LabelX) < floor($CenterX) && floor($LabelY) > floor($CenterY)) {
540 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_TOPRIGHT]);
541 }
542 if (floor($LabelX) == floor($CenterX) && floor($LabelY) > floor($CenterY)) {
543 $Object->drawText($LabelX, $LabelY, $Label, ["Align" => TEXT_ALIGN_TOPMIDDLE]);
544 }
545 }
546 }
547 $ID++;
548 }
549 /* Compute the plots position */
550 $ID = 0;
551 $Plot = [];
552 foreach ($Data["Series"] as $SerieName => $DataSet) {
553 if ($SerieName != $LabelSerie) {
554 $Color = ["R" => $Palette[$ID]["R"], "G" => $Palette[$ID]["G"], "B" => $Palette[$ID]["B"], "Alpha" => $Palette[$ID]["Alpha"], "Surrounding" => $PointSurrounding];
555 foreach ($DataSet["Data"] as $Key => $Value) {
556 $Angle = $Data["Series"][$LabelSerie]["Data"][$Key];
557 $Length = $EdgeHeight / ($Segments * $SegmentHeight) * $Value;
558 $X = cos(deg2rad($Angle + $AxisRotation)) * $Length + $CenterX;
559 $Y = sin(deg2rad($Angle + $AxisRotation)) * $Length + $CenterY;
560 if ($RecordImageMap) {
561 $this->pChartObject->addToImageMap("CIRCLE", sprintf("%s,%s,%s", floor($X), floor($Y), floor($PointRadius)), $this->pChartObject->toHTMLColor($Palette[$ID]["R"], $Palette[$ID]["G"], $Palette[$ID]["B"]), $DataSet["Description"], $Data["Series"][$LabelSerie]["Data"][$Key] . "&deg = " . $Value);
562 }
563 $Plot[$ID][] = [$X, $Y, $Value];
564 }
565 $ID++;
566 }
567 }
568 /* Draw all that stuff! */
569 foreach ($Plot as $ID => $Points) {
570 $Color = ["R" => $Palette[$ID]["R"], "G" => $Palette[$ID]["G"], "B" => $Palette[$ID]["B"], "Alpha" => $Palette[$ID]["Alpha"], "Surrounding" => $PointSurrounding];
571 /* Draw the polygons */
572 if ($DrawPoly) {
573 if ($PolyAlpha != null) {
574 $Color = ["R" => $Palette[$ID]["R"], "G" => $Palette[$ID]["G"], "B" => $Palette[$ID]["B"], "Alpha" => $PolyAlpha, "Surrounding" => $PointSurrounding];
575 }
576 $PointsArray = [];
577 for ($i = 0; $i < count($Points); $i++) {
578 $PointsArray[] = $Points[$i][0];
579 $PointsArray[] = $Points[$i][1];
580 }
581 $Object->drawPolygon($PointsArray, $Color);
582 }
583 $Color = ["R" => $Palette[$ID]["R"], "G" => $Palette[$ID]["G"], "B" => $Palette[$ID]["B"], "Alpha" => $Palette[$ID]["Alpha"], "Surrounding" => $PointSurrounding];
584 /* Bubble and labels settings */
585 $TextSettings = ["Align" => TEXT_ALIGN_MIDDLEMIDDLE, "FontName" => $ValueFontName, "FontSize" => $ValueFontSize, "R" => $Palette[$ID]["R"], "G" => $Palette[$ID]["G"], "B" => $Palette[$ID]["B"]];
586 $InnerColor = ["R" => $InnerBubbleR, "G" => $InnerBubbleG, "B" => $InnerBubbleB, "Alpha" => $InnerBubbleAlpha];
587 if ($OuterBubbleR != VOID) {
588 $OuterColor = ["R" => $OuterBubbleR, "G" => $OuterBubbleG, "B" => $OuterBubbleB, "Alpha" => $OuterBubbleAlpha];
589 } else {
590 $OuterColor = ["R" => $Palette[$ID]["R"] + 20, "G" => $Palette[$ID]["G"] + 20, "B" => $Palette[$ID]["B"] + 20, "Alpha" => $Palette[$ID]["Alpha"]];
591 }
592 /* Loop to the starting points if asked */
593 if ($LineLoopStart && $DrawLines) {
594 $Object->drawLine($Points[count($Points) - 1][0], $Points[count($Points) - 1][1], $Points[0][0], $Points[0][1], $Color);
595 }
596 /* Draw the lines & points */
597 for ($i = 0; $i < count($Points); $i++) {
598 if ($DrawLines && $i < count($Points) - 1) {
599 $Object->drawLine($Points[$i][0], $Points[$i][1], $Points[$i + 1][0], $Points[$i + 1][1], $Color);
600 }
601 if ($DrawPoints) {
602 $Object->drawFilledCircle($Points[$i][0], $Points[$i][1], $PointRadius, $Color);
603 }
604 if ($WriteValuesInBubble && $WriteValues) {
605 $TxtPos = $this->pChartObject->getTextBox($Points[$i][0], $Points[$i][1], $ValueFontName, $ValueFontSize, 0, $Points[$i][2]);
606 $Radius = floor(($TxtPos[1]["X"] - $TxtPos[0]["X"] + $ValuePadding * 2) / 2);
607 $this->pChartObject->drawFilledCircle($Points[$i][0], $Points[$i][1], $Radius + $OuterBubbleRadius, $OuterColor);
608 $this->pChartObject->drawFilledCircle($Points[$i][0], $Points[$i][1], $Radius, $InnerColor);
609 }
610 if ($WriteValues) {
611 $this->pChartObject->drawText($Points[$i][0] - 1, $Points[$i][1] - 1, $Points[$i][2], $TextSettings);
612 }
613 }
614 }
615 }
616 }
617