Bubble.php
1 year ago
Indicator.php
1 year ago
Pie.php
1 year ago
Radar.php
1 year ago
Scatter.php
1 year ago
Split.php
1 year ago
Spring.php
1 year ago
Stock.php
1 year ago
Surface.php
1 year ago
Indicator.php
233 lines
| 1 | <?php |
| 2 | |
| 3 | namespace CpChart\Chart; |
| 4 | |
| 5 | use CpChart\Image; |
| 6 | /** |
| 7 | * Indicator - class to draw indicators |
| 8 | * |
| 9 | * Version : 2.1.4 |
| 10 | * Made by : Jean-Damien POGOLOTTI |
| 11 | * Last Update : 19/01/2014 |
| 12 | * |
| 13 | * This file can be distributed under the license you can find at : |
| 14 | * |
| 15 | * http://www.pchart.net/license |
| 16 | * |
| 17 | * You can find the whole class documentation on the pChart web site. |
| 18 | */ |
| 19 | class Indicator |
| 20 | { |
| 21 | /** |
| 22 | * @var Image |
| 23 | */ |
| 24 | public $pChartObject; |
| 25 | /** |
| 26 | * @param Image $pChartObject |
| 27 | */ |
| 28 | public function __construct(Image $pChartObject) |
| 29 | { |
| 30 | $this->pChartObject = $pChartObject; |
| 31 | } |
| 32 | /** |
| 33 | * Draw an indicator |
| 34 | * |
| 35 | * @param int $X |
| 36 | * @param int $Y |
| 37 | * @param int $Width |
| 38 | * @param int $Height |
| 39 | * @param array $Format |
| 40 | * @return null|int |
| 41 | */ |
| 42 | public function draw($X, $Y, $Width, $Height, array $Format = []) |
| 43 | { |
| 44 | $Values = isset($Format["Values"]) ? $Format["Values"] : VOID; |
| 45 | $IndicatorSections = isset($Format["IndicatorSections"]) ? $Format["IndicatorSections"] : null; |
| 46 | $ValueDisplay = isset($Format["ValueDisplay"]) ? $Format["ValueDisplay"] : INDICATOR_VALUE_BUBBLE; |
| 47 | $SectionsMargin = isset($Format["SectionsMargin"]) ? $Format["SectionsMargin"] : 4; |
| 48 | $DrawLeftHead = isset($Format["DrawLeftHead"]) ? $Format["DrawLeftHead"] : \true; |
| 49 | $DrawRightHead = isset($Format["DrawRightHead"]) ? $Format["DrawRightHead"] : \true; |
| 50 | $HeadSize = isset($Format["HeadSize"]) ? $Format["HeadSize"] : floor($Height / 4); |
| 51 | $TextPadding = isset($Format["TextPadding"]) ? $Format["TextPadding"] : 4; |
| 52 | $CaptionLayout = isset($Format["CaptionLayout"]) ? $Format["CaptionLayout"] : INDICATOR_CAPTION_EXTENDED; |
| 53 | $CaptionPosition = isset($Format["CaptionPosition"]) ? $Format["CaptionPosition"] : INDICATOR_CAPTION_INSIDE; |
| 54 | $CaptionColorFactor = isset($Format["CaptionColorFactor"]) ? $Format["CaptionColorFactor"] : null; |
| 55 | $CaptionR = isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255; |
| 56 | $CaptionG = isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255; |
| 57 | $CaptionB = isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255; |
| 58 | $CaptionAlpha = isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100; |
| 59 | $SubCaptionColorFactor = isset($Format["SubCaptionColorFactor"]) ? $Format["SubCaptionColorFactor"] : null; |
| 60 | $SubCaptionR = isset($Format["SubCaptionR"]) ? $Format["SubCaptionR"] : 50; |
| 61 | $SubCaptionG = isset($Format["SubCaptionG"]) ? $Format["SubCaptionG"] : 50; |
| 62 | $SubCaptionB = isset($Format["SubCaptionB"]) ? $Format["SubCaptionB"] : 50; |
| 63 | $SubCaptionAlpha = isset($Format["SubCaptionAlpha"]) ? $Format["SubCaptionAlpha"] : 100; |
| 64 | $ValueFontName = isset($Format["ValueFontName"]) ? $Format["ValueFontName"] : $this->pChartObject->FontName; |
| 65 | $ValueFontSize = isset($Format["ValueFontSize"]) ? $Format["ValueFontSize"] : $this->pChartObject->FontSize; |
| 66 | $CaptionFontName = isset($Format["CaptionFontName"]) ? $Format["CaptionFontName"] : $this->pChartObject->FontName; |
| 67 | $CaptionFontSize = isset($Format["CaptionFontSize"]) ? $Format["CaptionFontSize"] : $this->pChartObject->FontSize; |
| 68 | $Unit = isset($Format["Unit"]) ? $Format["Unit"] : ""; |
| 69 | /* Convert the Values to display to an array if needed */ |
| 70 | if (!is_array($Values)) { |
| 71 | $Values = [$Values]; |
| 72 | } |
| 73 | /* No section, let's die */ |
| 74 | if ($IndicatorSections == null) { |
| 75 | return 0; |
| 76 | } |
| 77 | /* Determine indicator visual configuration */ |
| 78 | $OverallMin = $IndicatorSections[0]["End"]; |
| 79 | $OverallMax = $IndicatorSections[0]["Start"]; |
| 80 | foreach ($IndicatorSections as $Key => $Settings) { |
| 81 | if ($Settings["End"] > $OverallMax) { |
| 82 | $OverallMax = $Settings["End"]; |
| 83 | } |
| 84 | if ($Settings["Start"] < $OverallMin) { |
| 85 | $OverallMin = $Settings["Start"]; |
| 86 | } |
| 87 | } |
| 88 | $RealWidth = $Width - (count($IndicatorSections) - 1) * $SectionsMargin; |
| 89 | $XScale = $RealWidth / ($OverallMax - $OverallMin); |
| 90 | $X1 = $X; |
| 91 | $ValuesPos = []; |
| 92 | foreach ($IndicatorSections as $Key => $Settings) { |
| 93 | $Color = ["R" => $Settings["R"], "G" => $Settings["G"], "B" => $Settings["B"]]; |
| 94 | $Caption = $Settings["Caption"]; |
| 95 | $SubCaption = $Settings["Start"] . " - " . $Settings["End"]; |
| 96 | $X2 = $X1 + ($Settings["End"] - $Settings["Start"]) * $XScale; |
| 97 | if ($Key == 0 && $DrawLeftHead) { |
| 98 | $Poly = []; |
| 99 | $Poly[] = $X1 - 1; |
| 100 | $Poly[] = $Y; |
| 101 | $Poly[] = $X1 - 1; |
| 102 | $Poly[] = $Y + $Height; |
| 103 | $Poly[] = $X1 - 1 - $HeadSize; |
| 104 | $Poly[] = $Y + $Height / 2; |
| 105 | $this->pChartObject->drawPolygon($Poly, $Color); |
| 106 | $this->pChartObject->drawLine($X1 - 2, $Y, $X1 - 2 - $HeadSize, $Y + $Height / 2, $Color); |
| 107 | $this->pChartObject->drawLine($X1 - 2, $Y + $Height, $X1 - 2 - $HeadSize, $Y + $Height / 2, $Color); |
| 108 | } |
| 109 | /* Determine the position of the breaks */ |
| 110 | $Break = []; |
| 111 | foreach ($Values as $iKey => $Value) { |
| 112 | if ($Value >= $Settings["Start"] && $Value <= $Settings["End"]) { |
| 113 | $XBreak = $X1 + ($Value - $Settings["Start"]) * $XScale; |
| 114 | $ValuesPos[$Value] = $XBreak; |
| 115 | $Break[] = floor($XBreak); |
| 116 | } |
| 117 | } |
| 118 | if ($ValueDisplay == INDICATOR_VALUE_LABEL) { |
| 119 | if (!count($Break)) { |
| 120 | $this->pChartObject->drawFilledRectangle($X1, $Y, $X2, $Y + $Height, $Color); |
| 121 | } else { |
| 122 | sort($Break); |
| 123 | $Poly = []; |
| 124 | $Poly[] = $X1; |
| 125 | $Poly[] = $Y; |
| 126 | $LastPointWritten = \false; |
| 127 | foreach ($Break as $iKey => $Value) { |
| 128 | if ($Value - 5 >= $X1) { |
| 129 | $Poly[] = $Value - 5; |
| 130 | $Poly[] = $Y; |
| 131 | } elseif ($X1 - ($Value - 5) > 0) { |
| 132 | $Offset = $X1 - ($Value - 5); |
| 133 | $Poly = [$X1, $Y + $Offset]; |
| 134 | } |
| 135 | $Poly[] = $Value; |
| 136 | $Poly[] = $Y + 5; |
| 137 | if ($Value + 5 <= $X2) { |
| 138 | $Poly[] = $Value + 5; |
| 139 | $Poly[] = $Y; |
| 140 | } elseif ($Value + 5 > $X2) { |
| 141 | $Offset = $Value + 5 - $X2; |
| 142 | $Poly[] = $X2; |
| 143 | $Poly[] = $Y + $Offset; |
| 144 | $LastPointWritten = \true; |
| 145 | } |
| 146 | } |
| 147 | if (!$LastPointWritten) { |
| 148 | $Poly[] = $X2; |
| 149 | $Poly[] = $Y; |
| 150 | } |
| 151 | $Poly[] = $X2; |
| 152 | $Poly[] = $Y + $Height; |
| 153 | $Poly[] = $X1; |
| 154 | $Poly[] = $Y + $Height; |
| 155 | $this->pChartObject->drawPolygon($Poly, $Color); |
| 156 | } |
| 157 | } else { |
| 158 | $this->pChartObject->drawFilledRectangle($X1, $Y, $X2, $Y + $Height, $Color); |
| 159 | } |
| 160 | if ($Key == count($IndicatorSections) - 1 && $DrawRightHead) { |
| 161 | $Poly = []; |
| 162 | $Poly[] = $X2 + 1; |
| 163 | $Poly[] = $Y; |
| 164 | $Poly[] = $X2 + 1; |
| 165 | $Poly[] = $Y + $Height; |
| 166 | $Poly[] = $X2 + 1 + $HeadSize; |
| 167 | $Poly[] = $Y + $Height / 2; |
| 168 | $this->pChartObject->drawPolygon($Poly, $Color); |
| 169 | $this->pChartObject->drawLine($X2 + 1, $Y, $X2 + 1 + $HeadSize, $Y + $Height / 2, $Color); |
| 170 | $this->pChartObject->drawLine($X2 + 1, $Y + $Height, $X2 + 1 + $HeadSize, $Y + $Height / 2, $Color); |
| 171 | } |
| 172 | $YOffset = 0; |
| 173 | $XOffset = 0; |
| 174 | if ($CaptionPosition == INDICATOR_CAPTION_INSIDE) { |
| 175 | $TxtPos = $this->pChartObject->getTextBox($X1, $Y + $Height + $TextPadding, $CaptionFontName, $CaptionFontSize, 0, $Caption); |
| 176 | $YOffset = $TxtPos[0]["Y"] - $TxtPos[2]["Y"] + $TextPadding; |
| 177 | if ($CaptionLayout == INDICATOR_CAPTION_EXTENDED) { |
| 178 | $TxtPos = $this->pChartObject->getTextBox($X1, $Y + $Height + $TextPadding, $CaptionFontName, $CaptionFontSize, 0, $SubCaption); |
| 179 | $YOffset = $YOffset + ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]) + $TextPadding * 2; |
| 180 | } |
| 181 | $XOffset = $TextPadding; |
| 182 | } |
| 183 | if ($CaptionColorFactor == null) { |
| 184 | $CaptionColor = ["Align" => TEXT_ALIGN_TOPLEFT, "FontName" => $CaptionFontName, "FontSize" => $CaptionFontSize, "R" => $CaptionR, "G" => $CaptionG, "B" => $CaptionB, "Alpha" => $CaptionAlpha]; |
| 185 | } else { |
| 186 | $CaptionColor = ["Align" => TEXT_ALIGN_TOPLEFT, "FontName" => $CaptionFontName, "FontSize" => $CaptionFontSize, "R" => $Settings["R"] + $CaptionColorFactor, "G" => $Settings["G"] + $CaptionColorFactor, "B" => $Settings["B"] + $CaptionColorFactor]; |
| 187 | } |
| 188 | if ($SubCaptionColorFactor == null) { |
| 189 | $SubCaptionColor = ["Align" => TEXT_ALIGN_TOPLEFT, "FontName" => $CaptionFontName, "FontSize" => $CaptionFontSize, "R" => $SubCaptionR, "G" => $SubCaptionG, "B" => $SubCaptionB, "Alpha" => $SubCaptionAlpha]; |
| 190 | } else { |
| 191 | $SubCaptionColor = ["Align" => TEXT_ALIGN_TOPLEFT, "FontName" => $CaptionFontName, "FontSize" => $CaptionFontSize, "R" => $Settings["R"] + $SubCaptionColorFactor, "G" => $Settings["G"] + $SubCaptionColorFactor, "B" => $Settings["B"] + $SubCaptionColorFactor]; |
| 192 | } |
| 193 | $RestoreShadow = $this->pChartObject->Shadow; |
| 194 | $this->pChartObject->Shadow = \false; |
| 195 | if ($CaptionLayout == INDICATOR_CAPTION_DEFAULT) { |
| 196 | $this->pChartObject->drawText($X1, $Y + $Height + $TextPadding, $Caption, $CaptionColor); |
| 197 | } elseif ($CaptionLayout == INDICATOR_CAPTION_EXTENDED) { |
| 198 | $TxtPos = $this->pChartObject->getTextBox($X1, $Y + $Height + $TextPadding, $CaptionFontName, $CaptionFontSize, 0, $Caption); |
| 199 | $CaptionHeight = $TxtPos[0]["Y"] - $TxtPos[2]["Y"]; |
| 200 | $this->pChartObject->drawText($X1 + $XOffset, $Y + $Height - $YOffset + $TextPadding, $Caption, $CaptionColor); |
| 201 | $this->pChartObject->drawText($X1 + $XOffset, $Y + $Height - $YOffset + $CaptionHeight + $TextPadding * 2, $SubCaption, $SubCaptionColor); |
| 202 | } |
| 203 | $this->pChartObject->Shadow = $RestoreShadow; |
| 204 | $X1 = $X2 + $SectionsMargin; |
| 205 | } |
| 206 | $RestoreShadow = $this->pChartObject->Shadow; |
| 207 | $this->pChartObject->Shadow = \false; |
| 208 | foreach ($Values as $Key => $Value) { |
| 209 | if ($Value >= $OverallMin && $Value <= $OverallMax) { |
| 210 | foreach ($IndicatorSections as $Key => $Settings) { |
| 211 | if ($Value >= $Settings["Start"] && $Value <= $Settings["End"]) { |
| 212 | $X1 = $ValuesPos[$Value]; |
| 213 | //$X + $Key*$SectionsMargin + ($Value - $OverallMin) * $XScale; |
| 214 | if ($ValueDisplay == INDICATOR_VALUE_BUBBLE) { |
| 215 | $TxtPos = $this->pChartObject->getTextBox($X1, $Y, $ValueFontName, $ValueFontSize, 0, $Value . $Unit); |
| 216 | $Radius = floor(($TxtPos[1]["X"] - $TxtPos[0]["X"] + $TextPadding * 4) / 2); |
| 217 | $this->pChartObject->drawFilledCircle($X1, $Y, $Radius + 4, ["R" => $Settings["R"] + 20, "G" => $Settings["G"] + 20, "B" => $Settings["B"] + 20]); |
| 218 | $this->pChartObject->drawFilledCircle($X1, $Y, $Radius, ["R" => 255, "G" => 255, "B" => 255]); |
| 219 | $TextSettings = ["Align" => TEXT_ALIGN_MIDDLEMIDDLE, "FontName" => $ValueFontName, "FontSize" => $ValueFontSize]; |
| 220 | $this->pChartObject->drawText($X1 - 1, $Y - 1, $Value . $Unit, $TextSettings); |
| 221 | } elseif ($ValueDisplay == INDICATOR_VALUE_LABEL) { |
| 222 | $Caption = [["Format" => ["R" => $Settings["R"], "G" => $Settings["G"], "B" => $Settings["B"], "Alpha" => 100], "Caption" => $Value . $Unit]]; |
| 223 | $this->pChartObject->drawLabelBox(floor($X1), floor($Y) + 2, "Value - " . $Settings["Caption"], $Caption); |
| 224 | } |
| 225 | } |
| 226 | $X1 = $X2 + $SectionsMargin; |
| 227 | } |
| 228 | } |
| 229 | } |
| 230 | $this->pChartObject->Shadow = $RestoreShadow; |
| 231 | } |
| 232 | } |
| 233 |