1<?php
2
3namespace CpChart\Chart;
4
5use CpChart\Data;
6use CpChart\Image;
7use Exception;
8
9/**
10 *  Scatter - class to draw scatter charts
11 *
12 *  Version     : 2.1.4
13 *  Made by     : Jean-Damien POGOLOTTI
14 *  Last Update : 19/01/2014
15 *
16 *  This file can be distributed under the license you can find at :
17 *
18 *  http://www.pchart.net/license
19 *
20 *  You can find the whole class documentation on the pChart web site.
21 */
22class Scatter
23{
24    /**
25     * @var Image
26     */
27    public $pChartObject;
28
29    /**
30     * @var Data
31     */
32    public $pDataObject;
33
34    /**
35     * @param Image $pChartObject
36     * @param Data $pDataObject
37     */
38    public function __construct(Image $pChartObject, Data $pDataObject)
39    {
40        $this->pChartObject = $pChartObject;
41        $this->pDataObject = $pDataObject;
42    }
43
44    /**
45     * Prepare the scale
46     * @param array $Format
47     * @return null|int
48     * @throws Exception
49     */
50    public function drawScatterScale(array $Format = [])
51    {
52        $Mode = isset($Format["Mode"]) ? $Format["Mode"] : SCALE_MODE_FLOATING;
53        $Floating = isset($Format["Floating"]) ? $Format["Floating"] : false;
54        $XLabelsRotation = isset($Format["XLabelsRotation"]) ? $Format["XLabelsRotation"] : 90;
55        $MinDivHeight = isset($Format["MinDivHeight"]) ? $Format["MinDivHeight"] : 20;
56        $Factors = isset($Format["Factors"]) ? $Format["Factors"] : [1, 2, 5];
57        $ManualScale = isset($Format["ManualScale"])
58            ? $Format["ManualScale"] : ["0" => ["Min" => -100, "Max" => 100]]
59        ;
60        $XMargin = isset($Format["XMargin"]) ? $Format["XMargin"] : 0;
61        $YMargin = isset($Format["YMargin"]) ? $Format["YMargin"] : 0;
62        $ScaleSpacing = isset($Format["ScaleSpacing"]) ? $Format["ScaleSpacing"] : 15;
63        $InnerTickWidth = isset($Format["InnerTickWidth"]) ? $Format["InnerTickWidth"] : 2;
64        $OuterTickWidth = isset($Format["OuterTickWidth"]) ? $Format["OuterTickWidth"] : 2;
65        $DrawXLines = isset($Format["DrawXLines"]) ? $Format["DrawXLines"] : ALL;
66        $DrawYLines = isset($Format["DrawYLines"]) ? $Format["DrawYLines"] : ALL;
67        $GridTicks = isset($Format["GridTicks"]) ? $Format["GridTicks"] : 4;
68        $GridR = isset($Format["GridR"]) ? $Format["GridR"] : 255;
69        $GridG = isset($Format["GridG"]) ? $Format["GridG"] : 255;
70        $GridB = isset($Format["GridB"]) ? $Format["GridB"] : 255;
71        $GridAlpha = isset($Format["GridAlpha"]) ? $Format["GridAlpha"] : 40;
72        $AxisRo = isset($Format["AxisR"]) ? $Format["AxisR"] : 0;
73        $AxisGo = isset($Format["AxisG"]) ? $Format["AxisG"] : 0;
74        $AxisBo = isset($Format["AxisB"]) ? $Format["AxisB"] : 0;
75        $AxisAlpha = isset($Format["AxisAlpha"]) ? $Format["AxisAlpha"] : 100;
76        $TickRo = isset($Format["TickR"]) ? $Format["TickR"] : 0;
77        $TickGo = isset($Format["TickG"]) ? $Format["TickG"] : 0;
78        $TickBo = isset($Format["TickB"]) ? $Format["TickB"] : 0;
79        $TickAlpha = isset($Format["TickAlpha"]) ? $Format["TickAlpha"] : 100;
80        $DrawSubTicks = isset($Format["DrawSubTicks"]) ? $Format["DrawSubTicks"] : false;
81        $InnerSubTickWidth = isset($Format["InnerSubTickWidth"]) ? $Format["InnerSubTickWidth"] : 0;
82        $OuterSubTickWidth = isset($Format["OuterSubTickWidth"]) ? $Format["OuterSubTickWidth"] : 2;
83        $SubTickR = isset($Format["SubTickR"]) ? $Format["SubTickR"] : 255;
84        $SubTickG = isset($Format["SubTickG"]) ? $Format["SubTickG"] : 0;
85        $SubTickB = isset($Format["SubTickB"]) ? $Format["SubTickB"] : 0;
86        $SubTickAlpha = isset($Format["SubTickAlpha"]) ? $Format["SubTickAlpha"] : 100;
87        $XReleasePercent = isset($Format["XReleasePercent"]) ? $Format["XReleasePercent"] : 1;
88        $DrawArrows = isset($Format["DrawArrows"]) ? $Format["DrawArrows"] : false;
89        $ArrowSize = isset($Format["ArrowSize"]) ? $Format["ArrowSize"] : 8;
90        $CycleBackground = isset($Format["CycleBackground"]) ? $Format["CycleBackground"] : false;
91        $BackgroundR1 = isset($Format["BackgroundR1"]) ? $Format["BackgroundR1"] : 255;
92        $BackgroundG1 = isset($Format["BackgroundG1"]) ? $Format["BackgroundG1"] : 255;
93        $BackgroundB1 = isset($Format["BackgroundB1"]) ? $Format["BackgroundB1"] : 255;
94        $BackgroundAlpha1 = isset($Format["BackgroundAlpha1"]) ? $Format["BackgroundAlpha1"] : 10;
95        $BackgroundR2 = isset($Format["BackgroundR2"]) ? $Format["BackgroundR2"] : 230;
96        $BackgroundG2 = isset($Format["BackgroundG2"]) ? $Format["BackgroundG2"] : 230;
97        $BackgroundB2 = isset($Format["BackgroundB2"]) ? $Format["BackgroundB2"] : 230;
98        $BackgroundAlpha2 = isset($Format["BackgroundAlpha2"]) ? $Format["BackgroundAlpha2"] : 10;
99
100        /* Check if we have at least both one X and Y axis */
101        $GotXAxis = false;
102        $GotYAxis = false;
103        foreach ($this->pDataObject->Data["Axis"] as $AxisID => $AxisSettings) {
104            if ($AxisSettings["Identity"] == AXIS_X) {
105                $GotXAxis = true;
106            }
107            if ($AxisSettings["Identity"] == AXIS_Y) {
108                $GotYAxis = true;
109            }
110        }
111        if (!$GotXAxis) {
112            return SCATTER_MISSING_X_SERIE;
113        }
114        if (!$GotYAxis) {
115            return SCATTER_MISSING_Y_SERIE;
116        }
117
118        /* Skip a NOTICE event in case of an empty array */
119        if ($DrawYLines == NONE) {
120            $DrawYLines = ["zarma" => "31"];
121        }
122
123        $Data = $this->pDataObject->getData();
124
125        foreach ($Data["Axis"] as $AxisID => $AxisSettings) {
126            if ($AxisSettings["Identity"] == AXIS_X) {
127                $Width = $this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin * 2;
128            } else {
129                $Width = $this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1 - $YMargin * 2;
130            }
131
132            $AxisMin = ABSOLUTE_MAX;
133            $AxisMax = OUT_OF_SIGHT;
134            if ($Mode == SCALE_MODE_FLOATING) {
135                foreach ($Data["Series"] as $SerieID => $SerieParameter) {
136                    if ($SerieParameter["Axis"] == $AxisID
137                        && $Data["Series"][$SerieID]["isDrawable"]
138                    ) {
139                        $AxisMax = max($AxisMax, $Data["Series"][$SerieID]["Max"]);
140                        $AxisMin = min($AxisMin, $Data["Series"][$SerieID]["Min"]);
141                    }
142                }
143                $AutoMargin = (($AxisMax - $AxisMin) / 100) * $XReleasePercent;
144
145                $Data["Axis"][$AxisID]["Min"] = $AxisMin - $AutoMargin;
146                $Data["Axis"][$AxisID]["Max"] = $AxisMax + $AutoMargin;
147            } elseif ($Mode == SCALE_MODE_MANUAL) {
148                if (isset($ManualScale[$AxisID]["Min"])
149                    && isset($ManualScale[$AxisID]["Max"])
150                ) {
151                    $Data["Axis"][$AxisID]["Min"] = $ManualScale[$AxisID]["Min"];
152                    $Data["Axis"][$AxisID]["Max"] = $ManualScale[$AxisID]["Max"];
153                } else {
154                    throw new Exception("Manual scale boundaries not set.");
155                }
156            }
157
158            /* Full manual scale */
159            if (isset($ManualScale[$AxisID]["Rows"]) && isset($ManualScale[$AxisID]["RowHeight"])) {
160                $Scale = [
161                    "Rows" => $ManualScale[$AxisID]["Rows"],
162                    "RowHeight" => $ManualScale[$AxisID]["RowHeight"],
163                    "XMin" => $ManualScale[$AxisID]["Min"],
164                    "XMax" => $ManualScale[$AxisID]["Max"]
165                ];
166            } else {
167                $MaxDivs = floor($Width / $MinDivHeight);
168                $Scale = $this->pChartObject->computeScale(
169                    $Data["Axis"][$AxisID]["Min"],
170                    $Data["Axis"][$AxisID]["Max"],
171                    $MaxDivs,
172                    $Factors,
173                    $AxisID
174                );
175            }
176
177            $Data["Axis"][$AxisID]["Margin"] = $AxisSettings["Identity"] == AXIS_X ? $XMargin : $YMargin;
178            $Data["Axis"][$AxisID]["ScaleMin"] = $Scale["XMin"];
179            $Data["Axis"][$AxisID]["ScaleMax"] = $Scale["XMax"];
180            $Data["Axis"][$AxisID]["Rows"] = $Scale["Rows"];
181            $Data["Axis"][$AxisID]["RowHeight"] = $Scale["RowHeight"];
182
183            if (isset($Scale["Format"])) {
184                $Data["Axis"][$AxisID]["Format"] = $Scale["Format"];
185            }
186
187            if (!isset($Data["Axis"][$AxisID]["Display"])) {
188                $Data["Axis"][$AxisID]["Display"] = null;
189            }
190            if (!isset($Data["Axis"][$AxisID]["Format"])) {
191                $Data["Axis"][$AxisID]["Format"] = null;
192            }
193            if (!isset($Data["Axis"][$AxisID]["Unit"])) {
194                $Data["Axis"][$AxisID]["Unit"] = null;
195            }
196        }
197
198        /* Get the default font color */
199        $FontColorRo = $this->pChartObject->FontColorR;
200        $FontColorGo = $this->pChartObject->FontColorG;
201        $FontColorBo = $this->pChartObject->FontColorB;
202
203        /* Set the original boundaries */
204        $AxisPos["L"] = $this->pChartObject->GraphAreaX1;
205        $AxisPos["R"] = $this->pChartObject->GraphAreaX2;
206        $AxisPos["T"] = $this->pChartObject->GraphAreaY1;
207        $AxisPos["B"] = $this->pChartObject->GraphAreaY2;
208
209        foreach ($Data["Axis"] as $AxisID => $AxisSettings) {
210            if (isset($AxisSettings["Color"])) {
211                $AxisR = $AxisSettings["Color"]["R"];
212                $AxisG = $AxisSettings["Color"]["G"];
213                $AxisB = $AxisSettings["Color"]["B"];
214                $TickR = $AxisSettings["Color"]["R"];
215                $TickG = $AxisSettings["Color"]["G"];
216                $TickB = $AxisSettings["Color"]["B"];
217                $this->pChartObject->setFontProperties(
218                    [
219                        "R" => $AxisSettings["Color"]["R"],
220                        "G" => $AxisSettings["Color"]["G"],
221                        "B" => $AxisSettings["Color"]["B"]
222                    ]
223                );
224            } else {
225                $AxisR = $AxisRo;
226                $AxisG = $AxisGo;
227                $AxisB = $AxisBo;
228                $TickR = $TickRo;
229                $TickG = $TickGo;
230                $TickB = $TickBo;
231                $this->pChartObject->setFontProperties(
232                    ["R" => $FontColorRo, "G" => $FontColorGo, "B" => $FontColorBo]
233                );
234            }
235
236            if ($AxisSettings["Identity"] == AXIS_X) {
237                if ($AxisSettings["Position"] == AXIS_POSITION_BOTTOM) {
238                    if ($XLabelsRotation == 0) {
239                        $LabelAlign = TEXT_ALIGN_TOPMIDDLE;
240                        $LabelOffset = 2;
241                    }
242                    if ($XLabelsRotation > 0 && $XLabelsRotation < 190) {
243                        $LabelAlign = TEXT_ALIGN_MIDDLERIGHT;
244                        $LabelOffset = 5;
245                    }
246                    if ($XLabelsRotation == 180) {
247                        $LabelAlign = TEXT_ALIGN_BOTTOMMIDDLE;
248                        $LabelOffset = 5;
249                    }
250                    if ($XLabelsRotation > 180 && $XLabelsRotation < 360) {
251                        $LabelAlign = TEXT_ALIGN_MIDDLELEFT;
252                        $LabelOffset = 2;
253                    }
254
255                    if ($Floating) {
256                        $FloatingOffset = $YMargin;
257                        $this->pChartObject->drawLine(
258                            $this->pChartObject->GraphAreaX1 + $AxisSettings["Margin"],
259                            $AxisPos["B"],
260                            $this->pChartObject->GraphAreaX2 - $AxisSettings["Margin"],
261                            $AxisPos["B"],
262                            ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]
263                        );
264                    } else {
265                        $FloatingOffset = 0;
266                        $this->pChartObject->drawLine(
267                            $this->pChartObject->GraphAreaX1,
268                            $AxisPos["B"],
269                            $this->pChartObject->GraphAreaX2,
270                            $AxisPos["B"],
271                            ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]
272                        );
273                    }
274
275                    if ($DrawArrows) {
276                        $this->pChartObject->drawArrow(
277                            $this->pChartObject->GraphAreaX2 - $AxisSettings["Margin"],
278                            $AxisPos["B"],
279                            $this->pChartObject->GraphAreaX2 + ($ArrowSize * 2),
280                            $AxisPos["B"],
281                            ["FillR" => $AxisR, "FillG" => $AxisG, "FillB" => $AxisB, "Size" => $ArrowSize]
282                        );
283                    }
284
285                    $Width = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1)
286                        - $AxisSettings["Margin"] * 2
287                    ;
288                    $Step = $Width / $AxisSettings["Rows"];
289                    $SubTicksSize = $Step / 2;
290                    $MaxBottom = $AxisPos["B"];
291                    $LastX = null;
292                    for ($i = 0; $i <= $AxisSettings["Rows"]; $i++) {
293                        $XPos = $this->pChartObject->GraphAreaX1 + $AxisSettings["Margin"] + $Step * $i;
294                        $YPos = $AxisPos["B"];
295                        $Value = $this->pChartObject->scaleFormat(
296                            $AxisSettings["ScaleMin"] + $AxisSettings["RowHeight"] * $i,
297                            $AxisSettings["Display"],
298                            $AxisSettings["Format"],
299                            $AxisSettings["Unit"]
300                        );
301
302                        if ($i % 2 == 1) {
303                            $BGColor = [
304                                "R" => $BackgroundR1,
305                                "G" => $BackgroundG1,
306                                "B" => $BackgroundB1,
307                                "Alpha" => $BackgroundAlpha1
308                            ];
309                        } else {
310                            $BGColor = [
311                                "R" => $BackgroundR2,
312                                "G" => $BackgroundG2,
313                                "B" => $BackgroundB2,
314                                "Alpha" => $BackgroundAlpha2
315                            ];
316                        }
317                        if ($LastX != null
318                            && $CycleBackground
319                            && ($DrawXLines == ALL || in_array($AxisID, $DrawXLines))
320                        ) {
321                            $this->pChartObject->drawFilledRectangle(
322                                $LastX,
323                                $this->pChartObject->GraphAreaY1 + $FloatingOffset,
324                                $XPos,
325                                $this->pChartObject->GraphAreaY2 - $FloatingOffset,
326                                $BGColor
327                            );
328                        }
329
330                        if ($DrawXLines == ALL || in_array($AxisID, $DrawXLines)) {
331                            $this->pChartObject->drawLine(
332                                $XPos,
333                                $this->pChartObject->GraphAreaY1 + $FloatingOffset,
334                                $XPos,
335                                $this->pChartObject->GraphAreaY2 - $FloatingOffset,
336                                [
337                                    "R" => $GridR,
338                                    "G" => $GridG,
339                                    "B" => $GridB,
340                                    "Alpha" => $GridAlpha,
341                                    "Ticks" => $GridTicks
342                                ]
343                            );
344                        }
345                        if ($DrawSubTicks && $i != $AxisSettings["Rows"]) {
346                            $this->pChartObject->drawLine(
347                                $XPos + $SubTicksSize,
348                                $YPos - $InnerSubTickWidth,
349                                $XPos + $SubTicksSize,
350                                $YPos + $OuterSubTickWidth,
351                                [
352                                    "R" => $SubTickR,
353                                    "G" => $SubTickG,
354                                    "B" => $SubTickB,
355                                    "Alpha" => $SubTickAlpha
356                                ]
357                            );
358                        }
359                        $this->pChartObject->drawLine(
360                            $XPos,
361                            $YPos - $InnerTickWidth,
362                            $XPos,
363                            $YPos + $OuterTickWidth,
364                            ["R" => $TickR, "G" => $TickG, "B" => $TickB, "Alpha" => $TickAlpha]
365                        );
366                        $Bounds = $this->pChartObject->drawText(
367                            $XPos,
368                            $YPos + $OuterTickWidth + $LabelOffset,
369                            $Value,
370                            ["Angle" => $XLabelsRotation, "Align" => $LabelAlign]
371                        );
372                        $TxtBottom = $YPos + 2 + $OuterTickWidth + 2 + ($Bounds[0]["Y"] - $Bounds[2]["Y"]);
373                        $MaxBottom = max($MaxBottom, $TxtBottom);
374
375                        $LastX = $XPos;
376                    }
377
378                    if (isset($AxisSettings["Name"])) {
379                        $YPos = $MaxBottom + 2;
380                        $XPos = $this->pChartObject->GraphAreaX1
381                            + ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) / 2
382                        ;
383                        $Bounds = $this->pChartObject->drawText(
384                            $XPos,
385                            $YPos,
386                            $AxisSettings["Name"],
387                            ["Align" => TEXT_ALIGN_TOPMIDDLE]
388                        );
389                        $MaxBottom = $Bounds[0]["Y"];
390
391                        $this->pDataObject->Data["GraphArea"]["Y2"] = $MaxBottom + $this->pChartObject->FontSize;
392                    }
393
394                    $AxisPos["B"] = $MaxBottom + $ScaleSpacing;
395                } elseif ($AxisSettings["Position"] == AXIS_POSITION_TOP) {
396                    if ($XLabelsRotation == 0) {
397                        $LabelAlign = TEXT_ALIGN_BOTTOMMIDDLE;
398                        $LabelOffset = 2;
399                    }
400                    if ($XLabelsRotation > 0 && $XLabelsRotation < 190) {
401                        $LabelAlign = TEXT_ALIGN_MIDDLELEFT;
402                        $LabelOffset = 2;
403                    }
404                    if ($XLabelsRotation == 180) {
405                        $LabelAlign = TEXT_ALIGN_TOPMIDDLE;
406                        $LabelOffset = 5;
407                    }
408                    if ($XLabelsRotation > 180 && $XLabelsRotation < 360) {
409                        $LabelAlign = TEXT_ALIGN_MIDDLERIGHT;
410                        $LabelOffset = 5;
411                    }
412
413                    if ($Floating) {
414                        $FloatingOffset = $YMargin;
415                        $this->pChartObject->drawLine(
416                            $this->pChartObject->GraphAreaX1 + $AxisSettings["Margin"],
417                            $AxisPos["T"],
418                            $this->pChartObject->GraphAreaX2 - $AxisSettings["Margin"],
419                            $AxisPos["T"],
420                            ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]
421                        );
422                    } else {
423                        $FloatingOffset = 0;
424                        $this->pChartObject->drawLine(
425                            $this->pChartObject->GraphAreaX1,
426                            $AxisPos["T"],
427                            $this->pChartObject->GraphAreaX2,
428                            $AxisPos["T"],
429                            ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]
430                        );
431                    }
432
433                    if ($DrawArrows) {
434                        $this->pChartObject->drawArrow(
435                            $this->pChartObject->GraphAreaX2 - $AxisSettings["Margin"],
436                            $AxisPos["T"],
437                            $this->pChartObject->GraphAreaX2 + ($ArrowSize * 2),
438                            $AxisPos["T"],
439                            [
440                                "FillR" => $AxisR,
441                                "FillG" => $AxisG,
442                                "FillB" => $AxisB,
443                                "Size" => $ArrowSize
444                            ]
445                        );
446                    }
447
448                    $Width = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1)
449                        - $AxisSettings["Margin"] * 2
450                    ;
451                    $Step = $Width / $AxisSettings["Rows"];
452                    $SubTicksSize = $Step / 2;
453                    $MinTop = $AxisPos["T"];
454                    $LastX = null;
455                    for ($i = 0; $i <= $AxisSettings["Rows"]; $i++) {
456                        $XPos = $this->pChartObject->GraphAreaX1 + $AxisSettings["Margin"] + $Step * $i;
457                        $YPos = $AxisPos["T"];
458                        $Value = $this->pChartObject->scaleFormat(
459                            $AxisSettings["ScaleMin"] + $AxisSettings["RowHeight"] * $i,
460                            $AxisSettings["Display"],
461                            $AxisSettings["Format"],
462                            $AxisSettings["Unit"]
463                        );
464
465                        if ($i % 2 == 1) {
466                            $BGColor = [
467                                "R" => $BackgroundR1,
468                                "G" => $BackgroundG1,
469                                "B" => $BackgroundB1,
470                                "Alpha" => $BackgroundAlpha1
471                            ];
472                        } else {
473                            $BGColor = [
474                                "R" => $BackgroundR2,
475                                "G" => $BackgroundG2,
476                                "B" => $BackgroundB2,
477                                "Alpha" => $BackgroundAlpha2
478                            ];
479                        }
480                        if ($LastX != null
481                            && $CycleBackground
482                            && ($DrawXLines == ALL || in_array($AxisID, $DrawXLines))
483                        ) {
484                            $this->pChartObject->drawFilledRectangle(
485                                $LastX,
486                                $this->pChartObject->GraphAreaY1 + $FloatingOffset,
487                                $XPos,
488                                $this->pChartObject->GraphAreaY2 - $FloatingOffset,
489                                $BGColor
490                            );
491                        }
492
493                        if ($DrawXLines == ALL || in_array($AxisID, $DrawXLines)) {
494                            $this->pChartObject->drawLine(
495                                $XPos,
496                                $this->pChartObject->GraphAreaY1 + $FloatingOffset,
497                                $XPos,
498                                $this->pChartObject->GraphAreaY2 - $FloatingOffset,
499                                [
500                                    "R" => $GridR,
501                                    "G" => $GridG,
502                                    "B" => $GridB,
503                                    "Alpha" => $GridAlpha,
504                                    "Ticks" => $GridTicks
505                                ]
506                            );
507                        }
508
509                        if ($DrawSubTicks && $i != $AxisSettings["Rows"]) {
510                            $this->pChartObject->drawLine(
511                                $XPos + $SubTicksSize,
512                                $YPos - $OuterSubTickWidth,
513                                $XPos + $SubTicksSize,
514                                $YPos + $InnerSubTickWidth,
515                                [
516                                    "R" => $SubTickR,
517                                    "G" => $SubTickG,
518                                    "B" => $SubTickB,
519                                    "Alpha" => $SubTickAlpha
520                                ]
521                            );
522                        }
523                        $this->pChartObject->drawLine(
524                            $XPos,
525                            $YPos - $OuterTickWidth,
526                            $XPos,
527                            $YPos + $InnerTickWidth,
528                            ["R" => $TickR, "G" => $TickG, "B" => $TickB, "Alpha" => $TickAlpha]
529                        );
530                        $Bounds = $this->pChartObject->drawText(
531                            $XPos,
532                            $YPos - $OuterTickWidth - $LabelOffset,
533                            $Value,
534                            ["Angle" => $XLabelsRotation, "Align" => $LabelAlign]
535                        );
536                        $TxtBox = $YPos - $OuterTickWidth - 4 - ($Bounds[0]["Y"] - $Bounds[2]["Y"]);
537                        $MinTop = min($MinTop, $TxtBox);
538
539                        $LastX = $XPos;
540                    }
541
542                    if (isset($AxisSettings["Name"])) {
543                        $YPos = $MinTop - 2;
544                        $XPos = $this->pChartObject->GraphAreaX1
545                            + ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) / 2
546                        ;
547                        $Bounds = $this->pChartObject->drawText(
548                            $XPos,
549                            $YPos,
550                            $AxisSettings["Name"],
551                            ["Align" => TEXT_ALIGN_BOTTOMMIDDLE]
552                        );
553                        $MinTop = $Bounds[2]["Y"];
554
555                        $this->pDataObject->Data["GraphArea"]["Y1"] = $MinTop;
556                    }
557
558                    $AxisPos["T"] = $MinTop - $ScaleSpacing;
559                }
560            } elseif ($AxisSettings["Identity"] == AXIS_Y) {
561                if ($AxisSettings["Position"] == AXIS_POSITION_LEFT) {
562                    if ($Floating) {
563                        $FloatingOffset = $XMargin;
564                        $this->pChartObject->drawLine(
565                            $AxisPos["L"],
566                            $this->pChartObject->GraphAreaY1 + $AxisSettings["Margin"],
567                            $AxisPos["L"],
568                            $this->pChartObject->GraphAreaY2 - $AxisSettings["Margin"],
569                            ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]
570                        );
571                    } else {
572                        $FloatingOffset = 0;
573                        $this->pChartObject->drawLine(
574                            $AxisPos["L"],
575                            $this->pChartObject->GraphAreaY1,
576                            $AxisPos["L"],
577                            $this->pChartObject->GraphAreaY2,
578                            ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]
579                        );
580                    }
581
582                    if ($DrawArrows) {
583                        $this->pChartObject->drawArrow(
584                            $AxisPos["L"],
585                            $this->pChartObject->GraphAreaY1 + $AxisSettings["Margin"],
586                            $AxisPos["L"],
587                            $this->pChartObject->GraphAreaY1 - ($ArrowSize * 2),
588                            [
589                                "FillR" => $AxisR,
590                                "FillG" => $AxisG,
591                                "FillB" => $AxisB,
592                                "Size" => $ArrowSize
593                            ]
594                        );
595                    }
596
597                    $Height = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1)
598                        - $AxisSettings["Margin"] * 2
599                    ;
600                    $Step = $Height / $AxisSettings["Rows"];
601                    $SubTicksSize = $Step / 2;
602                    $MinLeft = $AxisPos["L"];
603                    $LastY = null;
604                    for ($i = 0; $i <= $AxisSettings["Rows"]; $i++) {
605                        $YPos = $this->pChartObject->GraphAreaY2 - $AxisSettings["Margin"] - $Step * $i;
606                        $XPos = $AxisPos["L"];
607                        $Value = $this->pChartObject->scaleFormat(
608                            $AxisSettings["ScaleMin"] + $AxisSettings["RowHeight"] * $i,
609                            $AxisSettings["Display"],
610                            $AxisSettings["Format"],
611                            $AxisSettings["Unit"]
612                        );
613
614                        if ($i % 2 == 1) {
615                            $BGColor = [
616                                "R" => $BackgroundR1,
617                                "G" => $BackgroundG1,
618                                "B" => $BackgroundB1,
619                                "Alpha" => $BackgroundAlpha1
620                            ];
621                        } else {
622                            $BGColor = [
623                                "R" => $BackgroundR2,
624                                "G" => $BackgroundG2,
625                                "B" => $BackgroundB2,
626                                "Alpha" => $BackgroundAlpha2
627                            ];
628                        }
629                        if ($LastY != null
630                            && $CycleBackground
631                            && ($DrawYLines == ALL || in_array($AxisID, $DrawYLines))
632                        ) {
633                            $this->pChartObject->drawFilledRectangle(
634                                $this->pChartObject->GraphAreaX1 + $FloatingOffset,
635                                $LastY,
636                                $this->pChartObject->GraphAreaX2 - $FloatingOffset,
637                                $YPos,
638                                $BGColor
639                            );
640                        }
641
642                        if (($YPos != $this->pChartObject->GraphAreaY1 && $YPos != $this->pChartObject->GraphAreaY2)
643                            && ($DrawYLines == ALL || in_array($AxisID, $DrawYLines))
644                        ) {
645                            $this->pChartObject->drawLine(
646                                $this->pChartObject->GraphAreaX1 + $FloatingOffset,
647                                $YPos,
648                                $this->pChartObject->GraphAreaX2 - $FloatingOffset,
649                                $YPos,
650                                [
651                                    "R" => $GridR,
652                                    "G" => $GridG,
653                                    "B" => $GridB,
654                                    "Alpha" => $GridAlpha,
655                                    "Ticks" => $GridTicks
656                                ]
657                            );
658                        }
659
660                        if ($DrawSubTicks && $i != $AxisSettings["Rows"]) {
661                            $this->pChartObject->drawLine(
662                                $XPos - $OuterSubTickWidth,
663                                $YPos - $SubTicksSize,
664                                $XPos + $InnerSubTickWidth,
665                                $YPos - $SubTicksSize,
666                                [
667                                    "R" => $SubTickR,
668                                    "G" => $SubTickG,
669                                    "B" => $SubTickB,
670                                    "Alpha" => $SubTickAlpha
671                                ]
672                            );
673                        }
674                        $this->pChartObject->drawLine(
675                            $XPos - $OuterTickWidth,
676                            $YPos,
677                            $XPos + $InnerTickWidth,
678                            $YPos,
679                            ["R" => $TickR, "G" => $TickG, "B" => $TickB, "Alpha" => $TickAlpha]
680                        );
681                        $Bounds = $this->pChartObject->drawText(
682                            $XPos - $OuterTickWidth - 2,
683                            $YPos,
684                            $Value,
685                            ["Align" => TEXT_ALIGN_MIDDLERIGHT]
686                        );
687                        $TxtLeft = $XPos - $OuterTickWidth - 2 - ($Bounds[1]["X"] - $Bounds[0]["X"]);
688                        $MinLeft = min($MinLeft, $TxtLeft);
689
690                        $LastY = $YPos;
691                    }
692
693                    if (isset($AxisSettings["Name"])) {
694                        $XPos = $MinLeft - 2;
695                        $YPos = $this->pChartObject->GraphAreaY1
696                            + ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) / 2
697                        ;
698                        $Bounds = $this->pChartObject->drawText(
699                            $XPos,
700                            $YPos,
701                            $AxisSettings["Name"],
702                            ["Align" => TEXT_ALIGN_BOTTOMMIDDLE, "Angle" => 90]
703                        );
704                        $MinLeft = $Bounds[2]["X"];
705
706                        $this->pDataObject->Data["GraphArea"]["X1"] = $MinLeft;
707                    }
708
709                    $AxisPos["L"] = $MinLeft - $ScaleSpacing;
710                } elseif ($AxisSettings["Position"] == AXIS_POSITION_RIGHT) {
711                    if ($Floating) {
712                        $FloatingOffset = $XMargin;
713                        $this->pChartObject->drawLine(
714                            $AxisPos["R"],
715                            $this->pChartObject->GraphAreaY1 + $AxisSettings["Margin"],
716                            $AxisPos["R"],
717                            $this->pChartObject->GraphAreaY2 - $AxisSettings["Margin"],
718                            ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]
719                        );
720                    } else {
721                        $FloatingOffset = 0;
722                        $this->pChartObject->drawLine(
723                            $AxisPos["R"],
724                            $this->pChartObject->GraphAreaY1,
725                            $AxisPos["R"],
726                            $this->pChartObject->GraphAreaY2,
727                            ["R" => $AxisR, "G" => $AxisG, "B" => $AxisB, "Alpha" => $AxisAlpha]
728                        );
729                    }
730
731                    if ($DrawArrows) {
732                        $this->pChartObject->drawArrow(
733                            $AxisPos["R"],
734                            $this->pChartObject->GraphAreaY1 + $AxisSettings["Margin"],
735                            $AxisPos["R"],
736                            $this->pChartObject->GraphAreaY1 - ($ArrowSize * 2),
737                            [
738                                "FillR" => $AxisR,
739                                "FillG" => $AxisG,
740                                "FillB" => $AxisB,
741                                "Size" => $ArrowSize
742                            ]
743                        );
744                    }
745
746                    $Height = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1)
747                        - $AxisSettings["Margin"] * 2
748                    ;
749                    $Step = $Height / $AxisSettings["Rows"];
750                    $SubTicksSize = $Step / 2;
751                    $MaxLeft = $AxisPos["R"];
752                    $LastY = null;
753                    for ($i = 0; $i <= $AxisSettings["Rows"]; $i++) {
754                        $YPos = $this->pChartObject->GraphAreaY2 - $AxisSettings["Margin"] - $Step * $i;
755                        $XPos = $AxisPos["R"];
756                        $Value = $this->pChartObject->scaleFormat(
757                            $AxisSettings["ScaleMin"] + $AxisSettings["RowHeight"] * $i,
758                            $AxisSettings["Display"],
759                            $AxisSettings["Format"],
760                            $AxisSettings["Unit"]
761                        );
762
763                        if ($i % 2 == 1) {
764                            $BGColor = [
765                                "R" => $BackgroundR1,
766                                "G" => $BackgroundG1,
767                                "B" => $BackgroundB1,
768                                "Alpha" => $BackgroundAlpha1
769                            ];
770                        } else {
771                            $BGColor = [
772                                "R" => $BackgroundR2,
773                                "G" => $BackgroundG2,
774                                "B" => $BackgroundB2,
775                                "Alpha" => $BackgroundAlpha2
776                            ];
777                        }
778                        if ($LastY != null
779                            && $CycleBackground
780                            && ($DrawYLines == ALL || in_array($AxisID, $DrawYLines))
781                        ) {
782                            $this->pChartObject->drawFilledRectangle(
783                                $this->pChartObject->GraphAreaX1 + $FloatingOffset,
784                                $LastY,
785                                $this->pChartObject->GraphAreaX2 - $FloatingOffset,
786                                $YPos,
787                                $BGColor
788                            );
789                        }
790
791                        if (($YPos != $this->pChartObject->GraphAreaY1
792                            && $YPos != $this->pChartObject->GraphAreaY2)
793                            && ($DrawYLines == ALL || in_array($AxisID, $DrawYLines))
794                        ) {
795                            $this->pChartObject->drawLine(
796                                $this->pChartObject->GraphAreaX1 + $FloatingOffset,
797                                $YPos,
798                                $this->pChartObject->GraphAreaX2 - $FloatingOffset,
799                                $YPos,
800                                [
801                                    "R" => $GridR,
802                                    "G" => $GridG,
803                                    "B" => $GridB,
804                                    "Alpha" => $GridAlpha,
805                                    "Ticks" => $GridTicks
806                                ]
807                            );
808                        }
809
810                        if ($DrawSubTicks && $i != $AxisSettings["Rows"]) {
811                            $this->pChartObject->drawLine(
812                                $XPos - $InnerSubTickWidth,
813                                $YPos - $SubTicksSize,
814                                $XPos + $OuterSubTickWidth,
815                                $YPos - $SubTicksSize,
816                                [
817                                    "R" => $SubTickR,
818                                    "G" => $SubTickG,
819                                    "B" => $SubTickB,
820                                    "Alpha" => $SubTickAlpha
821                                ]
822                            );
823                        }
824                        $this->pChartObject->drawLine(
825                            $XPos - $InnerTickWidth,
826                            $YPos,
827                            $XPos + $OuterTickWidth,
828                            $YPos,
829                            ["R" => $TickR, "G" => $TickG, "B" => $TickB, "Alpha" => $TickAlpha]
830                        );
831                        $Bounds = $this->pChartObject->drawText(
832                            $XPos + $OuterTickWidth + 2,
833                            $YPos,
834                            $Value,
835                            ["Align" => TEXT_ALIGN_MIDDLELEFT]
836                        );
837                        $TxtLeft = $XPos + $OuterTickWidth + 2 + ($Bounds[1]["X"] - $Bounds[0]["X"]);
838                        $MaxLeft = max($MaxLeft, $TxtLeft);
839
840                        $LastY = $YPos;
841                    }
842
843                    if (isset($AxisSettings["Name"])) {
844                        $XPos = $MaxLeft + 6;
845                        $YPos = $this->pChartObject->GraphAreaY1
846                            + ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) / 2
847                        ;
848                        $Bounds = $this->pChartObject->drawText(
849                            $XPos,
850                            $YPos,
851                            $AxisSettings["Name"],
852                            ["Align" => TEXT_ALIGN_BOTTOMMIDDLE, "Angle" => 270]
853                        );
854                        $MaxLeft = $Bounds[2]["X"];
855
856                        $this->pDataObject->Data["GraphArea"]["X2"] = $MaxLeft + $this->pChartObject->FontSize;
857                    }
858
859                    $AxisPos["R"] = $MaxLeft + $ScaleSpacing;
860                }
861            }
862        }
863
864        $this->pDataObject->saveAxisConfig($Data["Axis"]);
865    }
866
867    /**
868     * Draw a scatter plot chart
869     * @param array $Format
870     */
871    public function drawScatterPlotChart($Format = null)
872    {
873        $PlotSize = isset($Format["PlotSize"]) ? $Format["PlotSize"] : 3;
874        $PlotBorder = isset($Format["PlotBorder"]) ? $Format["PlotBorder"] : false;
875        $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 250;
876        $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 250;
877        $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 250;
878        $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 30;
879        $BorderSize = isset($Format["BorderSize"]) ? $Format["BorderSize"] : 1;
880        $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : false;
881        $ImageMapTitle = isset($Format["ImageMapTitle"]) ? $Format["ImageMapTitle"] : null;
882
883        $Data = $this->pDataObject->getData();
884
885        $BorderColor = ["R" => $BorderR, "G" => $BorderG, "B" => $BorderB, "Alpha" => $BorderAlpha];
886
887        foreach ($Data["ScatterSeries"] as $Key => $Series) {
888            if ($Series["isDrawable"] == true) {
889                $SerieX = $Series["X"];
890                $SerieValuesX = $Data["Series"][$SerieX]["Data"];
891                $SerieXAxis = $Data["Series"][$SerieX]["Axis"];
892                $SerieY = $Series["Y"];
893                $SerieValuesY = $Data["Series"][$SerieY]["Data"];
894                $SerieYAxis = $Data["Series"][$SerieY]["Axis"];
895
896                if ($ImageMapTitle == null) {
897                    $Description = sprintf(
898                        "%s / %s",
899                        $Data["Series"][$Series["X"]]["Description"],
900                        $Data["Series"][$Series["Y"]]["Description"]
901                    );
902                } else {
903                    $Description = $ImageMapTitle;
904                }
905
906                if (isset($Series["Picture"]) && $Series["Picture"] != "") {
907                    $Picture = $Series["Picture"];
908                    list($PicWidth, $PicHeight, $PicType) = $this->pChartObject->getPicInfo($Picture);
909                } else {
910                    $Picture = null;
911                }
912
913                $PosArrayX = $this->getPosArray($SerieValuesX, $SerieXAxis);
914                if (!is_array($PosArrayX)) {
915                    $Value = $PosArrayX;
916                    $PosArrayX = [];
917                    $PosArrayX[0] = $Value;
918                }
919                $PosArrayY = $this->getPosArray($SerieValuesY, $SerieYAxis);
920                if (!is_array($PosArrayY)) {
921                    $Value = $PosArrayY;
922                    $PosArrayY = [];
923                    $PosArrayY[0] = $Value;
924                }
925
926                $Color = [
927                    "R" => $Series["Color"]["R"],
928                    "G" => $Series["Color"]["G"],
929                    "B" => $Series["Color"]["B"],
930                    "Alpha" => $Series["Color"]["Alpha"]
931                ];
932
933                foreach ($PosArrayX as $Key => $Value) {
934                    $X = $Value;
935                    $Y = $PosArrayY[$Key];
936
937                    if ($X != VOID && $Y != VOID) {
938                        $RealValue = sprintf(
939                            "%s / %s",
940                            round($Data["Series"][$Series["X"]]["Data"][$Key], 2),
941                            round($Data["Series"][$Series["Y"]]["Data"][$Key], 2)
942                        );
943                        if ($RecordImageMap) {
944                            $this->pChartObject->addToImageMap(
945                                "CIRCLE",
946                                sprintf(
947                                    "%s,%s,%s",
948                                    floor($X),
949                                    floor($Y),
950                                    floor($PlotSize + $BorderSize)
951                                ),
952                                $this->pChartObject->toHTMLColor(
953                                    $Series["Color"]["R"],
954                                    $Series["Color"]["G"],
955                                    $Series["Color"]["B"]
956                                ),
957                                $Description,
958                                $RealValue
959                            );
960                        }
961
962                        if (isset($Series["Shape"])) {
963                            $this->pChartObject->drawShape(
964                                $X,
965                                $Y,
966                                $Series["Shape"],
967                                $PlotSize,
968                                $PlotBorder,
969                                $BorderSize,
970                                $Series["Color"]["R"],
971                                $Series["Color"]["G"],
972                                $Series["Color"]["B"],
973                                $Series["Color"]["Alpha"],
974                                $BorderR,
975                                $BorderG,
976                                $BorderB,
977                                $BorderAlpha
978                            );
979                        } elseif ($Picture == null) {
980                            if ($PlotBorder) {
981                                $this->pChartObject->drawFilledCircle(
982                                    $X,
983                                    $Y,
984                                    $PlotSize + $BorderSize,
985                                    $BorderColor
986                                );
987                            }
988                            $this->pChartObject->drawFilledCircle($X, $Y, $PlotSize, $Color);
989                        } else {
990                            $this->pChartObject->drawFromPicture(
991                                $PicType,
992                                $Picture,
993                                $X - $PicWidth / 2,
994                                $Y - $PicHeight / 2
995                            );
996                        }
997                    }
998                }
999            }
1000        }
1001    }
1002
1003    /**
1004     * Draw a scatter line chart
1005     * @param array $Format
1006     */
1007    public function drawScatterLineChart($Format = null)
1008    {
1009        $Data = $this->pDataObject->getData();
1010        $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : false;
1011        $ImageMapTitle = isset($Format["ImageMapTitle"]) ? $Format["ImageMapTitle"] : null;
1012        $ImageMapPlotSize = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 10;
1013
1014        /* Parse all the series to draw */
1015        foreach ($Data["ScatterSeries"] as $Key => $Series) {
1016            if ($Series["isDrawable"] == true) {
1017                $SerieX = $Series["X"];
1018                $SerieValuesX = $Data["Series"][$SerieX]["Data"];
1019                $SerieXAxis = $Data["Series"][$SerieX]["Axis"];
1020                $SerieY = $Series["Y"];
1021                $SerieValuesY = $Data["Series"][$SerieY]["Data"];
1022                $SerieYAxis = $Data["Series"][$SerieY]["Axis"];
1023                $Ticks = $Series["Ticks"];
1024                $Weight = $Series["Weight"];
1025
1026                if ($ImageMapTitle == null) {
1027                    $Description = sprintf(
1028                        "%s / %s",
1029                        $Data["Series"][$Series["X"]]["Description"],
1030                        $Data["Series"][$Series["Y"]]["Description"]
1031                    );
1032                } else {
1033                    $Description = $ImageMapTitle;
1034                }
1035
1036                $PosArrayX = $this->getPosArray($SerieValuesX, $SerieXAxis);
1037                if (!is_array($PosArrayX)) {
1038                    $Value = $PosArrayX;
1039                    $PosArrayX = [];
1040                    $PosArrayX[0] = $Value;
1041                }
1042                $PosArrayY = $this->getPosArray($SerieValuesY, $SerieYAxis);
1043                if (!is_array($PosArrayY)) {
1044                    $Value = $PosArrayY;
1045                    $PosArrayY = [];
1046                    $PosArrayY[0] = $Value;
1047                }
1048
1049                $Color = [
1050                    "R" => $Series["Color"]["R"],
1051                    "G" => $Series["Color"]["G"],
1052                    "B" => $Series["Color"]["B"],
1053                    "Alpha" => $Series["Color"]["Alpha"]
1054                ];
1055                if ($Ticks != 0) {
1056                    $Color["Ticks"] = $Ticks;
1057                }
1058                if ($Weight != 0) {
1059                    $Color["Weight"] = $Weight;
1060                }
1061
1062                $LastX = VOID;
1063                $LastY = VOID;
1064                foreach ($PosArrayX as $Key => $Value) {
1065                    $X = $Value;
1066                    $Y = $PosArrayY[$Key];
1067
1068                    if ($X != VOID && $Y != VOID) {
1069                        $RealValue = sprintf(
1070                            "%s / %s",
1071                            round($Data["Series"][$Series["X"]]["Data"][$Key], 2),
1072                            round($Data["Series"][$Series["Y"]]["Data"][$Key], 2)
1073                        );
1074                        if ($RecordImageMap) {
1075                            $this->pChartObject->addToImageMap(
1076                                "CIRCLE",
1077                                sprintf("%s,%s,%s", floor($X), floor($Y), $ImageMapPlotSize),
1078                                $this->pChartObject->toHTMLColor(
1079                                    $Series["Color"]["R"],
1080                                    $Series["Color"]["G"],
1081                                    $Series["Color"]["B"]
1082                                ),
1083                                $Description,
1084                                $RealValue
1085                            );
1086                        }
1087                    }
1088
1089                    if ($X != VOID && $Y != VOID && $LastX != VOID && $LastY != VOID) {
1090                        $this->pChartObject->drawLine($LastX, $LastY, $X, $Y, $Color);
1091                    }
1092                    $LastX = $X;
1093                    $LastY = $Y;
1094                }
1095            }
1096        }
1097    }
1098
1099    /**
1100     * Draw a scatter spline chart
1101     * @param array $Format
1102     */
1103    public function drawScatterSplineChart(array $Format = [])
1104    {
1105        $Data = $this->pDataObject->getData();
1106        $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : false;
1107        $ImageMapTitle = isset($Format["ImageMapTitle"]) ? $Format["ImageMapTitle"] : null;
1108        $ImageMapPlotSize = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 10;
1109
1110        foreach ($Data["ScatterSeries"] as $Key => $Series) {
1111            if ($Series["isDrawable"] == true) {
1112                $SerieX = $Series["X"];
1113                $SerieValuesX = $Data["Series"][$SerieX]["Data"];
1114                $SerieXAxis = $Data["Series"][$SerieX]["Axis"];
1115                $SerieY = $Series["Y"];
1116                $SerieValuesY = $Data["Series"][$SerieY]["Data"];
1117                $SerieYAxis = $Data["Series"][$SerieY]["Axis"];
1118                $Ticks = $Series["Ticks"];
1119                $Weight = $Series["Weight"];
1120
1121                if ($ImageMapTitle == null) {
1122                    $Description = sprintf(
1123                        "%s / %s",
1124                        $Data["Series"][$Series["X"]]["Description"],
1125                        $Data["Series"][$Series["Y"]]["Description"]
1126                    );
1127                } else {
1128                    $Description = $ImageMapTitle;
1129                }
1130
1131                $PosArrayX = $this->getPosArray($SerieValuesX, $SerieXAxis);
1132                if (!is_array($PosArrayX)) {
1133                    $Value = $PosArrayX;
1134                    $PosArrayX = [];
1135                    $PosArrayX[0] = $Value;
1136                }
1137                $PosArrayY = $this->getPosArray($SerieValuesY, $SerieYAxis);
1138                if (!is_array($PosArrayY)) {
1139                    $Value = $PosArrayY;
1140                    $PosArrayY = [];
1141                    $PosArrayY[0] = $Value;
1142                }
1143
1144                $SplineSettings = [
1145                    "R" => $Series["Color"]["R"],
1146                    "G" => $Series["Color"]["G"],
1147                    "B" => $Series["Color"]["B"],
1148                    "Alpha" => $Series["Color"]["Alpha"]
1149                ];
1150                if ($Ticks != 0) {
1151                    $SplineSettings["Ticks"] = $Ticks;
1152                }
1153                if ($Weight != 0) {
1154                    $SplineSettings["Weight"] = $Weight;
1155                }
1156
1157                $LastX = VOID;
1158                $LastY = VOID;
1159                $WayPoints = [];
1160                $Forces = [];
1161                foreach ($PosArrayX as $Key => $Value) {
1162                    $X = $Value;
1163                    $Y = $PosArrayY[$Key];
1164                    $Force = $this->pChartObject->getLength($LastX, $LastY, $X, $Y) / 5;
1165
1166                    if ($X != VOID && $Y != VOID) {
1167                        $RealValue = sprintf(
1168                            "%s / %s",
1169                            round($Data["Series"][$Series["X"]]["Data"][$Key], 2),
1170                            round($Data["Series"][$Series["Y"]]["Data"][$Key], 2)
1171                        );
1172                        if ($RecordImageMap) {
1173                            $this->pChartObject->addToImageMap(
1174                                "CIRCLE",
1175                                sprintf("%s,%s,%s", floor($X), floor($Y), $ImageMapPlotSize),
1176                                $this->pChartObject->toHTMLColor(
1177                                    $Series["Color"]["R"],
1178                                    $Series["Color"]["G"],
1179                                    $Series["Color"]["B"]
1180                                ),
1181                                $Description,
1182                                $RealValue
1183                            );
1184                        }
1185                    }
1186
1187                    if ($X != VOID && $Y != VOID) {
1188                        $WayPoints[] = [$X, $Y];
1189                        $Forces[] = $Force;
1190                    }
1191
1192                    if ($Y == VOID || $X == VOID) {
1193                        $SplineSettings["Forces"] = $Forces;
1194                        $this->pChartObject->drawSpline($WayPoints, $SplineSettings);
1195                        $WayPoints = [];
1196                        $Forces = [];
1197                    }
1198
1199                    $LastX = $X;
1200                    $LastY = $Y;
1201                }
1202                $SplineSettings["Forces"] = $Forces;
1203                $this->pChartObject->drawSpline($WayPoints, $SplineSettings);
1204            }
1205        }
1206    }
1207
1208    /**
1209     * Return the scaled plot position
1210     * @param mixed $Values
1211     * @param string $AxisID
1212     * @return mixed
1213     */
1214    public function getPosArray($Values, $AxisID)
1215    {
1216        $Data = $this->pDataObject->getData();
1217
1218        if (!is_array($Values)) {
1219            $Values = [$Values];
1220        }
1221
1222        if ($Data["Axis"][$AxisID]["Identity"] == AXIS_X) {
1223            $Height = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1)
1224                - $Data["Axis"][$AxisID]["Margin"] * 2
1225            ;
1226            $ScaleHeight = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"];
1227            $Step = $Height / $ScaleHeight;
1228
1229            $Result = [];
1230            foreach ($Values as $Key => $Value) {
1231                if ($Value == VOID) {
1232                    $Result[] = VOID;
1233                } else {
1234                    $Result[] = $this->pChartObject->GraphAreaX1
1235                        + $Data["Axis"][$AxisID]["Margin"]
1236                        + ($Step * ($Value - $Data["Axis"][$AxisID]["ScaleMin"]))
1237                    ;
1238                }
1239            }
1240        } else {
1241            $Height = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1)
1242                - $Data["Axis"][$AxisID]["Margin"] * 2
1243            ;
1244            $ScaleHeight = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"];
1245            $Step = $Height / $ScaleHeight;
1246
1247            $Result = [];
1248            foreach ($Values as $Key => $Value) {
1249                if ($Value == VOID) {
1250                    $Result[] = VOID;
1251                } else {
1252                    $Result[] = $this->pChartObject->GraphAreaY2
1253                        - $Data["Axis"][$AxisID]["Margin"]
1254                        - ($Step * ($Value - $Data["Axis"][$AxisID]["ScaleMin"]))
1255                    ;
1256                }
1257            }
1258        }
1259        return count($Result) == 1 ? reset($Result) : $Result;
1260    }
1261
1262    /**
1263     * Draw the legend of the active series
1264     * @param int $X
1265     * @param int $Y
1266     * @param array $Format
1267     */
1268    public function drawScatterLegend($X, $Y, array $Format = [])
1269    {
1270        $Family = isset($Format["Family"]) ? $Format["Family"] : LEGEND_FAMILY_BOX;
1271        $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName;
1272        $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize;
1273        $FontR = isset($Format["FontR"]) ? $Format["FontR"] : $this->pChartObject->FontColorR;
1274        $FontG = isset($Format["FontG"]) ? $Format["FontG"] : $this->pChartObject->FontColorG;
1275        $FontB = isset($Format["FontB"]) ? $Format["FontB"] : $this->pChartObject->FontColorB;
1276        $BoxWidth = isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 5;
1277        $BoxHeight = isset($Format["BoxHeight"]) ? $Format["BoxHeight"] : 5;
1278        $IconAreaWidth = isset($Format["IconAreaWidth"]) ? $Format["IconAreaWidth"] : $BoxWidth;
1279        $IconAreaHeight = isset($Format["IconAreaHeight"]) ? $Format["IconAreaHeight"] : $BoxHeight;
1280        $XSpacing = isset($Format["XSpacing"]) ? $Format["XSpacing"] : 5;
1281        $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5;
1282        $R = isset($Format["R"]) ? $Format["R"] : 200;
1283        $G = isset($Format["G"]) ? $Format["G"] : 200;
1284        $B = isset($Format["B"]) ? $Format["B"] : 200;
1285        $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
1286        $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255;
1287        $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255;
1288        $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255;
1289        $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : null;
1290        $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND;
1291        $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL;
1292
1293        if ($Surrounding != null) {
1294            $BorderR = $R + $Surrounding;
1295            $BorderG = $G + $Surrounding;
1296            $BorderB = $B + $Surrounding;
1297        }
1298
1299        $Data = $this->pDataObject->getData();
1300
1301        foreach ($Data["ScatterSeries"] as $Key => $Series) {
1302            if ($Series["isDrawable"] == true && isset($Series["Picture"])) {
1303                list($PicWidth, $PicHeight) = $this->pChartObject->getPicInfo($Series["Picture"]);
1304                if ($IconAreaWidth < $PicWidth) {
1305                    $IconAreaWidth = $PicWidth;
1306                }
1307                if ($IconAreaHeight < $PicHeight) {
1308                    $IconAreaHeight = $PicHeight;
1309                }
1310            }
1311        }
1312
1313        $YStep = max($this->pChartObject->FontSize, $IconAreaHeight) + 5;
1314        $XStep = $XSpacing;
1315
1316        $Boundaries = [];
1317        $Boundaries["L"] = $X;
1318        $Boundaries["T"] = $Y;
1319        $Boundaries["R"] = 0;
1320        $Boundaries["B"] = 0;
1321        $vY = $Y;
1322        $vX = $X;
1323        foreach ($Data["ScatterSeries"] as $Key => $Series) {
1324            if ($Series["isDrawable"] == true) {
1325                if ($Mode == LEGEND_VERTICAL) {
1326                    $BoxArray = $this->pChartObject->getTextBox(
1327                        $vX + $IconAreaWidth + 4,
1328                        $vY + $IconAreaHeight / 2,
1329                        $FontName,
1330                        $FontSize,
1331                        0,
1332                        $Series["Description"]
1333                    );
1334
1335                    if ($Boundaries["T"] > $BoxArray[2]["Y"] + $IconAreaHeight / 2) {
1336                        $Boundaries["T"] = $BoxArray[2]["Y"] + $IconAreaHeight / 2;
1337                    }
1338                    if ($Boundaries["R"] < $BoxArray[1]["X"] + 2) {
1339                        $Boundaries["R"] = $BoxArray[1]["X"] + 2;
1340                    }
1341                    if ($Boundaries["B"] < $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2) {
1342                        $Boundaries["B"] = $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2;
1343                    }
1344
1345                    $Lines = preg_split("/\n/", $Series["Description"]);
1346                    $vY = $vY + max($this->pChartObject->FontSize * count($Lines), $IconAreaHeight) + 5;
1347                } elseif ($Mode == LEGEND_HORIZONTAL) {
1348                    $Lines = preg_split("/\n/", $Series["Description"]);
1349                    $Width = [];
1350                    foreach ($Lines as $Key => $Value) {
1351                        $BoxArray = $this->pChartObject->getTextBox(
1352                            $vX + $IconAreaWidth + 6,
1353                            $Y + $IconAreaHeight / 2 + (($this->pChartObject->FontSize + 3) * $Key),
1354                            $FontName,
1355                            $FontSize,
1356                            0,
1357                            $Value
1358                        );
1359
1360                        if ($Boundaries["T"] > $BoxArray[2]["Y"] + $IconAreaHeight / 2) {
1361                            $Boundaries["T"] = $BoxArray[2]["Y"] + $IconAreaHeight / 2;
1362                        }
1363                        if ($Boundaries["R"] < $BoxArray[1]["X"] + 2) {
1364                            $Boundaries["R"] = $BoxArray[1]["X"] + 2;
1365                        }
1366                        if ($Boundaries["B"] < $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2) {
1367                            $Boundaries["B"] = $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2;
1368                        }
1369
1370                        $Width[] = $BoxArray[1]["X"];
1371                    }
1372                    $vX = max($Width) + $XStep;
1373                }
1374            }
1375        }
1376        $vY = $vY - $YStep;
1377        $vX = $vX - $XStep;
1378
1379        $TopOffset = $Y - $Boundaries["T"];
1380        if ($Boundaries["B"] - ($vY + $IconAreaHeight) < $TopOffset) {
1381            $Boundaries["B"] = $vY + $IconAreaHeight + $TopOffset;
1382        }
1383
1384        if ($Style == LEGEND_ROUND) {
1385            $this->pChartObject->drawRoundedFilledRectangle(
1386                $Boundaries["L"] - $Margin,
1387                $Boundaries["T"] - $Margin,
1388                $Boundaries["R"] + $Margin,
1389                $Boundaries["B"] + $Margin,
1390                $Margin,
1391                [
1392                    "R" => $R,
1393                    "G" => $G,
1394                    "B" => $B,
1395                    "Alpha" => $Alpha,
1396                    "BorderR" => $BorderR,
1397                    "BorderG" => $BorderG,
1398                    "BorderB" => $BorderB
1399                ]
1400            );
1401        } elseif ($Style == LEGEND_BOX) {
1402            $this->pChartObject->drawFilledRectangle(
1403                $Boundaries["L"] - $Margin,
1404                $Boundaries["T"] - $Margin,
1405                $Boundaries["R"] + $Margin,
1406                $Boundaries["B"] + $Margin,
1407                [
1408                    "R" => $R,
1409                    "G" => $G,
1410                    "B" => $B,
1411                    "Alpha" => $Alpha,
1412                    "BorderR" => $BorderR,
1413                    "BorderG" => $BorderG,
1414                    "BorderB" => $BorderB
1415                ]
1416            );
1417        }
1418        $RestoreShadow = $this->pChartObject->Shadow;
1419        $this->Shadow = false;
1420        foreach ($Data["ScatterSeries"] as $Key => $Series) {
1421            if ($Series["isDrawable"] == true) {
1422                $R = $Series["Color"]["R"];
1423                $G = $Series["Color"]["G"];
1424                $B = $Series["Color"]["B"];
1425                $Ticks = $Series["Ticks"];
1426                $Weight = $Series["Weight"];
1427
1428                if (isset($Series["Picture"])) {
1429                    $Picture = $Series["Picture"];
1430                    list($PicWidth, $PicHeight) = $this->pChartObject->getPicInfo($Picture);
1431                    $PicX = $X + $IconAreaWidth / 2;
1432                    $PicY = $Y + $IconAreaHeight / 2;
1433
1434                    $this->pChartObject->drawFromPNG($PicX - $PicWidth / 2, $PicY - $PicHeight / 2, $Picture);
1435                } else {
1436                    if ($Family == LEGEND_FAMILY_BOX) {
1437                        if ($BoxWidth != $IconAreaWidth) {
1438                            $XOffset = floor(($IconAreaWidth - $BoxWidth) / 2);
1439                        } else {
1440                            $XOffset = 0;
1441                        }
1442                        if ($BoxHeight != $IconAreaHeight) {
1443                            $YOffset = floor(($IconAreaHeight - $BoxHeight) / 2);
1444                        } else {
1445                            $YOffset = 0;
1446                        }
1447
1448                        $this->pChartObject->drawFilledRectangle(
1449                            $X + 1 + $XOffset,
1450                            $Y + 1 + $YOffset,
1451                            $X + $BoxWidth + $XOffset + 1,
1452                            $Y + $BoxHeight + 1 + $YOffset,
1453                            ["R" => 0, "G" => 0, "B" => 0, "Alpha" => 20]
1454                        );
1455                        $this->pChartObject->drawFilledRectangle(
1456                            $X + $XOffset,
1457                            $Y + $YOffset,
1458                            $X + $BoxWidth + $XOffset,
1459                            $Y + $BoxHeight + $YOffset,
1460                            ["R" => $R, "G" => $G, "B" => $B, "Surrounding" => 20]
1461                        );
1462                    } elseif ($Family == LEGEND_FAMILY_CIRCLE) {
1463                        $this->pChartObject->drawFilledCircle(
1464                            $X + 1 + $IconAreaWidth / 2,
1465                            $Y + 1 + $IconAreaHeight / 2,
1466                            min($IconAreaHeight / 2, $IconAreaWidth / 2),
1467                            ["R" => 0, "G" => 0, "B" => 0, "Alpha" => 20]
1468                        );
1469                        $this->pChartObject->drawFilledCircle(
1470                            $X + $IconAreaWidth / 2,
1471                            $Y + $IconAreaHeight / 2,
1472                            min($IconAreaHeight / 2, $IconAreaWidth / 2),
1473                            ["R" => $R, "G" => $G, "B" => $B, "Surrounding" => 20]
1474                        );
1475                    } elseif ($Family == LEGEND_FAMILY_LINE) {
1476                        $this->pChartObject->drawLine(
1477                            $X + 1,
1478                            $Y + 1 + $IconAreaHeight / 2,
1479                            $X + 1 + $IconAreaWidth,
1480                            $Y + 1 + $IconAreaHeight / 2,
1481                            [
1482                                "R" => 0,
1483                                "G" => 0,
1484                                "B" => 0,
1485                                "Alpha" => 20,
1486                                "Ticks" => $Ticks,
1487                                "Weight" => $Weight
1488                            ]
1489                        );
1490                        $this->pChartObject->drawLine(
1491                            $X,
1492                            $Y + $IconAreaHeight / 2,
1493                            $X + $IconAreaWidth,
1494                            $Y + $IconAreaHeight / 2,
1495                            ["R" => $R, "G" => $G, "B" => $B, "Ticks" => $Ticks, "Weight" => $Weight]
1496                        );
1497                    }
1498                }
1499
1500                if ($Mode == LEGEND_VERTICAL) {
1501                    $Lines = preg_split("/\n/", $Series["Description"]);
1502                    foreach ($Lines as $Key => $Value) {
1503                        $this->pChartObject->drawText(
1504                            $X + $IconAreaWidth + 4,
1505                            $Y + $IconAreaHeight / 2 + (($this->pChartObject->FontSize + 3) * $Key),
1506                            $Value,
1507                            [
1508                                "R" => $FontR,
1509                                "G" => $FontG,
1510                                "B" => $FontB,
1511                                "Align" => TEXT_ALIGN_MIDDLELEFT
1512                            ]
1513                        );
1514                    }
1515                    $Y = $Y + max($this->pChartObject->FontSize * count($Lines), $IconAreaHeight) + 5;
1516                } elseif ($Mode == LEGEND_HORIZONTAL) {
1517                    $Lines = preg_split("/\n/", $Series["Description"]);
1518                    $Width = [];
1519                    foreach ($Lines as $Key => $Value) {
1520                        $BoxArray = $this->pChartObject->drawText(
1521                            $X + $IconAreaWidth + 4,
1522                            $Y + $IconAreaHeight / 2 + (($this->pChartObject->FontSize + 3) * $Key),
1523                            $Value,
1524                            [
1525                                "R" => $FontR,
1526                                "G" => $FontG,
1527                                "B" => $FontB,
1528                                "Align" => TEXT_ALIGN_MIDDLELEFT
1529                            ]
1530                        );
1531                        $Width[] = $BoxArray[1]["X"];
1532                    }
1533                    $X = max($Width) + 2 + $XStep;
1534                }
1535            }
1536        }
1537
1538        $this->Shadow = $RestoreShadow;
1539    }
1540
1541    /**
1542     * Get the legend box size
1543     * @param array $Format
1544     * @return array
1545     */
1546    public function getScatterLegendSize(array $Format = [])
1547    {
1548        $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName;
1549        $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize;
1550        $BoxSize = isset($Format["BoxSize"]) ? $Format["BoxSize"] : 5;
1551        $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5;
1552        $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL;
1553        $XSpacing = isset($Format["XSpacing"]) ? $Format["XSpacing"] : 5;
1554
1555        $YStep = max($this->pChartObject->FontSize, $BoxSize) + 5;
1556        $XStep = $BoxSize + 5;
1557
1558        $X = 100;
1559        $Y = 100;
1560
1561        $Data = $this->pDataObject->getData();
1562
1563        foreach ($Data["ScatterSeries"] as $Key => $Series) {
1564            if ($Series["isDrawable"] == true && isset($Series["Picture"])) {
1565                list($PicWidth, $PicHeight) = $this->pChartObject->getPicInfo($Series["Picture"]);
1566                if ($IconAreaWidth < $PicWidth) {
1567                    $IconAreaWidth = $PicWidth;
1568                }
1569                if ($IconAreaHeight < $PicHeight) {
1570                    $IconAreaHeight = $PicHeight;
1571                }
1572            }
1573        }
1574
1575        $YStep = max($this->pChartObject->FontSize, $IconAreaHeight) + 5;
1576        $XStep = $XSpacing;
1577
1578        $Boundaries = [];
1579        $Boundaries["L"] = $X;
1580        $Boundaries["T"] = $Y;
1581        $Boundaries["R"] = 0;
1582        $Boundaries["B"] = 0;
1583        $vY = $Y;
1584        $vX = $X;
1585        foreach ($Data["ScatterSeries"] as $Key => $Series) {
1586            if ($Series["isDrawable"] == true) {
1587                if ($Mode == LEGEND_VERTICAL) {
1588                    $BoxArray = $this->pChartObject->getTextBox(
1589                        $vX + $IconAreaWidth + 4,
1590                        $vY + $IconAreaHeight / 2,
1591                        $FontName,
1592                        $FontSize,
1593                        0,
1594                        $Series["Description"]
1595                    );
1596
1597                    if ($Boundaries["T"] > $BoxArray[2]["Y"] + $IconAreaHeight / 2) {
1598                        $Boundaries["T"] = $BoxArray[2]["Y"] + $IconAreaHeight / 2;
1599                    }
1600                    if ($Boundaries["R"] < $BoxArray[1]["X"] + 2) {
1601                        $Boundaries["R"] = $BoxArray[1]["X"] + 2;
1602                    }
1603                    if ($Boundaries["B"] < $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2) {
1604                        $Boundaries["B"] = $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2;
1605                    }
1606
1607                    $Lines = preg_split("/\n/", $Series["Description"]);
1608                    $vY = $vY + max($this->pChartObject->FontSize * count($Lines), $IconAreaHeight) + 5;
1609                } elseif ($Mode == LEGEND_HORIZONTAL) {
1610                    $Lines = preg_split("/\n/", $Series["Description"]);
1611                    $Width = [];
1612                    foreach ($Lines as $Key => $Value) {
1613                        $BoxArray = $this->pChartObject->getTextBox(
1614                            $vX + $IconAreaWidth + 6,
1615                            $Y + $IconAreaHeight / 2 + (($this->pChartObject->FontSize + 3) * $Key),
1616                            $FontName,
1617                            $FontSize,
1618                            0,
1619                            $Value
1620                        );
1621
1622                        if ($Boundaries["T"] > $BoxArray[2]["Y"] + $IconAreaHeight / 2) {
1623                            $Boundaries["T"] = $BoxArray[2]["Y"] + $IconAreaHeight / 2;
1624                        }
1625                        if ($Boundaries["R"] < $BoxArray[1]["X"] + 2) {
1626                            $Boundaries["R"] = $BoxArray[1]["X"] + 2;
1627                        }
1628                        if ($Boundaries["B"] < $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2) {
1629                            $Boundaries["B"] = $BoxArray[1]["Y"] + 2 + $IconAreaHeight / 2;
1630                        }
1631
1632                        $Width[] = $BoxArray[1]["X"];
1633                    }
1634                    $vX = max($Width) + $XStep;
1635                }
1636            }
1637        }
1638        $vY = $vY - $YStep;
1639        $vX = $vX - $XStep;
1640
1641        $TopOffset = $Y - $Boundaries["T"];
1642        if ($Boundaries["B"] - ($vY + $BoxSize) < $TopOffset) {
1643            $Boundaries["B"] = $vY + $BoxSize + $TopOffset;
1644        }
1645
1646        $Width = ($Boundaries["R"] + $Margin) - ($Boundaries["L"] - $Margin);
1647        $Height = ($Boundaries["B"] + $Margin) - ($Boundaries["T"] - $Margin);
1648
1649        return ["Width" => $Width, "Height" => $Height];
1650    }
1651
1652    /**
1653     * Draw the line of best fit
1654     * @param array $Format
1655     */
1656    public function drawScatterBestFit(array $Format = [])
1657    {
1658        $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : 0;
1659
1660        $Data = $this->pDataObject->getData();
1661
1662        foreach ($Data["ScatterSeries"] as $Key => $Series) {
1663            if ($Series["isDrawable"] == true) {
1664                $SerieX = $Series["X"];
1665                $SerieXAxis = $Data["Series"][$SerieX]["Axis"];
1666                $SerieY = $Series["Y"];
1667                $SerieYAxis = $Data["Series"][$SerieY]["Axis"];
1668
1669                $Color = [
1670                    "R" => $Series["Color"]["R"],
1671                    "G" => $Series["Color"]["G"],
1672                    "B" => $Series["Color"]["B"],
1673                    "Alpha" => $Series["Color"]["Alpha"]
1674                ];
1675                $Color["Ticks"] = $Ticks;
1676
1677                $PosArrayX = $Data["Series"][$Series["X"]]["Data"];
1678                $PosArrayY = $Data["Series"][$Series["Y"]]["Data"];
1679
1680                $Sxy = 0;
1681                $Sx = 0;
1682                $Sy = 0;
1683                $Sxx = 0;
1684                foreach ($PosArrayX as $Key => $Value) {
1685                    $X = $Value;
1686                    $Y = $PosArrayY[$Key];
1687
1688                    $Sxy = $Sxy + $X * $Y;
1689                    $Sx = $Sx + $X;
1690                    $Sy = $Sy + $Y;
1691                    $Sxx = $Sxx + $X * $X;
1692                }
1693
1694                $n = count($PosArrayX);
1695
1696                if ((($n * $Sxx) == ($Sx * $Sx))) {
1697                    $X1 = $this->getPosArray($Data["Axis"][$SerieXAxis]["ScaleMin"], $SerieXAxis);
1698                    $X2 = $X1;
1699                    $Y1 = $this->pChartObject->GraphAreaY1;
1700                    $Y2 = $this->pChartObject->GraphAreaY2;
1701                } else {
1702                    $M = (($n * $Sxy) - ($Sx * $Sy)) / (($n * $Sxx) - ($Sx * $Sx));
1703                    $B = (($Sy) - ($M * $Sx)) / ($n);
1704
1705                    $X1 = $this->getPosArray($Data["Axis"][$SerieXAxis]["ScaleMin"], $SerieXAxis);
1706                    $Y1 = $this->getPosArray($M * $Data["Axis"][$SerieXAxis]["ScaleMin"] + $B, $SerieYAxis);
1707                    $X2 = $this->getPosArray($Data["Axis"][$SerieXAxis]["ScaleMax"], $SerieXAxis);
1708                    $Y2 = $this->getPosArray($M * $Data["Axis"][$SerieXAxis]["ScaleMax"] + $B, $SerieYAxis);
1709
1710                    $RealM = -($Y2 - $Y1) / ($X2 - $X1);
1711
1712                    if ($Y1 < $this->pChartObject->GraphAreaY1) {
1713                        $X1 = $X1 + ($this->pChartObject->GraphAreaY1 - $Y1 / $RealM);
1714                        $Y1 = $this->pChartObject->GraphAreaY1;
1715                    }
1716                    if ($Y1 > $this->pChartObject->GraphAreaY2) {
1717                        $X1 = $X1 + ($Y1 - $this->pChartObject->GraphAreaY2) / $RealM;
1718                        $Y1 = $this->pChartObject->GraphAreaY2;
1719                    }
1720                    if ($Y2 < $this->pChartObject->GraphAreaY1) {
1721                        $X2 = $X2 - ($this->pChartObject->GraphAreaY1 - $Y2) / $RealM;
1722                        $Y2 = $this->pChartObject->GraphAreaY1;
1723                    }
1724                    if ($Y2 > $this->pChartObject->GraphAreaY2) {
1725                        $X2 = $X2 - ($Y2 - $this->pChartObject->GraphAreaY2) / $RealM;
1726                        $Y2 = $this->pChartObject->GraphAreaY2;
1727                    }
1728                }
1729
1730                $this->pChartObject->drawLine($X1, $Y1, $X2, $Y2, $Color);
1731            }
1732        }
1733    }
1734
1735    /**
1736     *
1737     * @param string $ScatterSerieID
1738     * @param mixed $Points
1739     * @param array $Format
1740     * @return null|int
1741     */
1742    public function writeScatterLabel($ScatterSerieID, $Points, array $Format = [])
1743    {
1744        $DrawPoint = isset($Format["DrawPoint"]) ? $Format["DrawPoint"] : LABEL_POINT_BOX;
1745        $Decimals = isset($Format["Decimals"]) ? $Format["Decimals"] : null;
1746
1747        $Data = $this->pDataObject->getData();
1748
1749        if (!is_array($Points)) {
1750            $Points = [$Points];
1751        }
1752
1753        if (!isset($Data["ScatterSeries"][$ScatterSerieID])) {
1754            return 0;
1755        }
1756        $Series = $Data["ScatterSeries"][$ScatterSerieID];
1757
1758        $SerieX = $Series["X"];
1759        $SerieValuesX = $Data["Series"][$SerieX]["Data"];
1760        $SerieXAxis = $Data["Series"][$SerieX]["Axis"];
1761
1762        $SerieY = $Series["Y"];
1763        $SerieValuesY = $Data["Series"][$SerieY]["Data"];
1764        $SerieYAxis = $Data["Series"][$SerieY]["Axis"];
1765
1766        $PosArrayX = $this->getPosArray($SerieValuesX, $SerieXAxis);
1767        if (!is_array($PosArrayX)) {
1768            $Value = $PosArrayX;
1769            $PosArrayX = [];
1770            $PosArrayX[0] = $Value;
1771        }
1772        $PosArrayY = $this->getPosArray($SerieValuesY, $SerieYAxis);
1773        if (!is_array($PosArrayY)) {
1774            $Value = $PosArrayY;
1775            $PosArrayY = [];
1776            $PosArrayY[0] = $Value;
1777        }
1778
1779        foreach ($Points as $Key => $Point) {
1780            if (isset($PosArrayX[$Point]) && isset($PosArrayY[$Point])) {
1781                $X = floor($PosArrayX[$Point]);
1782                $Y = floor($PosArrayY[$Point]);
1783
1784                if ($DrawPoint == LABEL_POINT_CIRCLE) {
1785                    $this->pChartObject->drawFilledCircle(
1786                        $X,
1787                        $Y,
1788                        3,
1789                        [
1790                            "R" => 255,
1791                            "G" => 255,
1792                            "B" => 255,
1793                            "BorderR" => 0,
1794                            "BorderG" => 0,
1795                            "BorderB" => 0
1796                        ]
1797                    );
1798                } elseif ($DrawPoint == LABEL_POINT_BOX) {
1799                    $this->pChartObject->drawFilledRectangle(
1800                        $X - 2,
1801                        $Y - 2,
1802                        $X + 2,
1803                        $Y + 2,
1804                        [
1805                            "R" => 255,
1806                            "G" => 255,
1807                            "B" => 255,
1808                            "BorderR" => 0,
1809                            "BorderG" => 0,
1810                            "BorderB" => 0
1811                        ]
1812                    );
1813                }
1814                $Serie = [];
1815                $Serie["R"] = $Series["Color"]["R"];
1816                $Serie["G"] = $Series["Color"]["G"];
1817                $Serie["B"] = $Series["Color"]["B"];
1818                $Serie["Alpha"] = $Series["Color"]["Alpha"];
1819
1820                $XAxisMode = $Data["Axis"][$SerieXAxis]["Display"];
1821                $XAxisFormat = $Data["Axis"][$SerieXAxis]["Format"];
1822                $XAxisUnit = $Data["Axis"][$SerieXAxis]["Unit"];
1823                if ($Decimals == null) {
1824                    $XValue = $SerieValuesX[$Point];
1825                } else {
1826                    $XValue = round($SerieValuesX[$Point], $Decimals);
1827                }
1828                $XValue = $this->pChartObject->scaleFormat($XValue, $XAxisMode, $XAxisFormat, $XAxisUnit);
1829
1830                $YAxisMode = $Data["Axis"][$SerieYAxis]["Display"];
1831                $YAxisFormat = $Data["Axis"][$SerieYAxis]["Format"];
1832                $YAxisUnit = $Data["Axis"][$SerieYAxis]["Unit"];
1833                if ($Decimals == null) {
1834                    $YValue = $SerieValuesY[$Point];
1835                } else {
1836                    $YValue = round($SerieValuesY[$Point], $Decimals);
1837                }
1838                $YValue = $this->pChartObject->scaleFormat($YValue, $YAxisMode, $YAxisFormat, $YAxisUnit);
1839
1840                $Caption = sprintf("%s / %s", $XValue, $YValue);
1841
1842                if (isset($Series["Description"])) {
1843                    $Description = $Series["Description"];
1844                } else {
1845                    $Description = "No description";
1846                }
1847                $Series = [["Format" => $Serie, "Caption" => $Caption]];
1848
1849                $this->pChartObject->drawLabelBox($X, $Y - 3, $Description, $Series, $Format);
1850            }
1851        }
1852    }
1853
1854    /**
1855     * Draw a Scatter threshold
1856     * @param mixed $Value
1857     * @param array $Format
1858     * @return array
1859     */
1860    public function drawScatterThreshold($Value, array $Format = [])
1861    {
1862        $AxisID = isset($Format["AxisID"]) ? $Format["AxisID"] : 0;
1863        $R = isset($Format["R"]) ? $Format["R"] : 255;
1864        $G = isset($Format["G"]) ? $Format["G"] : 0;
1865        $B = isset($Format["B"]) ? $Format["B"] : 0;
1866        $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 50;
1867        $Weight = isset($Format["Weight"]) ? $Format["Weight"] : null;
1868        $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : 3;
1869        $Wide = isset($Format["Wide"]) ? $Format["Wide"] : false;
1870        $WideFactor = isset($Format["WideFactor"]) ? $Format["WideFactor"] : 5;
1871        $WriteCaption = isset($Format["WriteCaption"]) ? $Format["WriteCaption"] : false;
1872        $Caption = isset($Format["Caption"]) ? $Format["Caption"] : null;
1873        $CaptionAlign = isset($Format["CaptionAlign"]) ? $Format["CaptionAlign"] : CAPTION_LEFT_TOP;
1874        $CaptionOffset = isset($Format["CaptionOffset"]) ? $Format["CaptionOffset"] : 10;
1875        $CaptionR = isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255;
1876        $CaptionG = isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255;
1877        $CaptionB = isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255;
1878        $CaptionAlpha = isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100;
1879        $DrawBox = isset($Format["DrawBox"]) ? $Format["DrawBox"] : true;
1880        $DrawBoxBorder = isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : false;
1881        $BorderOffset = isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 5;
1882        $BoxRounded = isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : true;
1883        $RoundedRadius = isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 3;
1884        $BoxR = isset($Format["BoxR"]) ? $Format["BoxR"] : 0;
1885        $BoxG = isset($Format["BoxG"]) ? $Format["BoxG"] : 0;
1886        $BoxB = isset($Format["BoxB"]) ? $Format["BoxB"] : 0;
1887        $BoxAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 20;
1888        $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : "";
1889        $BoxBorderR = isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 255;
1890        $BoxBorderG = isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 255;
1891        $BoxBorderB = isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 255;
1892        $BoxBorderAlpha = isset($Format["BoxBorderAlpha"]) ? $Format["BoxBorderAlpha"] : 100;
1893
1894        $CaptionSettings = [
1895            "DrawBox" => $DrawBox,
1896            "DrawBoxBorder" => $DrawBoxBorder,
1897            "BorderOffset" => $BorderOffset,
1898            "BoxRounded" => $BoxRounded,
1899            "RoundedRadius" => $RoundedRadius,
1900            "BoxR" => $BoxR,
1901            "BoxG" => $BoxG,
1902            "BoxB" => $BoxB,
1903            "BoxAlpha" => $BoxAlpha,
1904            "BoxSurrounding" => $BoxSurrounding,
1905            "BoxBorderR" => $BoxBorderR,
1906            "BoxBorderG" => $BoxBorderG,
1907            "BoxBorderB" => $BoxBorderB,
1908            "BoxBorderAlpha" => $BoxBorderAlpha,
1909            "R" => $CaptionR,
1910            "G" => $CaptionG,
1911            "B" => $CaptionB,
1912            "Alpha" => $CaptionAlpha
1913        ];
1914
1915        if ($Caption == null) {
1916            $Caption = $Value;
1917        }
1918
1919        $Data = $this->pDataObject->getData();
1920
1921        if (!isset($Data["Axis"][$AxisID])) {
1922            return -1;
1923        }
1924
1925        if ($Data["Axis"][$AxisID]["Identity"] == AXIS_Y) {
1926            $X1 = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"];
1927            $X2 = $this->pChartObject->GraphAreaX2 - $Data["Axis"][$AxisID]["Margin"];
1928            $Y = $this->getPosArray($Value, $AxisID);
1929
1930            $this->pChartObject->drawLine(
1931                $X1,
1932                $Y,
1933                $X2,
1934                $Y,
1935                [
1936                    "R" => $R,
1937                    "G" => $G,
1938                    "B" => $B,
1939                    "Alpha" => $Alpha,
1940                    "Ticks" => $Ticks,
1941                    "Weight" => $Weight
1942                ]
1943            );
1944
1945            if ($Wide) {
1946                $this->pChartObject->drawLine(
1947                    $X1,
1948                    $Y - 1,
1949                    $X2,
1950                    $Y - 1,
1951                    [
1952                        "R" => $R,
1953                        "G" => $G,
1954                        "B" => $B,
1955                        "Alpha" => $Alpha / $WideFactor,
1956                        "Ticks" => $Ticks
1957                    ]
1958                );
1959                $this->pChartObject->drawLine(
1960                    $X1,
1961                    $Y + 1,
1962                    $X2,
1963                    $Y + 1,
1964                    [
1965                        "R" => $R,
1966                        "G" => $G,
1967                        "B" => $B,
1968                        "Alpha" => $Alpha / $WideFactor,
1969                        "Ticks" => $Ticks
1970                    ]
1971                );
1972            }
1973
1974            if ($WriteCaption) {
1975                if ($CaptionAlign == CAPTION_LEFT_TOP) {
1976                    $X = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"] + $CaptionOffset;
1977                    $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLELEFT;
1978                } else {
1979                    $X = $this->pChartObject->GraphAreaX2 - $Data["Axis"][$AxisID]["Margin"] - $CaptionOffset;
1980                    $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLERIGHT;
1981                }
1982                $this->pChartObject->drawText($X, $Y, $Caption, $CaptionSettings);
1983            }
1984
1985            return ["Y" => $Y];
1986        } elseif ($Data["Axis"][$AxisID]["Identity"] == AXIS_X) {
1987            $X = $this->getPosArray($Value, $AxisID);
1988            $Y1 = $this->pChartObject->GraphAreaY1 + $Data["Axis"][$AxisID]["Margin"];
1989            $Y2 = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"];
1990
1991            $this->pChartObject->drawLine(
1992                $X,
1993                $Y1,
1994                $X,
1995                $Y2,
1996                [
1997                    "R" => $R,
1998                    "G" => $G,
1999                    "B" => $B,
2000                    "Alpha" => $Alpha,
2001                    "Ticks" => $Ticks,
2002                    "Weight" => $Weight
2003                ]
2004            );
2005
2006            if ($Wide) {
2007                $this->pChartObject->drawLine(
2008                    $X - 1,
2009                    $Y1,
2010                    $X - 1,
2011                    $Y2,
2012                    ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha / $WideFactor, "Ticks" => $Ticks]
2013                );
2014                $this->pChartObject->drawLine(
2015                    $X + 1,
2016                    $Y1,
2017                    $X + 1,
2018                    $Y2,
2019                    ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha / $WideFactor, "Ticks" => $Ticks]
2020                );
2021            }
2022
2023            if ($WriteCaption) {
2024                if ($CaptionAlign == CAPTION_LEFT_TOP) {
2025                    $Y = $this->pChartObject->GraphAreaY1 + $Data["Axis"][$AxisID]["Margin"] + $CaptionOffset;
2026                    $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE;
2027                } else {
2028                    $Y = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"] - $CaptionOffset;
2029                    $CaptionSettings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE;
2030                }
2031
2032                $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE;
2033                $this->pChartObject->drawText($X, $Y, $Caption, $CaptionSettings);
2034            }
2035
2036            return ["X" => $X];
2037        }
2038    }
2039
2040    /**
2041     * Draw a Scatter threshold area
2042     * @param int|float $Value1
2043     * @param int|float $Value2
2044     * @param array $Format
2045     * @return type
2046     */
2047    public function drawScatterThresholdArea($Value1, $Value2, array $Format = [])
2048    {
2049        $AxisID = isset($Format["AxisID"]) ? $Format["AxisID"] : 0;
2050        $R = isset($Format["R"]) ? $Format["R"] : 255;
2051        $G = isset($Format["G"]) ? $Format["G"] : 0;
2052        $B = isset($Format["B"]) ? $Format["B"] : 0;
2053        $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 20;
2054        $Border = isset($Format["Border"]) ? $Format["Border"] : true;
2055        $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R;
2056        $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G;
2057        $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B;
2058        $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha + 20;
2059        $BorderTicks = isset($Format["BorderTicks"]) ? $Format["BorderTicks"] : 2;
2060        $AreaName = isset($Format["AreaName"]) ? $Format["AreaName"] : "La ouate de phoque"; //null;
2061        $NameAngle = isset($Format["NameAngle"]) ? $Format["NameAngle"] : ZONE_NAME_ANGLE_AUTO;
2062        $NameR = isset($Format["NameR"]) ? $Format["NameR"] : 255;
2063        $NameG = isset($Format["NameG"]) ? $Format["NameG"] : 255;
2064        $NameB = isset($Format["NameB"]) ? $Format["NameB"] : 255;
2065        $NameAlpha = isset($Format["NameAlpha"]) ? $Format["NameAlpha"] : 100;
2066        $DisableShadowOnArea = isset($Format["DisableShadowOnArea"]) ? $Format["DisableShadowOnArea"] : true;
2067
2068        if ($Value1 > $Value2) {
2069            list($Value1, $Value2) = [$Value2, $Value1];
2070        }
2071
2072        $RestoreShadow = $this->pChartObject->Shadow;
2073        if ($DisableShadowOnArea && $this->pChartObject->Shadow) {
2074            $this->pChartObject->Shadow = false;
2075        }
2076
2077        if ($BorderAlpha > 100) {
2078            $BorderAlpha = 100;
2079        }
2080
2081        $Data = $this->pDataObject->getData();
2082
2083        if (!isset($Data["Axis"][$AxisID])) {
2084            return -1;
2085        }
2086
2087        if ($Data["Axis"][$AxisID]["Identity"] == AXIS_X) {
2088            $Y1 = $this->pChartObject->GraphAreaY1 + $Data["Axis"][$AxisID]["Margin"];
2089            $Y2 = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"];
2090            $X1 = $this->getPosArray($Value1, $AxisID);
2091            $X2 = $this->getPosArray($Value2, $AxisID);
2092
2093            if ($X1 <= $this->pChartObject->GraphAreaX1) {
2094                $X1 = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"];
2095            }
2096            if ($X2 >= $this->pChartObject->GraphAreaX2) {
2097                $X2 = $this->pChartObject->GraphAreaX2 - $Data["Axis"][$AxisID]["Margin"];
2098            }
2099
2100            $this->pChartObject->drawFilledRectangle(
2101                $X1,
2102                $Y1,
2103                $X2,
2104                $Y2,
2105                ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha]
2106            );
2107
2108            if ($Border) {
2109                $this->pChartObject->drawLine(
2110                    $X1,
2111                    $Y1,
2112                    $X1,
2113                    $Y2,
2114                    [
2115                        "R" => $BorderR,
2116                        "G" => $BorderG,
2117                        "B" => $BorderB,
2118                        "Alpha" => $BorderAlpha,
2119                        "Ticks" => $BorderTicks
2120                    ]
2121                );
2122                $this->pChartObject->drawLine(
2123                    $X2,
2124                    $Y1,
2125                    $X2,
2126                    $Y2,
2127                    [
2128                        "R" => $BorderR,
2129                        "G" => $BorderG,
2130                        "B" => $BorderB,
2131                        "Alpha" => $BorderAlpha,
2132                        "Ticks" => $BorderTicks
2133                    ]
2134                );
2135            }
2136
2137            if ($AreaName != null) {
2138                $XPos = ($X2 - $X1) / 2 + $X1;
2139                $YPos = ($Y2 - $Y1) / 2 + $Y1;
2140
2141                if ($NameAngle == ZONE_NAME_ANGLE_AUTO) {
2142                    $TxtPos = $this->pChartObject->getTextBox(
2143                        $XPos,
2144                        $YPos,
2145                        $this->pChartObject->FontName,
2146                        $this->pChartObject->FontSize,
2147                        0,
2148                        $AreaName
2149                    );
2150                    $TxtWidth = $TxtPos[1]["X"] - $TxtPos[0]["X"];
2151                    if (abs($X2 - $X1) > $TxtWidth) {
2152                        $NameAngle = 0;
2153                    } else {
2154                        $NameAngle = 90;
2155                    }
2156                }
2157                $this->pChartObject->Shadow = $RestoreShadow;
2158                $this->pChartObject->drawText(
2159                    $XPos,
2160                    $YPos,
2161                    $AreaName,
2162                    [
2163                        "R" => $NameR,
2164                        "G" => $NameG,
2165                        "B" => $NameB,
2166                        "Alpha" => $NameAlpha,
2167                        "Angle" => $NameAngle,
2168                        "Align" => TEXT_ALIGN_MIDDLEMIDDLE
2169                    ]
2170                );
2171                if ($DisableShadowOnArea) {
2172                    $this->pChartObject->Shadow = false;
2173                }
2174            }
2175
2176            $this->pChartObject->Shadow = $RestoreShadow;
2177            return ["X1" => $X1, "X2" => $X2];
2178        } elseif ($Data["Axis"][$AxisID]["Identity"] == AXIS_Y) {
2179            $X1 = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"];
2180            $X2 = $this->pChartObject->GraphAreaX2 - $Data["Axis"][$AxisID]["Margin"];
2181            $Y1 = $this->getPosArray($Value1, $AxisID);
2182            $Y2 = $this->getPosArray($Value2, $AxisID);
2183
2184            if ($Y1 >= $this->pChartObject->GraphAreaY2) {
2185                $Y1 = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"];
2186            }
2187            if ($Y2 <= $this->pChartObject->GraphAreaY1) {
2188                $Y2 = $this->pChartObject->GraphAreaY1 + $Data["Axis"][$AxisID]["Margin"];
2189            }
2190
2191            $this->pChartObject->drawFilledRectangle(
2192                $X1,
2193                $Y1,
2194                $X2,
2195                $Y2,
2196                ["R" => $R, "G" => $G, "B" => $B, "Alpha" => $Alpha]
2197            );
2198
2199            if ($Border) {
2200                $this->pChartObject->drawLine(
2201                    $X1,
2202                    $Y1,
2203                    $X2,
2204                    $Y1,
2205                    [
2206                        "R" => $BorderR,
2207                        "G" => $BorderG,
2208                        "B" => $BorderB,
2209                        "Alpha" => $BorderAlpha,
2210                        "Ticks" => $BorderTicks
2211                    ]
2212                );
2213                $this->pChartObject->drawLine(
2214                    $X1,
2215                    $Y2,
2216                    $X2,
2217                    $Y2,
2218                    [
2219                        "R" => $BorderR,
2220                        "G" => $BorderG,
2221                        "B" => $BorderB,
2222                        "Alpha" => $BorderAlpha,
2223                        "Ticks" => $BorderTicks
2224                    ]
2225                );
2226            }
2227
2228            if ($AreaName != null) {
2229                $XPos = ($X2 - $X1) / 2 + $X1;
2230                $YPos = ($Y2 - $Y1) / 2 + $Y1;
2231
2232                $this->pChartObject->Shadow = $RestoreShadow;
2233                $this->pChartObject->drawText(
2234                    $YPos,
2235                    $XPos,
2236                    $AreaName,
2237                    [
2238                        "R" => $NameR,
2239                        "G" => $NameG,
2240                        "B" => $NameB,
2241                        "Alpha" => $NameAlpha,
2242                        "Angle" => 0,
2243                        "Align" => TEXT_ALIGN_MIDDLEMIDDLE
2244                    ]
2245                );
2246                if ($DisableShadowOnArea) {
2247                    $this->Shadow = false;
2248                }
2249            }
2250
2251            $this->pChartObject->Shadow = $RestoreShadow;
2252            return ["Y1" => $Y1, "Y2" => $Y2];
2253        }
2254    }
2255}
2256