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 / Scatter.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
Scatter.php
1261 lines
1 <?php
2
3 namespace CpChart\Chart;
4
5 use CpChart\Data;
6 use CpChart\Image;
7 use Exception;
8 /**
9 * Scatter - class to draw scatter charts
10 *
11 * Version : 2.1.4
12 * Made by : Jean-Damien POGOLOTTI
13 * Last Update : 19/01/2014
14 *
15 * This file can be distributed under the license you can find at :
16 *
17 * http://www.pchart.net/license
18 *
19 * You can find the whole class documentation on the pChart web site.
20 */
21 class Scatter
22 {
23 /**
24 * @var Image
25 */
26 public $pChartObject;
27 /**
28 * @var Data
29 */
30 public $pDataObject;
31 /**
32 * @param Image $pChartObject
33 * @param Data $pDataObject
34 */
35 public function __construct(Image $pChartObject, Data $pDataObject)
36 {
37 $this->pChartObject = $pChartObject;
38 $this->pDataObject = $pDataObject;
39 }
40 /**
41 * Prepare the scale
42 * @param array $Format
43 * @return null|int
44 * @throws Exception
45 */
46 public function drawScatterScale(array $Format = [])
47 {
48 $Mode = isset($Format["Mode"]) ? $Format["Mode"] : SCALE_MODE_FLOATING;
49 $Floating = isset($Format["Floating"]) ? $Format["Floating"] : \false;
50 $XLabelsRotation = isset($Format["XLabelsRotation"]) ? $Format["XLabelsRotation"] : 90;
51 $MinDivHeight = isset($Format["MinDivHeight"]) ? $Format["MinDivHeight"] : 20;
52 $Factors = isset($Format["Factors"]) ? $Format["Factors"] : [1, 2, 5];
53 $ManualScale = isset($Format["ManualScale"]) ? $Format["ManualScale"] : ["0" => ["Min" => -100, "Max" => 100]];
54 $XMargin = isset($Format["XMargin"]) ? $Format["XMargin"] : 0;
55 $YMargin = isset($Format["YMargin"]) ? $Format["YMargin"] : 0;
56 $ScaleSpacing = isset($Format["ScaleSpacing"]) ? $Format["ScaleSpacing"] : 15;
57 $InnerTickWidth = isset($Format["InnerTickWidth"]) ? $Format["InnerTickWidth"] : 2;
58 $OuterTickWidth = isset($Format["OuterTickWidth"]) ? $Format["OuterTickWidth"] : 2;
59 $DrawXLines = isset($Format["DrawXLines"]) ? $Format["DrawXLines"] : ALL;
60 $DrawYLines = isset($Format["DrawYLines"]) ? $Format["DrawYLines"] : ALL;
61 $GridTicks = isset($Format["GridTicks"]) ? $Format["GridTicks"] : 4;
62 $GridR = isset($Format["GridR"]) ? $Format["GridR"] : 255;
63 $GridG = isset($Format["GridG"]) ? $Format["GridG"] : 255;
64 $GridB = isset($Format["GridB"]) ? $Format["GridB"] : 255;
65 $GridAlpha = isset($Format["GridAlpha"]) ? $Format["GridAlpha"] : 40;
66 $AxisRo = isset($Format["AxisR"]) ? $Format["AxisR"] : 0;
67 $AxisGo = isset($Format["AxisG"]) ? $Format["AxisG"] : 0;
68 $AxisBo = isset($Format["AxisB"]) ? $Format["AxisB"] : 0;
69 $AxisAlpha = isset($Format["AxisAlpha"]) ? $Format["AxisAlpha"] : 100;
70 $TickRo = isset($Format["TickR"]) ? $Format["TickR"] : 0;
71 $TickGo = isset($Format["TickG"]) ? $Format["TickG"] : 0;
72 $TickBo = isset($Format["TickB"]) ? $Format["TickB"] : 0;
73 $TickAlpha = isset($Format["TickAlpha"]) ? $Format["TickAlpha"] : 100;
74 $DrawSubTicks = isset($Format["DrawSubTicks"]) ? $Format["DrawSubTicks"] : \false;
75 $InnerSubTickWidth = isset($Format["InnerSubTickWidth"]) ? $Format["InnerSubTickWidth"] : 0;
76 $OuterSubTickWidth = isset($Format["OuterSubTickWidth"]) ? $Format["OuterSubTickWidth"] : 2;
77 $SubTickR = isset($Format["SubTickR"]) ? $Format["SubTickR"] : 255;
78 $SubTickG = isset($Format["SubTickG"]) ? $Format["SubTickG"] : 0;
79 $SubTickB = isset($Format["SubTickB"]) ? $Format["SubTickB"] : 0;
80 $SubTickAlpha = isset($Format["SubTickAlpha"]) ? $Format["SubTickAlpha"] : 100;
81 $XReleasePercent = isset($Format["XReleasePercent"]) ? $Format["XReleasePercent"] : 1;
82 $DrawArrows = isset($Format["DrawArrows"]) ? $Format["DrawArrows"] : \false;
83 $ArrowSize = isset($Format["ArrowSize"]) ? $Format["ArrowSize"] : 8;
84 $CycleBackground = isset($Format["CycleBackground"]) ? $Format["CycleBackground"] : \false;
85 $BackgroundR1 = isset($Format["BackgroundR1"]) ? $Format["BackgroundR1"] : 255;
86 $BackgroundG1 = isset($Format["BackgroundG1"]) ? $Format["BackgroundG1"] : 255;
87 $BackgroundB1 = isset($Format["BackgroundB1"]) ? $Format["BackgroundB1"] : 255;
88 $BackgroundAlpha1 = isset($Format["BackgroundAlpha1"]) ? $Format["BackgroundAlpha1"] : 10;
89 $BackgroundR2 = isset($Format["BackgroundR2"]) ? $Format["BackgroundR2"] : 230;
90 $BackgroundG2 = isset($Format["BackgroundG2"]) ? $Format["BackgroundG2"] : 230;
91 $BackgroundB2 = isset($Format["BackgroundB2"]) ? $Format["BackgroundB2"] : 230;
92 $BackgroundAlpha2 = isset($Format["BackgroundAlpha2"]) ? $Format["BackgroundAlpha2"] : 10;
93 /* Check if we have at least both one X and Y axis */
94 $GotXAxis = \false;
95 $GotYAxis = \false;
96 foreach ($this->pDataObject->Data["Axis"] as $AxisID => $AxisSettings) {
97 if ($AxisSettings["Identity"] == AXIS_X) {
98 $GotXAxis = \true;
99 }
100 if ($AxisSettings["Identity"] == AXIS_Y) {
101 $GotYAxis = \true;
102 }
103 }
104 if (!$GotXAxis) {
105 return SCATTER_MISSING_X_SERIE;
106 }
107 if (!$GotYAxis) {
108 return SCATTER_MISSING_Y_SERIE;
109 }
110 /* Skip a NOTICE event in case of an empty array */
111 if ($DrawYLines == NONE) {
112 $DrawYLines = ["zarma" => "31"];
113 }
114 $Data = $this->pDataObject->getData();
115 foreach ($Data["Axis"] as $AxisID => $AxisSettings) {
116 if ($AxisSettings["Identity"] == AXIS_X) {
117 $Width = $this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin * 2;
118 } else {
119 $Width = $this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1 - $YMargin * 2;
120 }
121 $AxisMin = ABSOLUTE_MAX;
122 $AxisMax = OUT_OF_SIGHT;
123 if ($Mode == SCALE_MODE_FLOATING) {
124 foreach ($Data["Series"] as $SerieID => $SerieParameter) {
125 if ($SerieParameter["Axis"] == $AxisID && $Data["Series"][$SerieID]["isDrawable"]) {
126 $AxisMax = max($AxisMax, $Data["Series"][$SerieID]["Max"]);
127 $AxisMin = min($AxisMin, $Data["Series"][$SerieID]["Min"]);
128 }
129 }
130 $AutoMargin = ($AxisMax - $AxisMin) / 100 * $XReleasePercent;
131 $Data["Axis"][$AxisID]["Min"] = $AxisMin - $AutoMargin;
132 $Data["Axis"][$AxisID]["Max"] = $AxisMax + $AutoMargin;
133 } elseif ($Mode == SCALE_MODE_MANUAL) {
134 if (isset($ManualScale[$AxisID]["Min"]) && isset($ManualScale[$AxisID]["Max"])) {
135 $Data["Axis"][$AxisID]["Min"] = $ManualScale[$AxisID]["Min"];
136 $Data["Axis"][$AxisID]["Max"] = $ManualScale[$AxisID]["Max"];
137 } else {
138 throw new Exception("Manual scale boundaries not set.");
139 }
140 }
141 /* Full manual scale */
142 if (isset($ManualScale[$AxisID]["Rows"]) && isset($ManualScale[$AxisID]["RowHeight"])) {
143 $Scale = ["Rows" => $ManualScale[$AxisID]["Rows"], "RowHeight" => $ManualScale[$AxisID]["RowHeight"], "XMin" => $ManualScale[$AxisID]["Min"], "XMax" => $ManualScale[$AxisID]["Max"]];
144 } else {
145 $MaxDivs = floor($Width / $MinDivHeight);
146 $Scale = $this->pChartObject->computeScale($Data["Axis"][$AxisID]["Min"], $Data["Axis"][$AxisID]["Max"], $MaxDivs, $Factors, $AxisID);
147 }
148 $Data["Axis"][$AxisID]["Margin"] = $AxisSettings["Identity"] == AXIS_X ? $XMargin : $YMargin;
149 $Data["Axis"][$AxisID]["ScaleMin"] = $Scale["XMin"];
150 $Data["Axis"][$AxisID]["ScaleMax"] = $Scale["XMax"];
151 $Data["Axis"][$AxisID]["Rows"] = $Scale["Rows"];
152 $Data["Axis"][$AxisID]["RowHeight"] = $Scale["RowHeight"];
153 if (isset($Scale["Format"])) {
154 $Data["Axis"][$AxisID]["Format"] = $Scale["Format"];
155 }
156 if (!isset($Data["Axis"][$AxisID]["Display"])) {
157 $Data["Axis"][$AxisID]["Display"] = null;
158 }
159 if (!isset($Data["Axis"][$AxisID]["Format"])) {
160 $Data["Axis"][$AxisID]["Format"] = null;
161 }
162 if (!isset($Data["Axis"][$AxisID]["Unit"])) {
163 $Data["Axis"][$AxisID]["Unit"] = null;
164 }
165 }
166 /* Get the default font color */
167 $FontColorRo = $this->pChartObject->FontColorR;
168 $FontColorGo = $this->pChartObject->FontColorG;
169 $FontColorBo = $this->pChartObject->FontColorB;
170 /* Set the original boundaries */
171 $AxisPos["L"] = $this->pChartObject->GraphAreaX1;
172 $AxisPos["R"] = $this->pChartObject->GraphAreaX2;
173 $AxisPos["T"] = $this->pChartObject->GraphAreaY1;
174 $AxisPos["B"] = $this->pChartObject->GraphAreaY2;
175 foreach ($Data["Axis"] as $AxisID => $AxisSettings) {
176 if (isset($AxisSettings["Color"])) {
177 $AxisR = $AxisSettings["Color"]["R"];
178 $AxisG = $AxisSettings["Color"]["G"];
179 $AxisB = $AxisSettings["Color"]["B"];
180 $TickR = $AxisSettings["Color"]["R"];
181 $TickG = $AxisSettings["Color"]["G"];
182 $TickB = $AxisSettings["Color"]["B"];
183 $this->pChartObject->setFontProperties(["R" => $AxisSettings["Color"]["R"], "G" => $AxisSettings["Color"]["G"], "B" => $AxisSettings["Color"]["B"]]);
184 } else {
185 $AxisR = $AxisRo;
186 $AxisG = $AxisGo;
187 $AxisB = $AxisBo;
188 $TickR = $TickRo;
189 $TickG = $TickGo;
190 $TickB = $TickBo;
191 $this->pChartObject->setFontProperties(["R" => $FontColorRo, "G" => $FontColorGo, "B" => $FontColorBo]);
192 }
193 if ($AxisSettings["Identity"] == AXIS_X) {
194 if ($AxisSettings["Position"] == AXIS_POSITION_BOTTOM) {
195 if ($XLabelsRotation == 0) {
196 $LabelAlign = TEXT_ALIGN_TOPMIDDLE;
197 $LabelOffset = 2;
198 }
199 if ($XLabelsRotation > 0 && $XLabelsRotation < 190) {
200 $LabelAlign = TEXT_ALIGN_MIDDLERIGHT;
201 $LabelOffset = 5;
202 }
203 if ($XLabelsRotation == 180) {
204 $LabelAlign = TEXT_ALIGN_BOTTOMMIDDLE;
205 $LabelOffset = 5;
206 }
207 if ($XLabelsRotation > 180 && $XLabelsRotation < 360) {
208 $LabelAlign = TEXT_ALIGN_MIDDLELEFT;
209 $LabelOffset = 2;
210 }
211 if ($Floating) {
212 $FloatingOffset = $YMargin;
213 $this->pChartObject->drawLine($this->pChartObject->GraphAreaX1 + $AxisSettings["Margin"], $AxisPos["B"], $this->pChartObject->GraphAreaX2 - $AxisSettings["Margin"], $AxisPos["B"], ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]);
214 } else {
215 $FloatingOffset = 0;
216 $this->pChartObject->drawLine($this->pChartObject->GraphAreaX1, $AxisPos["B"], $this->pChartObject->GraphAreaX2, $AxisPos["B"], ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]);
217 }
218 if ($DrawArrows) {
219 $this->pChartObject->drawArrow($this->pChartObject->GraphAreaX2 - $AxisSettings["Margin"], $AxisPos["B"], $this->pChartObject->GraphAreaX2 + $ArrowSize * 2, $AxisPos["B"], ["FillR" => $AxisR, "FillG" => $AxisG, "FillB" => $AxisB, "Size" => $ArrowSize]);
220 }
221 $Width = $this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $AxisSettings["Margin"] * 2;
222 $Step = $Width / $AxisSettings["Rows"];
223 $SubTicksSize = $Step / 2;
224 $MaxBottom = $AxisPos["B"];
225 $LastX = null;
226 for ($i = 0; $i <= $AxisSettings["Rows"]; $i++) {
227 $XPos = $this->pChartObject->GraphAreaX1 + $AxisSettings["Margin"] + $Step * $i;
228 $YPos = $AxisPos["B"];
229 $Value = $this->pChartObject->scaleFormat($AxisSettings["ScaleMin"] + $AxisSettings["RowHeight"] * $i, $AxisSettings["Display"], $AxisSettings["Format"], $AxisSettings["Unit"]);
230 if ($i % 2 == 1) {
231 $BGColor = ["R" => $BackgroundR1, "G" => $BackgroundG1, "B" => $BackgroundB1, "Alpha" => $BackgroundAlpha1];
232 } else {
233 $BGColor = ["R" => $BackgroundR2, "G" => $BackgroundG2, "B" => $BackgroundB2, "Alpha" => $BackgroundAlpha2];
234 }
235 if ($LastX != null && $CycleBackground && ($DrawXLines == ALL || in_array($AxisID, $DrawXLines))) {
236 $this->pChartObject->drawFilledRectangle($LastX, $this->pChartObject->GraphAreaY1 + $FloatingOffset, $XPos, $this->pChartObject->GraphAreaY2 - $FloatingOffset, $BGColor);
237 }
238 if ($DrawXLines == ALL || in_array($AxisID, $DrawXLines)) {
239 $this->pChartObject->drawLine($XPos, $this->pChartObject->GraphAreaY1 + $FloatingOffset, $XPos, $this->pChartObject->GraphAreaY2 - $FloatingOffset, ["R" => $GridR, "G" => $GridG, "B" => $GridB, "Alpha" => $GridAlpha, "Ticks" => $GridTicks]);
240 }
241 if ($DrawSubTicks && $i != $AxisSettings["Rows"]) {
242 $this->pChartObject->drawLine($XPos + $SubTicksSize, $YPos - $InnerSubTickWidth, $XPos + $SubTicksSize, $YPos + $OuterSubTickWidth, ["R" => $SubTickR, "G" => $SubTickG, "B" => $SubTickB, "Alpha" => $SubTickAlpha]);
243 }
244 $this->pChartObject->drawLine($XPos, $YPos - $InnerTickWidth, $XPos, $YPos + $OuterTickWidth, ["R" => $TickR, "G" => $TickG, "B" => $TickB, "Alpha" => $TickAlpha]);
245 $Bounds = $this->pChartObject->drawText($XPos, $YPos + $OuterTickWidth + $LabelOffset, $Value, ["Angle" => $XLabelsRotation, "Align" => $LabelAlign]);
246 $TxtBottom = $YPos + 2 + $OuterTickWidth + 2 + ($Bounds[0]["Y"] - $Bounds[2]["Y"]);
247 $MaxBottom = max($MaxBottom, $TxtBottom);
248 $LastX = $XPos;
249 }
250 if (isset($AxisSettings["Name"])) {
251 $YPos = $MaxBottom + 2;
252 $XPos = $this->pChartObject->GraphAreaX1 + ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) / 2;
253 $Bounds = $this->pChartObject->drawText($XPos, $YPos, $AxisSettings["Name"], ["Align" => TEXT_ALIGN_TOPMIDDLE]);
254 $MaxBottom = $Bounds[0]["Y"];
255 $this->pDataObject->Data["GraphArea"]["Y2"] = $MaxBottom + $this->pChartObject->FontSize;
256 }
257 $AxisPos["B"] = $MaxBottom + $ScaleSpacing;
258 } elseif ($AxisSettings["Position"] == AXIS_POSITION_TOP) {
259 if ($XLabelsRotation == 0) {
260 $LabelAlign = TEXT_ALIGN_BOTTOMMIDDLE;
261 $LabelOffset = 2;
262 }
263 if ($XLabelsRotation > 0 && $XLabelsRotation < 190) {
264 $LabelAlign = TEXT_ALIGN_MIDDLELEFT;
265 $LabelOffset = 2;
266 }
267 if ($XLabelsRotation == 180) {
268 $LabelAlign = TEXT_ALIGN_TOPMIDDLE;
269 $LabelOffset = 5;
270 }
271 if ($XLabelsRotation > 180 && $XLabelsRotation < 360) {
272 $LabelAlign = TEXT_ALIGN_MIDDLERIGHT;
273 $LabelOffset = 5;
274 }
275 if ($Floating) {
276 $FloatingOffset = $YMargin;
277 $this->pChartObject->drawLine($this->pChartObject->GraphAreaX1 + $AxisSettings["Margin"], $AxisPos["T"], $this->pChartObject->GraphAreaX2 - $AxisSettings["Margin"], $AxisPos["T"], ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]);
278 } else {
279 $FloatingOffset = 0;
280 $this->pChartObject->drawLine($this->pChartObject->GraphAreaX1, $AxisPos["T"], $this->pChartObject->GraphAreaX2, $AxisPos["T"], ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]);
281 }
282 if ($DrawArrows) {
283 $this->pChartObject->drawArrow($this->pChartObject->GraphAreaX2 - $AxisSettings["Margin"], $AxisPos["T"], $this->pChartObject->GraphAreaX2 + $ArrowSize * 2, $AxisPos["T"], ["FillR" => $AxisR, "FillG" => $AxisG, "FillB" => $AxisB, "Size" => $ArrowSize]);
284 }
285 $Width = $this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $AxisSettings["Margin"] * 2;
286 $Step = $Width / $AxisSettings["Rows"];
287 $SubTicksSize = $Step / 2;
288 $MinTop = $AxisPos["T"];
289 $LastX = null;
290 for ($i = 0; $i <= $AxisSettings["Rows"]; $i++) {
291 $XPos = $this->pChartObject->GraphAreaX1 + $AxisSettings["Margin"] + $Step * $i;
292 $YPos = $AxisPos["T"];
293 $Value = $this->pChartObject->scaleFormat($AxisSettings["ScaleMin"] + $AxisSettings["RowHeight"] * $i, $AxisSettings["Display"], $AxisSettings["Format"], $AxisSettings["Unit"]);
294 if ($i % 2 == 1) {
295 $BGColor = ["R" => $BackgroundR1, "G" => $BackgroundG1, "B" => $BackgroundB1, "Alpha" => $BackgroundAlpha1];
296 } else {
297 $BGColor = ["R" => $BackgroundR2, "G" => $BackgroundG2, "B" => $BackgroundB2, "Alpha" => $BackgroundAlpha2];
298 }
299 if ($LastX != null && $CycleBackground && ($DrawXLines == ALL || in_array($AxisID, $DrawXLines))) {
300 $this->pChartObject->drawFilledRectangle($LastX, $this->pChartObject->GraphAreaY1 + $FloatingOffset, $XPos, $this->pChartObject->GraphAreaY2 - $FloatingOffset, $BGColor);
301 }
302 if ($DrawXLines == ALL || in_array($AxisID, $DrawXLines)) {
303 $this->pChartObject->drawLine($XPos, $this->pChartObject->GraphAreaY1 + $FloatingOffset, $XPos, $this->pChartObject->GraphAreaY2 - $FloatingOffset, ["R" => $GridR, "G" => $GridG, "B" => $GridB, "Alpha" => $GridAlpha, "Ticks" => $GridTicks]);
304 }
305 if ($DrawSubTicks && $i != $AxisSettings["Rows"]) {
306 $this->pChartObject->drawLine($XPos + $SubTicksSize, $YPos - $OuterSubTickWidth, $XPos + $SubTicksSize, $YPos + $InnerSubTickWidth, ["R" => $SubTickR, "G" => $SubTickG, "B" => $SubTickB, "Alpha" => $SubTickAlpha]);
307 }
308 $this->pChartObject->drawLine($XPos, $YPos - $OuterTickWidth, $XPos, $YPos + $InnerTickWidth, ["R" => $TickR, "G" => $TickG, "B" => $TickB, "Alpha" => $TickAlpha]);
309 $Bounds = $this->pChartObject->drawText($XPos, $YPos - $OuterTickWidth - $LabelOffset, $Value, ["Angle" => $XLabelsRotation, "Align" => $LabelAlign]);
310 $TxtBox = $YPos - $OuterTickWidth - 4 - ($Bounds[0]["Y"] - $Bounds[2]["Y"]);
311 $MinTop = min($MinTop, $TxtBox);
312 $LastX = $XPos;
313 }
314 if (isset($AxisSettings["Name"])) {
315 $YPos = $MinTop - 2;
316 $XPos = $this->pChartObject->GraphAreaX1 + ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) / 2;
317 $Bounds = $this->pChartObject->drawText($XPos, $YPos, $AxisSettings["Name"], ["Align" => TEXT_ALIGN_BOTTOMMIDDLE]);
318 $MinTop = $Bounds[2]["Y"];
319 $this->pDataObject->Data["GraphArea"]["Y1"] = $MinTop;
320 }
321 $AxisPos["T"] = $MinTop - $ScaleSpacing;
322 }
323 } elseif ($AxisSettings["Identity"] == AXIS_Y) {
324 if ($AxisSettings["Position"] == AXIS_POSITION_LEFT) {
325 if ($Floating) {
326 $FloatingOffset = $XMargin;
327 $this->pChartObject->drawLine($AxisPos["L"], $this->pChartObject->GraphAreaY1 + $AxisSettings["Margin"], $AxisPos["L"], $this->pChartObject->GraphAreaY2 - $AxisSettings["Margin"], ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]);
328 } else {
329 $FloatingOffset = 0;
330 $this->pChartObject->drawLine($AxisPos["L"], $this->pChartObject->GraphAreaY1, $AxisPos["L"], $this->pChartObject->GraphAreaY2, ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]);
331 }
332 if ($DrawArrows) {
333 $this->pChartObject->drawArrow($AxisPos["L"], $this->pChartObject->GraphAreaY1 + $AxisSettings["Margin"], $AxisPos["L"], $this->pChartObject->GraphAreaY1 - $ArrowSize * 2, ["FillR" => $AxisR, "FillG" => $AxisG, "FillB" => $AxisB, "Size" => $ArrowSize]);
334 }
335 $Height = $this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1 - $AxisSettings["Margin"] * 2;
336 $Step = $Height / $AxisSettings["Rows"];
337 $SubTicksSize = $Step / 2;
338 $MinLeft = $AxisPos["L"];
339 $LastY = null;
340 for ($i = 0; $i <= $AxisSettings["Rows"]; $i++) {
341 $YPos = $this->pChartObject->GraphAreaY2 - $AxisSettings["Margin"] - $Step * $i;
342 $XPos = $AxisPos["L"];
343 $Value = $this->pChartObject->scaleFormat($AxisSettings["ScaleMin"] + $AxisSettings["RowHeight"] * $i, $AxisSettings["Display"], $AxisSettings["Format"], $AxisSettings["Unit"]);
344 if ($i % 2 == 1) {
345 $BGColor = ["R" => $BackgroundR1, "G" => $BackgroundG1, "B" => $BackgroundB1, "Alpha" => $BackgroundAlpha1];
346 } else {
347 $BGColor = ["R" => $BackgroundR2, "G" => $BackgroundG2, "B" => $BackgroundB2, "Alpha" => $BackgroundAlpha2];
348 }
349 if ($LastY != null && $CycleBackground && ($DrawYLines == ALL || in_array($AxisID, $DrawYLines))) {
350 $this->pChartObject->drawFilledRectangle($this->pChartObject->GraphAreaX1 + $FloatingOffset, $LastY, $this->pChartObject->GraphAreaX2 - $FloatingOffset, $YPos, $BGColor);
351 }
352 if ($YPos != $this->pChartObject->GraphAreaY1 && $YPos != $this->pChartObject->GraphAreaY2 && ($DrawYLines == ALL || in_array($AxisID, $DrawYLines))) {
353 $this->pChartObject->drawLine($this->pChartObject->GraphAreaX1 + $FloatingOffset, $YPos, $this->pChartObject->GraphAreaX2 - $FloatingOffset, $YPos, ["R" => $GridR, "G" => $GridG, "B" => $GridB, "Alpha" => $GridAlpha, "Ticks" => $GridTicks]);
354 }
355 if ($DrawSubTicks && $i != $AxisSettings["Rows"]) {
356 $this->pChartObject->drawLine($XPos - $OuterSubTickWidth, $YPos - $SubTicksSize, $XPos + $InnerSubTickWidth, $YPos - $SubTicksSize, ["R" => $SubTickR, "G" => $SubTickG, "B" => $SubTickB, "Alpha" => $SubTickAlpha]);
357 }
358 $this->pChartObject->drawLine($XPos - $OuterTickWidth, $YPos, $XPos + $InnerTickWidth, $YPos, ["R" => $TickR, "G" => $TickG, "B" => $TickB, "Alpha" => $TickAlpha]);
359 $Bounds = $this->pChartObject->drawText($XPos - $OuterTickWidth - 2, $YPos, $Value, ["Align" => TEXT_ALIGN_MIDDLERIGHT]);
360 $TxtLeft = $XPos - $OuterTickWidth - 2 - ($Bounds[1]["X"] - $Bounds[0]["X"]);
361 $MinLeft = min($MinLeft, $TxtLeft);
362 $LastY = $YPos;
363 }
364 if (isset($AxisSettings["Name"])) {
365 $XPos = $MinLeft - 2;
366 $YPos = $this->pChartObject->GraphAreaY1 + ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) / 2;
367 $Bounds = $this->pChartObject->drawText($XPos, $YPos, $AxisSettings["Name"], ["Align" => TEXT_ALIGN_BOTTOMMIDDLE, "Angle" => 90]);
368 $MinLeft = $Bounds[2]["X"];
369 $this->pDataObject->Data["GraphArea"]["X1"] = $MinLeft;
370 }
371 $AxisPos["L"] = $MinLeft - $ScaleSpacing;
372 } elseif ($AxisSettings["Position"] == AXIS_POSITION_RIGHT) {
373 if ($Floating) {
374 $FloatingOffset = $XMargin;
375 $this->pChartObject->drawLine($AxisPos["R"], $this->pChartObject->GraphAreaY1 + $AxisSettings["Margin"], $AxisPos["R"], $this->pChartObject->GraphAreaY2 - $AxisSettings["Margin"], ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]);
376 } else {
377 $FloatingOffset = 0;
378 $this->pChartObject->drawLine($AxisPos["R"], $this->pChartObject->GraphAreaY1, $AxisPos["R"], $this->pChartObject->GraphAreaY2, ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]);
379 }
380 if ($DrawArrows) {
381 $this->pChartObject->drawArrow($AxisPos["R"], $this->pChartObject->GraphAreaY1 + $AxisSettings["Margin"], $AxisPos["R"], $this->pChartObject->GraphAreaY1 - $ArrowSize * 2, ["FillR" => $AxisR, "FillG" => $AxisG, "FillB" => $AxisB, "Size" => $ArrowSize]);
382 }
383 $Height = $this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1 - $AxisSettings["Margin"] * 2;
384 $Step = $Height / $AxisSettings["Rows"];
385 $SubTicksSize = $Step / 2;
386 $MaxLeft = $AxisPos["R"];
387 $LastY = null;
388 for ($i = 0; $i <= $AxisSettings["Rows"]; $i++) {
389 $YPos = $this->pChartObject->GraphAreaY2 - $AxisSettings["Margin"] - $Step * $i;
390 $XPos = $AxisPos["R"];
391 $Value = $this->pChartObject->scaleFormat($AxisSettings["ScaleMin"] + $AxisSettings["RowHeight"] * $i, $AxisSettings["Display"], $AxisSettings["Format"], $AxisSettings["Unit"]);
392 if ($i % 2 == 1) {
393 $BGColor = ["R" => $BackgroundR1, "G" => $BackgroundG1, "B" => $BackgroundB1, "Alpha" => $BackgroundAlpha1];
394 } else {
395 $BGColor = ["R" => $BackgroundR2, "G" => $BackgroundG2, "B" => $BackgroundB2, "Alpha" => $BackgroundAlpha2];
396 }
397 if ($LastY != null && $CycleBackground && ($DrawYLines == ALL || in_array($AxisID, $DrawYLines))) {
398 $this->pChartObject->drawFilledRectangle($this->pChartObject->GraphAreaX1 + $FloatingOffset, $LastY, $this->pChartObject->GraphAreaX2 - $FloatingOffset, $YPos, $BGColor);
399 }
400 if ($YPos != $this->pChartObject->GraphAreaY1 && $YPos != $this->pChartObject->GraphAreaY2 && ($DrawYLines == ALL || in_array($AxisID, $DrawYLines))) {
401 $this->pChartObject->drawLine($this->pChartObject->GraphAreaX1 + $FloatingOffset, $YPos, $this->pChartObject->GraphAreaX2 - $FloatingOffset, $YPos, ["R" => $GridR, "G" => $GridG, "B" => $GridB, "Alpha" => $GridAlpha, "Ticks" => $GridTicks]);
402 }
403 if ($DrawSubTicks && $i != $AxisSettings["Rows"]) {
404 $this->pChartObject->drawLine($XPos - $InnerSubTickWidth, $YPos - $SubTicksSize, $XPos + $OuterSubTickWidth, $YPos - $SubTicksSize, ["R" => $SubTickR, "G" => $SubTickG, "B" => $SubTickB, "Alpha" => $SubTickAlpha]);
405 }
406 $this->pChartObject->drawLine($XPos - $InnerTickWidth, $YPos, $XPos + $OuterTickWidth, $YPos, ["R" => $TickR, "G" => $TickG, "B" => $TickB, "Alpha" => $TickAlpha]);
407 $Bounds = $this->pChartObject->drawText($XPos + $OuterTickWidth + 2, $YPos, $Value, ["Align" => TEXT_ALIGN_MIDDLELEFT]);
408 $TxtLeft = $XPos + $OuterTickWidth + 2 + ($Bounds[1]["X"] - $Bounds[0]["X"]);
409 $MaxLeft = max($MaxLeft, $TxtLeft);
410 $LastY = $YPos;
411 }
412 if (isset($AxisSettings["Name"])) {
413 $XPos = $MaxLeft + 6;
414 $YPos = $this->pChartObject->GraphAreaY1 + ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) / 2;
415 $Bounds = $this->pChartObject->drawText($XPos, $YPos, $AxisSettings["Name"], ["Align" => TEXT_ALIGN_BOTTOMMIDDLE, "Angle" => 270]);
416 $MaxLeft = $Bounds[2]["X"];
417 $this->pDataObject->Data["GraphArea"]["X2"] = $MaxLeft + $this->pChartObject->FontSize;
418 }
419 $AxisPos["R"] = $MaxLeft + $ScaleSpacing;
420 }
421 }
422 }
423 $this->pDataObject->saveAxisConfig($Data["Axis"]);
424 }
425 /**
426 * Draw a scatter plot chart
427 * @param array $Format
428 */
429 public function drawScatterPlotChart($Format = null)
430 {
431 $PlotSize = isset($Format["PlotSize"]) ? $Format["PlotSize"] : 3;
432 $PlotBorder = isset($Format["PlotBorder"]) ? $Format["PlotBorder"] : \false;
433 $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 250;
434 $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 250;
435 $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 250;
436 $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 30;
437 $BorderSize = isset($Format["BorderSize"]) ? $Format["BorderSize"] : 1;
438 $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : \false;
439 $ImageMapTitle = isset($Format["ImageMapTitle"]) ? $Format["ImageMapTitle"] : null;
440 $Data = $this->pDataObject->getData();
441 $BorderColor = ["R" => $BorderR, "G" => $BorderG, "B" => $BorderB, "Alpha" => $BorderAlpha];
442 foreach ($Data["ScatterSeries"] as $Key => $Series) {
443 if ($Series["isDrawable"] == \true) {
444 $SerieX = $Series["X"];
445 $SerieValuesX = $Data["Series"][$SerieX]["Data"];
446 $SerieXAxis = $Data["Series"][$SerieX]["Axis"];
447 $SerieY = $Series["Y"];
448 $SerieValuesY = $Data["Series"][$SerieY]["Data"];
449 $SerieYAxis = $Data["Series"][$SerieY]["Axis"];
450 if ($ImageMapTitle == null) {
451 $Description = sprintf("%s / %s", $Data["Series"][$Series["X"]]["Description"], $Data["Series"][$Series["Y"]]["Description"]);
452 } else {
453 $Description = $ImageMapTitle;
454 }
455 if (isset($Series["Picture"]) && $Series["Picture"] != "") {
456 $Picture = $Series["Picture"];
457 list($PicWidth, $PicHeight, $PicType) = $this->pChartObject->getPicInfo($Picture);
458 } else {
459 $Picture = null;
460 }
461 $PosArrayX = $this->getPosArray($SerieValuesX, $SerieXAxis);
462 if (!is_array($PosArrayX)) {
463 $Value = $PosArrayX;
464 $PosArrayX = [];
465 $PosArrayX[0] = $Value;
466 }
467 $PosArrayY = $this->getPosArray($SerieValuesY, $SerieYAxis);
468 if (!is_array($PosArrayY)) {
469 $Value = $PosArrayY;
470 $PosArrayY = [];
471 $PosArrayY[0] = $Value;
472 }
473 $Color = ["R" => $Series["Color"]["R"], "G" => $Series["Color"]["G"], "B" => $Series["Color"]["B"], "Alpha" => $Series["Color"]["Alpha"]];
474 foreach ($PosArrayX as $Key => $Value) {
475 $X = $Value;
476 $Y = $PosArrayY[$Key];
477 if ($X != VOID && $Y != VOID) {
478 $RealValue = sprintf("%s / %s", round($Data["Series"][$Series["X"]]["Data"][$Key], 2), round($Data["Series"][$Series["Y"]]["Data"][$Key], 2));
479 if ($RecordImageMap) {
480 $this->pChartObject->addToImageMap("CIRCLE", sprintf("%s,%s,%s", floor($X), floor($Y), floor($PlotSize + $BorderSize)), $this->pChartObject->toHTMLColor($Series["Color"]["R"], $Series["Color"]["G"], $Series["Color"]["B"]), $Description, $RealValue);
481 }
482 if (isset($Series["Shape"])) {
483 $this->pChartObject->drawShape($X, $Y, $Series["Shape"], $PlotSize, $PlotBorder, $BorderSize, $Series["Color"]["R"], $Series["Color"]["G"], $Series["Color"]["B"], $Series["Color"]["Alpha"], $BorderR, $BorderG, $BorderB, $BorderAlpha);
484 } elseif ($Picture == null) {
485 if ($PlotBorder) {
486 $this->pChartObject->drawFilledCircle($X, $Y, $PlotSize + $BorderSize, $BorderColor);
487 }
488 $this->pChartObject->drawFilledCircle($X, $Y, $PlotSize, $Color);
489 } else {
490 $this->pChartObject->drawFromPicture($PicType, $Picture, $X - $PicWidth / 2, $Y - $PicHeight / 2);
491 }
492 }
493 }
494 }
495 }
496 }
497 /**
498 * Draw a scatter line chart
499 * @param array $Format
500 */
501 public function drawScatterLineChart($Format = null)
502 {
503 $Data = $this->pDataObject->getData();
504 $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : \false;
505 $ImageMapTitle = isset($Format["ImageMapTitle"]) ? $Format["ImageMapTitle"] : null;
506 $ImageMapPlotSize = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 10;
507 /* Parse all the series to draw */
508 foreach ($Data["ScatterSeries"] as $Key => $Series) {
509 if ($Series["isDrawable"] == \true) {
510 $SerieX = $Series["X"];
511 $SerieValuesX = $Data["Series"][$SerieX]["Data"];
512 $SerieXAxis = $Data["Series"][$SerieX]["Axis"];
513 $SerieY = $Series["Y"];
514 $SerieValuesY = $Data["Series"][$SerieY]["Data"];
515 $SerieYAxis = $Data["Series"][$SerieY]["Axis"];
516 $Ticks = $Series["Ticks"];
517 $Weight = $Series["Weight"];
518 if ($ImageMapTitle == null) {
519 $Description = sprintf("%s / %s", $Data["Series"][$Series["X"]]["Description"], $Data["Series"][$Series["Y"]]["Description"]);
520 } else {
521 $Description = $ImageMapTitle;
522 }
523 $PosArrayX = $this->getPosArray($SerieValuesX, $SerieXAxis);
524 if (!is_array($PosArrayX)) {
525 $Value = $PosArrayX;
526 $PosArrayX = [];
527 $PosArrayX[0] = $Value;
528 }
529 $PosArrayY = $this->getPosArray($SerieValuesY, $SerieYAxis);
530 if (!is_array($PosArrayY)) {
531 $Value = $PosArrayY;
532 $PosArrayY = [];
533 $PosArrayY[0] = $Value;
534 }
535 $Color = ["R" => $Series["Color"]["R"], "G" => $Series["Color"]["G"], "B" => $Series["Color"]["B"], "Alpha" => $Series["Color"]["Alpha"]];
536 if ($Ticks != 0) {
537 $Color["Ticks"] = $Ticks;
538 }
539 if ($Weight != 0) {
540 $Color["Weight"] = $Weight;
541 }
542 $LastX = VOID;
543 $LastY = VOID;
544 foreach ($PosArrayX as $Key => $Value) {
545 $X = $Value;
546 $Y = $PosArrayY[$Key];
547 if ($X != VOID && $Y != VOID) {
548 $RealValue = sprintf("%s / %s", round($Data["Series"][$Series["X"]]["Data"][$Key], 2), round($Data["Series"][$Series["Y"]]["Data"][$Key], 2));
549 if ($RecordImageMap) {
550 $this->pChartObject->addToImageMap("CIRCLE", sprintf("%s,%s,%s", floor($X), floor($Y), $ImageMapPlotSize), $this->pChartObject->toHTMLColor($Series["Color"]["R"], $Series["Color"]["G"], $Series["Color"]["B"]), $Description, $RealValue);
551 }
552 }
553 if ($X != VOID && $Y != VOID && $LastX != VOID && $LastY != VOID) {
554 $this->pChartObject->drawLine($LastX, $LastY, $X, $Y, $Color);
555 }
556 $LastX = $X;
557 $LastY = $Y;
558 }
559 }
560 }
561 }
562 /**
563 * Draw a scatter spline chart
564 * @param array $Format
565 */
566 public function drawScatterSplineChart(array $Format = [])
567 {
568 $Data = $this->pDataObject->getData();
569 $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : \false;
570 $ImageMapTitle = isset($Format["ImageMapTitle"]) ? $Format["ImageMapTitle"] : null;
571 $ImageMapPlotSize = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 10;
572 foreach ($Data["ScatterSeries"] as $Key => $Series) {
573 if ($Series["isDrawable"] == \true) {
574 $SerieX = $Series["X"];
575 $SerieValuesX = $Data["Series"][$SerieX]["Data"];
576 $SerieXAxis = $Data["Series"][$SerieX]["Axis"];
577 $SerieY = $Series["Y"];
578 $SerieValuesY = $Data["Series"][$SerieY]["Data"];
579 $SerieYAxis = $Data["Series"][$SerieY]["Axis"];
580 $Ticks = $Series["Ticks"];
581 $Weight = $Series["Weight"];
582 if ($ImageMapTitle == null) {
583 $Description = sprintf("%s / %s", $Data["Series"][$Series["X"]]["Description"], $Data["Series"][$Series["Y"]]["Description"]);
584 } else {
585 $Description = $ImageMapTitle;
586 }
587 $PosArrayX = $this->getPosArray($SerieValuesX, $SerieXAxis);
588 if (!is_array($PosArrayX)) {
589 $Value = $PosArrayX;
590 $PosArrayX = [];
591 $PosArrayX[0] = $Value;
592 }
593 $PosArrayY = $this->getPosArray($SerieValuesY, $SerieYAxis);
594 if (!is_array($PosArrayY)) {
595 $Value = $PosArrayY;
596 $PosArrayY = [];
597 $PosArrayY[0] = $Value;
598 }
599 $SplineSettings = ["R" => $Series["Color"]["R"], "G" => $Series["Color"]["G"], "B" => $Series["Color"]["B"], "Alpha" => $Series["Color"]["Alpha"]];
600 if ($Ticks != 0) {
601 $SplineSettings["Ticks"] = $Ticks;
602 }
603 if ($Weight != 0) {
604 $SplineSettings["Weight"] = $Weight;
605 }
606 $LastX = VOID;
607 $LastY = VOID;
608 $WayPoints = [];
609 $Forces = [];
610 foreach ($PosArrayX as $Key => $Value) {
611 $X = $Value;
612 $Y = $PosArrayY[$Key];
613 $Force = $this->pChartObject->getLength($LastX, $LastY, $X, $Y) / 5;
614 if ($X != VOID && $Y != VOID) {
615 $RealValue = sprintf("%s / %s", round($Data["Series"][$Series["X"]]["Data"][$Key], 2), round($Data["Series"][$Series["Y"]]["Data"][$Key], 2));
616 if ($RecordImageMap) {
617 $this->pChartObject->addToImageMap("CIRCLE", sprintf("%s,%s,%s", floor($X), floor($Y), $ImageMapPlotSize), $this->pChartObject->toHTMLColor($Series["Color"]["R"], $Series["Color"]["G"], $Series["Color"]["B"]), $Description, $RealValue);
618 }
619 }
620 if ($X != VOID && $Y != VOID) {
621 $WayPoints[] = [$X, $Y];
622 $Forces[] = $Force;
623 }
624 if ($Y == VOID || $X == VOID) {
625 $SplineSettings["Forces"] = $Forces;
626 $this->pChartObject->drawSpline($WayPoints, $SplineSettings);
627 $WayPoints = [];
628 $Forces = [];
629 }
630 $LastX = $X;
631 $LastY = $Y;
632 }
633 $SplineSettings["Forces"] = $Forces;
634 $this->pChartObject->drawSpline($WayPoints, $SplineSettings);
635 }
636 }
637 }
638 /**
639 * Return the scaled plot position
640 * @param mixed $Values
641 * @param string $AxisID
642 * @return mixed
643 */
644 public function getPosArray($Values, $AxisID)
645 {
646 $Data = $this->pDataObject->getData();
647 if (!is_array($Values)) {
648 $Values = [$Values];
649 }
650 if ($Data["Axis"][$AxisID]["Identity"] == AXIS_X) {
651 $Height = $this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $Data["Axis"][$AxisID]["Margin"] * 2;
652 $ScaleHeight = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"];
653 $Step = $Height / $ScaleHeight;
654 $Result = [];
655 foreach ($Values as $Key => $Value) {
656 if ($Value == VOID) {
657 $Result[] = VOID;
658 } else {
659 $Result[] = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"] + $Step * ($Value - $Data["Axis"][$AxisID]["ScaleMin"]);
660 }
661 }
662 } else {
663 $Height = $this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1 - $Data["Axis"][$AxisID]["Margin"] * 2;
664 $ScaleHeight = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"];
665 $Step = $Height / $ScaleHeight;
666 $Result = [];
667 foreach ($Values as $Key => $Value) {
668 if ($Value == VOID) {
669 $Result[] = VOID;
670 } else {
671 $Result[] = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"] - $Step * ($Value - $Data["Axis"][$AxisID]["ScaleMin"]);
672 }
673 }
674 }
675 return count($Result) == 1 ? reset($Result) : $Result;
676 }
677 /**
678 * Draw the legend of the active series
679 * @param int $X
680 * @param int $Y
681 * @param array $Format
682 */
683 public function drawScatterLegend($X, $Y, array $Format = [])
684 {
685 $Family = isset($Format["Family"]) ? $Format["Family"] : LEGEND_FAMILY_BOX;
686 $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName;
687 $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize;
688 $FontR = isset($Format["FontR"]) ? $Format["FontR"] : $this->pChartObject->FontColorR;
689 $FontG = isset($Format["FontG"]) ? $Format["FontG"] : $this->pChartObject->FontColorG;
690 $FontB = isset($Format["FontB"]) ? $Format["FontB"] : $this->pChartObject->FontColorB;
691 $BoxWidth = isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 5;
692 $BoxHeight = isset($Format["BoxHeight"]) ? $Format["BoxHeight"] : 5;
693 $IconAreaWidth = isset($Format["IconAreaWidth"]) ? $Format["IconAreaWidth"] : $BoxWidth;
694 $IconAreaHeight = isset($Format["IconAreaHeight"]) ? $Format["IconAreaHeight"] : $BoxHeight;
695 $XSpacing = isset($Format["XSpacing"]) ? $Format["XSpacing"] : 5;
696 $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5;
697 $R = isset($Format["R"]) ? $Format["R"] : 200;
698 $G = isset($Format["G"]) ? $Format["G"] : 200;
699 $B = isset($Format["B"]) ? $Format["B"] : 200;
700 $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
701 $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255;
702 $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255;
703 $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255;
704 $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : null;
705 $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND;
706 $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL;
707 if ($Surrounding != null) {
708 $BorderR = $R + $Surrounding;
709 $BorderG = $G + $Surrounding;
710 $BorderB = $B + $Surrounding;
711 }
712 $Data = $this->pDataObject->getData();
713 foreach ($Data["ScatterSeries"] as $Key => $Series) {
714 if ($Series["isDrawable"] == \true && isset($Series["Picture"])) {
715 list($PicWidth, $PicHeight) = $this->pChartObject->getPicInfo($Series["Picture"]);
716 if ($IconAreaWidth < $PicWidth) {
717 $IconAreaWidth = $PicWidth;
718 }
719 if ($IconAreaHeight < $PicHeight) {
720 $IconAreaHeight = $PicHeight;
721 }
722 }
723 }
724 $YStep = max($this->pChartObject->FontSize, $IconAreaHeight) + 5;
725 $XStep = $XSpacing;
726 $Boundaries = [];
727 $Boundaries["L"] = $X;
728 $Boundaries["T"] = $Y;
729 $Boundaries["R"] = 0;
730 $Boundaries["B"] = 0;
731 $vY = $Y;
732 $vX = $X;
733 foreach ($Data["ScatterSeries"] as $Key => $Series) {
734 if ($Series["isDrawable"] == \true) {
735 if ($Mode == LEGEND_VERTICAL) {
736 $BoxArray = $this->pChartObject->getTextBox($vX + $IconAreaWidth + 4, $vY + $IconAreaHeight / 2, $FontName, $FontSize, 0, $Series["Description"]);
737 if ($Boundaries["T"] > $BoxArray[2]["Y"] + $IconAreaHeight / 2) {
738 $Boundaries["T"] = $BoxArray[2]["Y"] + $IconAreaHeight / 2;
739 }
740 if ($Boundaries["R"] < $BoxArray[1]["X"] + 2) {
741 $Boundaries["R"] = $BoxArray[1]["X"] + 2;
742 }
743 if ($Boundaries["B"] < $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2) {
744 $Boundaries["B"] = $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2;
745 }
746 $Lines = preg_split("/\n/", $Series["Description"]);
747 $vY = $vY + max($this->pChartObject->FontSize * count($Lines), $IconAreaHeight) + 5;
748 } elseif ($Mode == LEGEND_HORIZONTAL) {
749 $Lines = preg_split("/\n/", $Series["Description"]);
750 $Width = [];
751 foreach ($Lines as $Key => $Value) {
752 $BoxArray = $this->pChartObject->getTextBox($vX + $IconAreaWidth + 6, $Y + $IconAreaHeight / 2 + ($this->pChartObject->FontSize + 3) * $Key, $FontName, $FontSize, 0, $Value);
753 if ($Boundaries["T"] > $BoxArray[2]["Y"] + $IconAreaHeight / 2) {
754 $Boundaries["T"] = $BoxArray[2]["Y"] + $IconAreaHeight / 2;
755 }
756 if ($Boundaries["R"] < $BoxArray[1]["X"] + 2) {
757 $Boundaries["R"] = $BoxArray[1]["X"] + 2;
758 }
759 if ($Boundaries["B"] < $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2) {
760 $Boundaries["B"] = $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2;
761 }
762 $Width[] = $BoxArray[1]["X"];
763 }
764 $vX = max($Width) + $XStep;
765 }
766 }
767 }
768 $vY = $vY - $YStep;
769 $vX = $vX - $XStep;
770 $TopOffset = $Y - $Boundaries["T"];
771 if ($Boundaries["B"] - ($vY + $IconAreaHeight) < $TopOffset) {
772 $Boundaries["B"] = $vY + $IconAreaHeight + $TopOffset;
773 }
774 if ($Style == LEGEND_ROUND) {
775 $this->pChartObject->drawRoundedFilledRectangle($Boundaries["L"] - $Margin, $Boundaries["T"] - $Margin, $Boundaries["R"] + $Margin, $Boundaries["B"] + $Margin, $Margin, ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha, "BorderR" => $BorderR, "BorderG" => $BorderG, "BorderB" => $BorderB]);
776 } elseif ($Style == LEGEND_BOX) {
777 $this->pChartObject->drawFilledRectangle($Boundaries["L"] - $Margin, $Boundaries["T"] - $Margin, $Boundaries["R"] + $Margin, $Boundaries["B"] + $Margin, ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha, "BorderR" => $BorderR, "BorderG" => $BorderG, "BorderB" => $BorderB]);
778 }
779 $RestoreShadow = $this->pChartObject->Shadow;
780 $this->pChartObject->Shadow = \false;
781 foreach ($Data["ScatterSeries"] as $Key => $Series) {
782 if ($Series["isDrawable"] == \true) {
783 $R = $Series["Color"]["R"];
784 $G = $Series["Color"]["G"];
785 $B = $Series["Color"]["B"];
786 $Ticks = $Series["Ticks"];
787 $Weight = $Series["Weight"];
788 if (isset($Series["Picture"])) {
789 $Picture = $Series["Picture"];
790 list($PicWidth, $PicHeight) = $this->pChartObject->getPicInfo($Picture);
791 $PicX = $X + $IconAreaWidth / 2;
792 $PicY = $Y + $IconAreaHeight / 2;
793 $this->pChartObject->drawFromPNG($PicX - $PicWidth / 2, $PicY - $PicHeight / 2, $Picture);
794 } else {
795 if ($Family == LEGEND_FAMILY_BOX) {
796 if ($BoxWidth != $IconAreaWidth) {
797 $XOffset = floor(($IconAreaWidth - $BoxWidth) / 2);
798 } else {
799 $XOffset = 0;
800 }
801 if ($BoxHeight != $IconAreaHeight) {
802 $YOffset = floor(($IconAreaHeight - $BoxHeight) / 2);
803 } else {
804 $YOffset = 0;
805 }
806 $this->pChartObject->drawFilledRectangle($X + 1 + $XOffset, $Y + 1 + $YOffset, $X + $BoxWidth + $XOffset + 1, $Y + $BoxHeight + 1 + $YOffset, ["R" => 0, "G" => 0, "B" => 0, "Alpha" => 20]);
807 $this->pChartObject->drawFilledRectangle($X + $XOffset, $Y + $YOffset, $X + $BoxWidth + $XOffset, $Y + $BoxHeight + $YOffset, ["R" => $R, "G" => $G, "B" => $B, "Surrounding" => 20]);
808 } elseif ($Family == LEGEND_FAMILY_CIRCLE) {
809 $this->pChartObject->drawFilledCircle($X + 1 + $IconAreaWidth / 2, $Y + 1 + $IconAreaHeight / 2, min($IconAreaHeight / 2, $IconAreaWidth / 2), ["R" => 0, "G" => 0, "B" => 0, "Alpha" => 20]);
810 $this->pChartObject->drawFilledCircle($X + $IconAreaWidth / 2, $Y + $IconAreaHeight / 2, min($IconAreaHeight / 2, $IconAreaWidth / 2), ["R" => $R, "G" => $G, "B" => $B, "Surrounding" => 20]);
811 } elseif ($Family == LEGEND_FAMILY_LINE) {
812 $this->pChartObject->drawLine($X + 1, $Y + 1 + $IconAreaHeight / 2, $X + 1 + $IconAreaWidth, $Y + 1 + $IconAreaHeight / 2, ["R" => 0, "G" => 0, "B" => 0, "Alpha" => 20, "Ticks" => $Ticks, "Weight" => $Weight]);
813 $this->pChartObject->drawLine($X, $Y + $IconAreaHeight / 2, $X + $IconAreaWidth, $Y + $IconAreaHeight / 2, ["R" => $R, "G" => $G, "B" => $B, "Ticks" => $Ticks, "Weight" => $Weight]);
814 }
815 }
816 if ($Mode == LEGEND_VERTICAL) {
817 $Lines = preg_split("/\n/", $Series["Description"]);
818 foreach ($Lines as $Key => $Value) {
819 $this->pChartObject->drawText($X + $IconAreaWidth + 4, $Y + $IconAreaHeight / 2 + ($this->pChartObject->FontSize + 3) * $Key, $Value, ["R" => $FontR, "G" => $FontG, "B" => $FontB, "Align" => TEXT_ALIGN_MIDDLELEFT]);
820 }
821 $Y = $Y + max($this->pChartObject->FontSize * count($Lines), $IconAreaHeight) + 5;
822 } elseif ($Mode == LEGEND_HORIZONTAL) {
823 $Lines = preg_split("/\n/", $Series["Description"]);
824 $Width = [];
825 foreach ($Lines as $Key => $Value) {
826 $BoxArray = $this->pChartObject->drawText($X + $IconAreaWidth + 4, $Y + $IconAreaHeight / 2 + ($this->pChartObject->FontSize + 3) * $Key, $Value, ["R" => $FontR, "G" => $FontG, "B" => $FontB, "Align" => TEXT_ALIGN_MIDDLELEFT]);
827 $Width[] = $BoxArray[1]["X"];
828 }
829 $X = max($Width) + 2 + $XStep;
830 }
831 }
832 }
833 $this->pChartObject->Shadow = $RestoreShadow;
834 }
835 /**
836 * Get the legend box size
837 * @param array $Format
838 * @return array
839 */
840 public function getScatterLegendSize(array $Format = [])
841 {
842 $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName;
843 $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize;
844 $BoxSize = isset($Format["BoxSize"]) ? $Format["BoxSize"] : 5;
845 $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5;
846 $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL;
847 $XSpacing = isset($Format["XSpacing"]) ? $Format["XSpacing"] : 5;
848 $YStep = max($this->pChartObject->FontSize, $BoxSize) + 5;
849 $XStep = $BoxSize + 5;
850 $X = 100;
851 $Y = 100;
852 $Data = $this->pDataObject->getData();
853 foreach ($Data["ScatterSeries"] as $Key => $Series) {
854 if ($Series["isDrawable"] == \true && isset($Series["Picture"])) {
855 list($PicWidth, $PicHeight) = $this->pChartObject->getPicInfo($Series["Picture"]);
856 if ($IconAreaWidth < $PicWidth) {
857 $IconAreaWidth = $PicWidth;
858 }
859 if ($IconAreaHeight < $PicHeight) {
860 $IconAreaHeight = $PicHeight;
861 }
862 }
863 }
864 $YStep = max($this->pChartObject->FontSize, $IconAreaHeight) + 5;
865 $XStep = $XSpacing;
866 $Boundaries = [];
867 $Boundaries["L"] = $X;
868 $Boundaries["T"] = $Y;
869 $Boundaries["R"] = 0;
870 $Boundaries["B"] = 0;
871 $vY = $Y;
872 $vX = $X;
873 foreach ($Data["ScatterSeries"] as $Key => $Series) {
874 if ($Series["isDrawable"] == \true) {
875 if ($Mode == LEGEND_VERTICAL) {
876 $BoxArray = $this->pChartObject->getTextBox($vX + $IconAreaWidth + 4, $vY + $IconAreaHeight / 2, $FontName, $FontSize, 0, $Series["Description"]);
877 if ($Boundaries["T"] > $BoxArray[2]["Y"] + $IconAreaHeight / 2) {
878 $Boundaries["T"] = $BoxArray[2]["Y"] + $IconAreaHeight / 2;
879 }
880 if ($Boundaries["R"] < $BoxArray[1]["X"] + 2) {
881 $Boundaries["R"] = $BoxArray[1]["X"] + 2;
882 }
883 if ($Boundaries["B"] < $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2) {
884 $Boundaries["B"] = $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2;
885 }
886 $Lines = preg_split("/\n/", $Series["Description"]);
887 $vY = $vY + max($this->pChartObject->FontSize * count($Lines), $IconAreaHeight) + 5;
888 } elseif ($Mode == LEGEND_HORIZONTAL) {
889 $Lines = preg_split("/\n/", $Series["Description"]);
890 $Width = [];
891 foreach ($Lines as $Key => $Value) {
892 $BoxArray = $this->pChartObject->getTextBox($vX + $IconAreaWidth + 6, $Y + $IconAreaHeight / 2 + ($this->pChartObject->FontSize + 3) * $Key, $FontName, $FontSize, 0, $Value);
893 if ($Boundaries["T"] > $BoxArray[2]["Y"] + $IconAreaHeight / 2) {
894 $Boundaries["T"] = $BoxArray[2]["Y"] + $IconAreaHeight / 2;
895 }
896 if ($Boundaries["R"] < $BoxArray[1]["X"] + 2) {
897 $Boundaries["R"] = $BoxArray[1]["X"] + 2;
898 }
899 if ($Boundaries["B"] < $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2) {
900 $Boundaries["B"] = $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2;
901 }
902 $Width[] = $BoxArray[1]["X"];
903 }
904 $vX = max($Width) + $XStep;
905 }
906 }
907 }
908 $vY = $vY - $YStep;
909 $vX = $vX - $XStep;
910 $TopOffset = $Y - $Boundaries["T"];
911 if ($Boundaries["B"] - ($vY + $BoxSize) < $TopOffset) {
912 $Boundaries["B"] = $vY + $BoxSize + $TopOffset;
913 }
914 $Width = $Boundaries["R"] + $Margin - ($Boundaries["L"] - $Margin);
915 $Height = $Boundaries["B"] + $Margin - ($Boundaries["T"] - $Margin);
916 return ["Width" => $Width, "Height" => $Height];
917 }
918 /**
919 * Draw the line of best fit
920 * @param array $Format
921 */
922 public function drawScatterBestFit(array $Format = [])
923 {
924 $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : 0;
925 $Data = $this->pDataObject->getData();
926 foreach ($Data["ScatterSeries"] as $Key => $Series) {
927 if ($Series["isDrawable"] == \true) {
928 $SerieX = $Series["X"];
929 $SerieXAxis = $Data["Series"][$SerieX]["Axis"];
930 $SerieY = $Series["Y"];
931 $SerieYAxis = $Data["Series"][$SerieY]["Axis"];
932 $Color = ["R" => $Series["Color"]["R"], "G" => $Series["Color"]["G"], "B" => $Series["Color"]["B"], "Alpha" => $Series["Color"]["Alpha"]];
933 $Color["Ticks"] = $Ticks;
934 $PosArrayX = $Data["Series"][$Series["X"]]["Data"];
935 $PosArrayY = $Data["Series"][$Series["Y"]]["Data"];
936 $Sxy = 0;
937 $Sx = 0;
938 $Sy = 0;
939 $Sxx = 0;
940 foreach ($PosArrayX as $Key => $Value) {
941 $X = $Value;
942 $Y = $PosArrayY[$Key];
943 $Sxy = $Sxy + $X * $Y;
944 $Sx = $Sx + $X;
945 $Sy = $Sy + $Y;
946 $Sxx = $Sxx + $X * $X;
947 }
948 $n = count($PosArrayX);
949 if ($n * $Sxx == $Sx * $Sx) {
950 $X1 = $this->getPosArray($Data["Axis"][$SerieXAxis]["ScaleMin"], $SerieXAxis);
951 $X2 = $X1;
952 $Y1 = $this->pChartObject->GraphAreaY1;
953 $Y2 = $this->pChartObject->GraphAreaY2;
954 } else {
955 $M = ($n * $Sxy - $Sx * $Sy) / ($n * $Sxx - $Sx * $Sx);
956 $B = ($Sy - $M * $Sx) / $n;
957 $X1 = $this->getPosArray($Data["Axis"][$SerieXAxis]["ScaleMin"], $SerieXAxis);
958 $Y1 = $this->getPosArray($M * $Data["Axis"][$SerieXAxis]["ScaleMin"] + $B, $SerieYAxis);
959 $X2 = $this->getPosArray($Data["Axis"][$SerieXAxis]["ScaleMax"], $SerieXAxis);
960 $Y2 = $this->getPosArray($M * $Data["Axis"][$SerieXAxis]["ScaleMax"] + $B, $SerieYAxis);
961 $RealM = -($Y2 - $Y1) / ($X2 - $X1);
962 if ($Y1 < $this->pChartObject->GraphAreaY1) {
963 $X1 = $X1 + ($this->pChartObject->GraphAreaY1 - $Y1 / $RealM);
964 $Y1 = $this->pChartObject->GraphAreaY1;
965 }
966 if ($Y1 > $this->pChartObject->GraphAreaY2) {
967 $X1 = $X1 + ($Y1 - $this->pChartObject->GraphAreaY2) / $RealM;
968 $Y1 = $this->pChartObject->GraphAreaY2;
969 }
970 if ($Y2 < $this->pChartObject->GraphAreaY1) {
971 $X2 = $X2 - ($this->pChartObject->GraphAreaY1 - $Y2) / $RealM;
972 $Y2 = $this->pChartObject->GraphAreaY1;
973 }
974 if ($Y2 > $this->pChartObject->GraphAreaY2) {
975 $X2 = $X2 - ($Y2 - $this->pChartObject->GraphAreaY2) / $RealM;
976 $Y2 = $this->pChartObject->GraphAreaY2;
977 }
978 }
979 $this->pChartObject->drawLine($X1, $Y1, $X2, $Y2, $Color);
980 }
981 }
982 }
983 /**
984 *
985 * @param string $ScatterSerieID
986 * @param mixed $Points
987 * @param array $Format
988 * @return null|int
989 */
990 public function writeScatterLabel($ScatterSerieID, $Points, array $Format = [])
991 {
992 $DrawPoint = isset($Format["DrawPoint"]) ? $Format["DrawPoint"] : LABEL_POINT_BOX;
993 $Decimals = isset($Format["Decimals"]) ? $Format["Decimals"] : null;
994 $Data = $this->pDataObject->getData();
995 if (!is_array($Points)) {
996 $Points = [$Points];
997 }
998 if (!isset($Data["ScatterSeries"][$ScatterSerieID])) {
999 return 0;
1000 }
1001 $Series = $Data["ScatterSeries"][$ScatterSerieID];
1002 $SerieX = $Series["X"];
1003 $SerieValuesX = $Data["Series"][$SerieX]["Data"];
1004 $SerieXAxis = $Data["Series"][$SerieX]["Axis"];
1005 $SerieY = $Series["Y"];
1006 $SerieValuesY = $Data["Series"][$SerieY]["Data"];
1007 $SerieYAxis = $Data["Series"][$SerieY]["Axis"];
1008 $PosArrayX = $this->getPosArray($SerieValuesX, $SerieXAxis);
1009 if (!is_array($PosArrayX)) {
1010 $Value = $PosArrayX;
1011 $PosArrayX = [];
1012 $PosArrayX[0] = $Value;
1013 }
1014 $PosArrayY = $this->getPosArray($SerieValuesY, $SerieYAxis);
1015 if (!is_array($PosArrayY)) {
1016 $Value = $PosArrayY;
1017 $PosArrayY = [];
1018 $PosArrayY[0] = $Value;
1019 }
1020 foreach ($Points as $Key => $Point) {
1021 if (isset($PosArrayX[$Point]) && isset($PosArrayY[$Point])) {
1022 $X = floor($PosArrayX[$Point]);
1023 $Y = floor($PosArrayY[$Point]);
1024 if ($DrawPoint == LABEL_POINT_CIRCLE) {
1025 $this->pChartObject->drawFilledCircle($X, $Y, 3, ["R" => 255, "G" => 255, "B" => 255, "BorderR" => 0, "BorderG" => 0, "BorderB" => 0]);
1026 } elseif ($DrawPoint == LABEL_POINT_BOX) {
1027 $this->pChartObject->drawFilledRectangle($X - 2, $Y - 2, $X + 2, $Y + 2, ["R" => 255, "G" => 255, "B" => 255, "BorderR" => 0, "BorderG" => 0, "BorderB" => 0]);
1028 }
1029 $Serie = [];
1030 $Serie["R"] = $Series["Color"]["R"];
1031 $Serie["G"] = $Series["Color"]["G"];
1032 $Serie["B"] = $Series["Color"]["B"];
1033 $Serie["Alpha"] = $Series["Color"]["Alpha"];
1034 $XAxisMode = $Data["Axis"][$SerieXAxis]["Display"];
1035 $XAxisFormat = $Data["Axis"][$SerieXAxis]["Format"];
1036 $XAxisUnit = $Data["Axis"][$SerieXAxis]["Unit"];
1037 if ($Decimals == null) {
1038 $XValue = $SerieValuesX[$Point];
1039 } else {
1040 $XValue = round($SerieValuesX[$Point], $Decimals);
1041 }
1042 $XValue = $this->pChartObject->scaleFormat($XValue, $XAxisMode, $XAxisFormat, $XAxisUnit);
1043 $YAxisMode = $Data["Axis"][$SerieYAxis]["Display"];
1044 $YAxisFormat = $Data["Axis"][$SerieYAxis]["Format"];
1045 $YAxisUnit = $Data["Axis"][$SerieYAxis]["Unit"];
1046 if ($Decimals == null) {
1047 $YValue = $SerieValuesY[$Point];
1048 } else {
1049 $YValue = round($SerieValuesY[$Point], $Decimals);
1050 }
1051 $YValue = $this->pChartObject->scaleFormat($YValue, $YAxisMode, $YAxisFormat, $YAxisUnit);
1052 $Caption = sprintf("%s / %s", $XValue, $YValue);
1053 if (isset($Series["Description"])) {
1054 $Description = $Series["Description"];
1055 } else {
1056 $Description = "No description";
1057 }
1058 $Series = [["Format" => $Serie, "Caption" => $Caption]];
1059 $this->pChartObject->drawLabelBox($X, $Y - 3, $Description, $Series, $Format);
1060 }
1061 }
1062 }
1063 /**
1064 * Draw a Scatter threshold
1065 * @param mixed $Value
1066 * @param array $Format
1067 * @return array
1068 */
1069 public function drawScatterThreshold($Value, array $Format = [])
1070 {
1071 $AxisID = isset($Format["AxisID"]) ? $Format["AxisID"] : 0;
1072 $R = isset($Format["R"]) ? $Format["R"] : 255;
1073 $G = isset($Format["G"]) ? $Format["G"] : 0;
1074 $B = isset($Format["B"]) ? $Format["B"] : 0;
1075 $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 50;
1076 $Weight = isset($Format["Weight"]) ? $Format["Weight"] : null;
1077 $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : 3;
1078 $Wide = isset($Format["Wide"]) ? $Format["Wide"] : \false;
1079 $WideFactor = isset($Format["WideFactor"]) ? $Format["WideFactor"] : 5;
1080 $WriteCaption = isset($Format["WriteCaption"]) ? $Format["WriteCaption"] : \false;
1081 $Caption = isset($Format["Caption"]) ? $Format["Caption"] : null;
1082 $CaptionAlign = isset($Format["CaptionAlign"]) ? $Format["CaptionAlign"] : CAPTION_LEFT_TOP;
1083 $CaptionOffset = isset($Format["CaptionOffset"]) ? $Format["CaptionOffset"] : 10;
1084 $CaptionR = isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255;
1085 $CaptionG = isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255;
1086 $CaptionB = isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255;
1087 $CaptionAlpha = isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100;
1088 $DrawBox = isset($Format["DrawBox"]) ? $Format["DrawBox"] : \true;
1089 $DrawBoxBorder = isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : \false;
1090 $BorderOffset = isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 5;
1091 $BoxRounded = isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : \true;
1092 $RoundedRadius = isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 3;
1093 $BoxR = isset($Format["BoxR"]) ? $Format["BoxR"] : 0;
1094 $BoxG = isset($Format["BoxG"]) ? $Format["BoxG"] : 0;
1095 $BoxB = isset($Format["BoxB"]) ? $Format["BoxB"] : 0;
1096 $BoxAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 20;
1097 $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : "";
1098 $BoxBorderR = isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 255;
1099 $BoxBorderG = isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 255;
1100 $BoxBorderB = isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 255;
1101 $BoxBorderAlpha = isset($Format["BoxBorderAlpha"]) ? $Format["BoxBorderAlpha"] : 100;
1102 $CaptionSettings = ["DrawBox" => $DrawBox, "DrawBoxBorder" => $DrawBoxBorder, "BorderOffset" => $BorderOffset, "BoxRounded" => $BoxRounded, "RoundedRadius" => $RoundedRadius, "BoxR" => $BoxR, "BoxG" => $BoxG, "BoxB" => $BoxB, "BoxAlpha" => $BoxAlpha, "BoxSurrounding" => $BoxSurrounding, "BoxBorderR" => $BoxBorderR, "BoxBorderG" => $BoxBorderG, "BoxBorderB" => $BoxBorderB, "BoxBorderAlpha" => $BoxBorderAlpha, "R" => $CaptionR, "G" => $CaptionG, "B" => $CaptionB, "Alpha" => $CaptionAlpha];
1103 if ($Caption == null) {
1104 $Caption = $Value;
1105 }
1106 $Data = $this->pDataObject->getData();
1107 if (!isset($Data["Axis"][$AxisID])) {
1108 return -1;
1109 }
1110 if ($Data["Axis"][$AxisID]["Identity"] == AXIS_Y) {
1111 $X1 = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"];
1112 $X2 = $this->pChartObject->GraphAreaX2 - $Data["Axis"][$AxisID]["Margin"];
1113 $Y = $this->getPosArray($Value, $AxisID);
1114 $this->pChartObject->drawLine($X1, $Y, $X2, $Y, ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha, "Ticks" => $Ticks, "Weight" => $Weight]);
1115 if ($Wide) {
1116 $this->pChartObject->drawLine($X1, $Y - 1, $X2, $Y - 1, ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha / $WideFactor, "Ticks" => $Ticks]);
1117 $this->pChartObject->drawLine($X1, $Y + 1, $X2, $Y + 1, ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha / $WideFactor, "Ticks" => $Ticks]);
1118 }
1119 if ($WriteCaption) {
1120 if ($CaptionAlign == CAPTION_LEFT_TOP) {
1121 $X = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"] + $CaptionOffset;
1122 $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLELEFT;
1123 } else {
1124 $X = $this->pChartObject->GraphAreaX2 - $Data["Axis"][$AxisID]["Margin"] - $CaptionOffset;
1125 $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLERIGHT;
1126 }
1127 $this->pChartObject->drawText($X, $Y, $Caption, $CaptionSettings);
1128 }
1129 return ["Y" => $Y];
1130 } elseif ($Data["Axis"][$AxisID]["Identity"] == AXIS_X) {
1131 $X = $this->getPosArray($Value, $AxisID);
1132 $Y1 = $this->pChartObject->GraphAreaY1 + $Data["Axis"][$AxisID]["Margin"];
1133 $Y2 = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"];
1134 $this->pChartObject->drawLine($X, $Y1, $X, $Y2, ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha, "Ticks" => $Ticks, "Weight" => $Weight]);
1135 if ($Wide) {
1136 $this->pChartObject->drawLine($X - 1, $Y1, $X - 1, $Y2, ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha / $WideFactor, "Ticks" => $Ticks]);
1137 $this->pChartObject->drawLine($X + 1, $Y1, $X + 1, $Y2, ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha / $WideFactor, "Ticks" => $Ticks]);
1138 }
1139 if ($WriteCaption) {
1140 if ($CaptionAlign == CAPTION_LEFT_TOP) {
1141 $Y = $this->pChartObject->GraphAreaY1 + $Data["Axis"][$AxisID]["Margin"] + $CaptionOffset;
1142 $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE;
1143 } else {
1144 $Y = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"] - $CaptionOffset;
1145 $CaptionSettings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE;
1146 }
1147 $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE;
1148 $this->pChartObject->drawText($X, $Y, $Caption, $CaptionSettings);
1149 }
1150 return ["X" => $X];
1151 }
1152 }
1153 /**
1154 * Draw a Scatter threshold area
1155 * @param int|float $Value1
1156 * @param int|float $Value2
1157 * @param array $Format
1158 * @return type
1159 */
1160 public function drawScatterThresholdArea($Value1, $Value2, array $Format = [])
1161 {
1162 $AxisID = isset($Format["AxisID"]) ? $Format["AxisID"] : 0;
1163 $R = isset($Format["R"]) ? $Format["R"] : 255;
1164 $G = isset($Format["G"]) ? $Format["G"] : 0;
1165 $B = isset($Format["B"]) ? $Format["B"] : 0;
1166 $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 20;
1167 $Border = isset($Format["Border"]) ? $Format["Border"] : \true;
1168 $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R;
1169 $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G;
1170 $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B;
1171 $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha + 20;
1172 $BorderTicks = isset($Format["BorderTicks"]) ? $Format["BorderTicks"] : 2;
1173 $AreaName = isset($Format["AreaName"]) ? $Format["AreaName"] : "La ouate de phoque";
1174 //null;
1175 $NameAngle = isset($Format["NameAngle"]) ? $Format["NameAngle"] : ZONE_NAME_ANGLE_AUTO;
1176 $NameR = isset($Format["NameR"]) ? $Format["NameR"] : 255;
1177 $NameG = isset($Format["NameG"]) ? $Format["NameG"] : 255;
1178 $NameB = isset($Format["NameB"]) ? $Format["NameB"] : 255;
1179 $NameAlpha = isset($Format["NameAlpha"]) ? $Format["NameAlpha"] : 100;
1180 $DisableShadowOnArea = isset($Format["DisableShadowOnArea"]) ? $Format["DisableShadowOnArea"] : \true;
1181 if ($Value1 > $Value2) {
1182 list($Value1, $Value2) = [$Value2, $Value1];
1183 }
1184 $RestoreShadow = $this->pChartObject->Shadow;
1185 if ($DisableShadowOnArea && $this->pChartObject->Shadow) {
1186 $this->pChartObject->Shadow = \false;
1187 }
1188 if ($BorderAlpha > 100) {
1189 $BorderAlpha = 100;
1190 }
1191 $Data = $this->pDataObject->getData();
1192 if (!isset($Data["Axis"][$AxisID])) {
1193 return -1;
1194 }
1195 if ($Data["Axis"][$AxisID]["Identity"] == AXIS_X) {
1196 $Y1 = $this->pChartObject->GraphAreaY1 + $Data["Axis"][$AxisID]["Margin"];
1197 $Y2 = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"];
1198 $X1 = $this->getPosArray($Value1, $AxisID);
1199 $X2 = $this->getPosArray($Value2, $AxisID);
1200 if ($X1 <= $this->pChartObject->GraphAreaX1) {
1201 $X1 = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"];
1202 }
1203 if ($X2 >= $this->pChartObject->GraphAreaX2) {
1204 $X2 = $this->pChartObject->GraphAreaX2 - $Data["Axis"][$AxisID]["Margin"];
1205 }
1206 $this->pChartObject->drawFilledRectangle($X1, $Y1, $X2, $Y2, ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha]);
1207 if ($Border) {
1208 $this->pChartObject->drawLine($X1, $Y1, $X1, $Y2, ["R" => $BorderR, "G" => $BorderG, "B" => $BorderB, "Alpha" => $BorderAlpha, "Ticks" => $BorderTicks]);
1209 $this->pChartObject->drawLine($X2, $Y1, $X2, $Y2, ["R" => $BorderR, "G" => $BorderG, "B" => $BorderB, "Alpha" => $BorderAlpha, "Ticks" => $BorderTicks]);
1210 }
1211 if ($AreaName != null) {
1212 $XPos = ($X2 - $X1) / 2 + $X1;
1213 $YPos = ($Y2 - $Y1) / 2 + $Y1;
1214 if ($NameAngle == ZONE_NAME_ANGLE_AUTO) {
1215 $TxtPos = $this->pChartObject->getTextBox($XPos, $YPos, $this->pChartObject->FontName, $this->pChartObject->FontSize, 0, $AreaName);
1216 $TxtWidth = $TxtPos[1]["X"] - $TxtPos[0]["X"];
1217 if (abs($X2 - $X1) > $TxtWidth) {
1218 $NameAngle = 0;
1219 } else {
1220 $NameAngle = 90;
1221 }
1222 }
1223 $this->pChartObject->Shadow = $RestoreShadow;
1224 $this->pChartObject->drawText($XPos, $YPos, $AreaName, ["R" => $NameR, "G" => $NameG, "B" => $NameB, "Alpha" => $NameAlpha, "Angle" => $NameAngle, "Align" => TEXT_ALIGN_MIDDLEMIDDLE]);
1225 if ($DisableShadowOnArea) {
1226 $this->pChartObject->Shadow = \false;
1227 }
1228 }
1229 $this->pChartObject->Shadow = $RestoreShadow;
1230 return ["X1" => $X1, "X2" => $X2];
1231 } elseif ($Data["Axis"][$AxisID]["Identity"] == AXIS_Y) {
1232 $X1 = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"];
1233 $X2 = $this->pChartObject->GraphAreaX2 - $Data["Axis"][$AxisID]["Margin"];
1234 $Y1 = $this->getPosArray($Value1, $AxisID);
1235 $Y2 = $this->getPosArray($Value2, $AxisID);
1236 if ($Y1 >= $this->pChartObject->GraphAreaY2) {
1237 $Y1 = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"];
1238 }
1239 if ($Y2 <= $this->pChartObject->GraphAreaY1) {
1240 $Y2 = $this->pChartObject->GraphAreaY1 + $Data["Axis"][$AxisID]["Margin"];
1241 }
1242 $this->pChartObject->drawFilledRectangle($X1, $Y1, $X2, $Y2, ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha]);
1243 if ($Border) {
1244 $this->pChartObject->drawLine($X1, $Y1, $X2, $Y1, ["R" => $BorderR, "G" => $BorderG, "B" => $BorderB, "Alpha" => $BorderAlpha, "Ticks" => $BorderTicks]);
1245 $this->pChartObject->drawLine($X1, $Y2, $X2, $Y2, ["R" => $BorderR, "G" => $BorderG, "B" => $BorderB, "Alpha" => $BorderAlpha, "Ticks" => $BorderTicks]);
1246 }
1247 if ($AreaName != null) {
1248 $XPos = ($X2 - $X1) / 2 + $X1;
1249 $YPos = ($Y2 - $Y1) / 2 + $Y1;
1250 $this->pChartObject->Shadow = $RestoreShadow;
1251 $this->pChartObject->drawText($YPos, $XPos, $AreaName, ["R" => $NameR, "G" => $NameG, "B" => $NameB, "Alpha" => $NameAlpha, "Angle" => 0, "Align" => TEXT_ALIGN_MIDDLEMIDDLE]);
1252 if ($DisableShadowOnArea) {
1253 ${$this}->pChartObject->Shadow = \false;
1254 }
1255 }
1256 $this->pChartObject->Shadow = $RestoreShadow;
1257 return ["Y1" => $Y1, "Y2" => $Y2];
1258 }
1259 }
1260 }
1261