1<?php 2 3namespace CpChart\Chart; 4 5use CpChart\Image; 6 7class Indicator 8{ 9 /** 10 * @var Image 11 */ 12 public $pChartObject; 13 14 public function __construct(Image $pChartObject) 15 { 16 $this->pChartObject = $pChartObject; 17 } 18 19 /** 20 * Draw an indicator 21 * 22 * @param int $X 23 * @param int $Y 24 * @param int $Width 25 * @param int $Height 26 * @param array $Format 27 * @return null|int 28 */ 29 public function draw($X, $Y, $Width, $Height, array $Format = []) 30 { 31 $Values = isset($Format["Values"]) ? $Format["Values"] : VOID; 32 $IndicatorSections = isset($Format["IndicatorSections"]) ? $Format["IndicatorSections"] : null; 33 $ValueDisplay = isset($Format["ValueDisplay"]) ? $Format["ValueDisplay"] : INDICATOR_VALUE_BUBBLE; 34 $SectionsMargin = isset($Format["SectionsMargin"]) ? $Format["SectionsMargin"] : 4; 35 $DrawLeftHead = isset($Format["DrawLeftHead"]) ? $Format["DrawLeftHead"] : true; 36 $DrawRightHead = isset($Format["DrawRightHead"]) ? $Format["DrawRightHead"] : true; 37 $HeadSize = isset($Format["HeadSize"]) ? $Format["HeadSize"] : floor($Height / 4); 38 $TextPadding = isset($Format["TextPadding"]) ? $Format["TextPadding"] : 4; 39 $CaptionLayout = isset($Format["CaptionLayout"]) ? $Format["CaptionLayout"] : INDICATOR_CAPTION_EXTENDED; 40 $CaptionPosition = isset($Format["CaptionPosition"]) ? $Format["CaptionPosition"] : INDICATOR_CAPTION_INSIDE; 41 $CaptionColorFactor = isset($Format["CaptionColorFactor"]) ? $Format["CaptionColorFactor"] : null; 42 $CaptionR = isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255; 43 $CaptionG = isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255; 44 $CaptionB = isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255; 45 $CaptionAlpha = isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100; 46 $SubCaptionColorFactor = isset($Format["SubCaptionColorFactor"]) ? $Format["SubCaptionColorFactor"] : null; 47 $SubCaptionR = isset($Format["SubCaptionR"]) ? $Format["SubCaptionR"] : 50; 48 $SubCaptionG = isset($Format["SubCaptionG"]) ? $Format["SubCaptionG"] : 50; 49 $SubCaptionB = isset($Format["SubCaptionB"]) ? $Format["SubCaptionB"] : 50; 50 $SubCaptionAlpha = isset($Format["SubCaptionAlpha"]) ? $Format["SubCaptionAlpha"] : 100; 51 $ValueFontName = isset($Format["ValueFontName"]) ? $Format["ValueFontName"] : $this->pChartObject->FontName; 52 $ValueFontSize = isset($Format["ValueFontSize"]) ? $Format["ValueFontSize"] : $this->pChartObject->FontSize; 53 $CaptionFontName = isset($Format["CaptionFontName"]) 54 ? $Format["CaptionFontName"] : $this->pChartObject->FontName 55 ; 56 $CaptionFontSize = isset($Format["CaptionFontSize"]) 57 ? $Format["CaptionFontSize"] : $this->pChartObject->FontSize 58 ; 59 $Unit = isset($Format["Unit"]) ? $Format["Unit"] : ""; 60 61 /* Convert the Values to display to an array if needed */ 62 if (!is_array($Values)) { 63 $Values = [$Values]; 64 } 65 66 /* No section, let's die */ 67 if ($IndicatorSections == null) { 68 return 0; 69 } 70 71 /* Determine indicator visual configuration */ 72 $OverallMin = $IndicatorSections[0]["End"]; 73 $OverallMax = $IndicatorSections[0]["Start"]; 74 foreach ($IndicatorSections as $Key => $Settings) { 75 if ($Settings["End"] > $OverallMax) { 76 $OverallMax = $Settings["End"]; 77 } 78 if ($Settings["Start"] < $OverallMin) { 79 $OverallMin = $Settings["Start"]; 80 } 81 } 82 $RealWidth = $Width - (count($IndicatorSections) - 1) * $SectionsMargin; 83 $XScale = $RealWidth / ($OverallMax - $OverallMin); 84 85 $X1 = $X; 86 $ValuesPos = []; 87 foreach ($IndicatorSections as $Key => $Settings) { 88 $Color = ["R" => $Settings["R"], "G" => $Settings["G"], "B" => $Settings["B"]]; 89 $Caption = $Settings["Caption"]; 90 $SubCaption = $Settings["Start"] . " - " . $Settings["End"]; 91 92 $X2 = $X1 + ($Settings["End"] - $Settings["Start"]) * $XScale; 93 94 if ($Key == 0 && $DrawLeftHead) { 95 $Poly = []; 96 $Poly[] = $X1 - 1; 97 $Poly[] = $Y; 98 $Poly[] = $X1 - 1; 99 $Poly[] = $Y + $Height; 100 $Poly[] = $X1 - 1 - $HeadSize; 101 $Poly[] = $Y + ($Height / 2); 102 $this->pChartObject->drawPolygon($Poly, $Color); 103 $this->pChartObject->drawLine($X1 - 2, $Y, $X1 - 2 - $HeadSize, $Y + ($Height / 2), $Color); 104 $this->pChartObject->drawLine( 105 $X1 - 2, 106 $Y + $Height, 107 $X1 - 2 - $HeadSize, 108 $Y + ($Height / 2), 109 $Color 110 ); 111 } 112 113 /* Determine the position of the breaks */ 114 $Break = []; 115 foreach ($Values as $iKey => $Value) { 116 if ($Value >= $Settings["Start"] && $Value <= $Settings["End"]) { 117 $XBreak = $X1 + ($Value - $Settings["Start"]) * $XScale; 118 $ValuesPos[$Value] = $XBreak; 119 $Break[] = floor($XBreak); 120 } 121 } 122 123 if ($ValueDisplay == INDICATOR_VALUE_LABEL) { 124 if (!count($Break)) { 125 $this->pChartObject->drawFilledRectangle($X1, $Y, $X2, $Y + $Height, $Color); 126 } else { 127 sort($Break); 128 $Poly = []; 129 $Poly[] = $X1; 130 $Poly[] = $Y; 131 $LastPointWritten = false; 132 foreach ($Break as $iKey => $Value) { 133 if ($Value - 5 >= $X1) { 134 $Poly[] = $Value - 5; 135 $Poly[] = $Y; 136 } elseif ($X1 - ($Value - 5) > 0) { 137 $Offset = $X1 - ($Value - 5); 138 $Poly = [$X1, $Y + $Offset]; 139 } 140 141 $Poly[] = $Value; 142 $Poly[] = $Y + 5; 143 144 if ($Value + 5 <= $X2) { 145 $Poly[] = $Value + 5; 146 $Poly[] = $Y; 147 } elseif (($Value + 5) > $X2) { 148 $Offset = ($Value + 5) - $X2; 149 $Poly[] = $X2; 150 $Poly[] = $Y + $Offset; 151 $LastPointWritten = true; 152 } 153 } 154 if (!$LastPointWritten) { 155 $Poly[] = $X2; 156 $Poly[] = $Y; 157 } 158 $Poly[] = $X2; 159 $Poly[] = $Y + $Height; 160 $Poly[] = $X1; 161 $Poly[] = $Y + $Height; 162 163 $this->pChartObject->drawPolygon($Poly, $Color); 164 } 165 } else { 166 $this->pChartObject->drawFilledRectangle($X1, $Y, $X2, $Y + $Height, $Color); 167 } 168 169 if ($Key == count($IndicatorSections) - 1 && $DrawRightHead) { 170 $Poly = []; 171 $Poly[] = $X2 + 1; 172 $Poly[] = $Y; 173 $Poly[] = $X2 + 1; 174 $Poly[] = $Y + $Height; 175 $Poly[] = $X2 + 1 + $HeadSize; 176 $Poly[] = $Y + ($Height / 2); 177 $this->pChartObject->drawPolygon($Poly, $Color); 178 $this->pChartObject->drawLine($X2 + 1, $Y, $X2 + 1 + $HeadSize, $Y + ($Height / 2), $Color); 179 $this->pChartObject->drawLine( 180 $X2 + 1, 181 $Y + $Height, 182 $X2 + 1 + $HeadSize, 183 $Y + ($Height / 2), 184 $Color 185 ); 186 } 187 188 $YOffset = 0; 189 $XOffset = 0; 190 if ($CaptionPosition == INDICATOR_CAPTION_INSIDE) { 191 $TxtPos = $this->pChartObject->getTextBox( 192 $X1, 193 $Y + $Height + $TextPadding, 194 $CaptionFontName, 195 $CaptionFontSize, 196 0, 197 $Caption 198 ); 199 $YOffset = ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]) + $TextPadding; 200 201 if ($CaptionLayout == INDICATOR_CAPTION_EXTENDED) { 202 $TxtPos = $this->pChartObject->getTextBox( 203 $X1, 204 $Y + $Height + $TextPadding, 205 $CaptionFontName, 206 $CaptionFontSize, 207 0, 208 $SubCaption 209 ); 210 $YOffset = $YOffset + ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]) + $TextPadding * 2; 211 } 212 $XOffset = $TextPadding; 213 } 214 215 if ($CaptionColorFactor == null) { 216 $CaptionColor = [ 217 "Align" => TEXT_ALIGN_TOPLEFT, 218 "FontName" => $CaptionFontName, 219 "FontSize" => $CaptionFontSize, 220 "R" => $CaptionR, 221 "G" => $CaptionG, 222 "B" => $CaptionB, 223 "Alpha" => $CaptionAlpha 224 ]; 225 } else { 226 $CaptionColor = [ 227 "Align" => TEXT_ALIGN_TOPLEFT, 228 "FontName" => $CaptionFontName, 229 "FontSize" => $CaptionFontSize, 230 "R" => $Settings["R"] + $CaptionColorFactor, 231 "G" => $Settings["G"] + $CaptionColorFactor, 232 "B" => $Settings["B"] + $CaptionColorFactor 233 ]; 234 } 235 236 if ($SubCaptionColorFactor == null) { 237 $SubCaptionColor = [ 238 "Align" => TEXT_ALIGN_TOPLEFT, 239 "FontName" => $CaptionFontName, 240 "FontSize" => $CaptionFontSize, 241 "R" => $SubCaptionR, 242 "G" => $SubCaptionG, 243 "B" => $SubCaptionB, 244 "Alpha" => $SubCaptionAlpha 245 ]; 246 } else { 247 $SubCaptionColor = [ 248 "Align" => TEXT_ALIGN_TOPLEFT, 249 "FontName" => $CaptionFontName, 250 "FontSize" => $CaptionFontSize, 251 "R" => $Settings["R"] + $SubCaptionColorFactor, 252 "G" => $Settings["G"] + $SubCaptionColorFactor, 253 "B" => $Settings["B"] + $SubCaptionColorFactor 254 ]; 255 } 256 257 $RestoreShadow = $this->pChartObject->Shadow; 258 $this->pChartObject->Shadow = false; 259 260 if ($CaptionLayout == INDICATOR_CAPTION_DEFAULT) { 261 $this->pChartObject->drawText($X1, $Y + $Height + $TextPadding, $Caption, $CaptionColor); 262 } elseif ($CaptionLayout == INDICATOR_CAPTION_EXTENDED) { 263 $TxtPos = $this->pChartObject->getTextBox( 264 $X1, 265 $Y + $Height + $TextPadding, 266 $CaptionFontName, 267 $CaptionFontSize, 268 0, 269 $Caption 270 ); 271 $CaptionHeight = $TxtPos[0]["Y"] - $TxtPos[2]["Y"]; 272 273 $this->pChartObject->drawText( 274 $X1 + $XOffset, 275 $Y + $Height - $YOffset + $TextPadding, 276 $Caption, 277 $CaptionColor 278 ); 279 $this->pChartObject->drawText( 280 $X1 + $XOffset, 281 $Y + $Height - $YOffset + $CaptionHeight + $TextPadding * 2, 282 $SubCaption, 283 $SubCaptionColor 284 ); 285 } 286 287 $this->pChartObject->Shadow = $RestoreShadow; 288 289 $X1 = $X2 + $SectionsMargin; 290 } 291 292 $RestoreShadow = $this->pChartObject->Shadow; 293 $this->pChartObject->Shadow = false; 294 295 foreach ($Values as $Key => $Value) { 296 if ($Value >= $OverallMin && $Value <= $OverallMax) { 297 foreach ($IndicatorSections as $Key => $Settings) { 298 if ($Value >= $Settings["Start"] && $Value <= $Settings["End"]) { 299 $X1 = $ValuesPos[$Value]; //$X + $Key*$SectionsMargin + ($Value - $OverallMin) * $XScale; 300 301 if ($ValueDisplay == INDICATOR_VALUE_BUBBLE) { 302 $TxtPos = $this->pChartObject->getTextBox( 303 $X1, 304 $Y, 305 $ValueFontName, 306 $ValueFontSize, 307 0, 308 $Value . $Unit 309 ); 310 $Radius = floor(($TxtPos[1]["X"] - $TxtPos[0]["X"] + $TextPadding * 4) / 2); 311 312 $this->pChartObject->drawFilledCircle( 313 $X1, 314 $Y, 315 $Radius + 4, 316 [ 317 "R" => $Settings["R"] + 20, 318 "G" => $Settings["G"] + 20, 319 "B" => $Settings["B"] + 20 320 ] 321 ); 322 $this->pChartObject->drawFilledCircle( 323 $X1, 324 $Y, 325 $Radius, 326 ["R" => 255, "G" => 255, "B" => 255] 327 ); 328 329 $TextSettings = [ 330 "Align" => TEXT_ALIGN_MIDDLEMIDDLE, 331 "FontName" => $ValueFontName, 332 "FontSize" => $ValueFontSize 333 ]; 334 $this->pChartObject->drawText($X1 - 1, $Y - 1, $Value . $Unit, $TextSettings); 335 } elseif ($ValueDisplay == INDICATOR_VALUE_LABEL) { 336 $Caption = [ 337 [ 338 "Format" => [ 339 "R" => $Settings["R"], 340 "G" => $Settings["G"], 341 "B" => $Settings["B"], 342 "Alpha" => 100 343 ], 344 "Caption" => $Value . $Unit 345 ] 346 ]; 347 $this->pChartObject->drawLabelBox( 348 floor($X1), 349 floor($Y) + 2, 350 "Value - " . $Settings["Caption"], 351 $Caption 352 ); 353 } 354 } 355 $X1 = $X2 + $SectionsMargin; 356 } 357 } 358 } 359 $this->pChartObject->Shadow = $RestoreShadow; 360 } 361} 362