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