1<?php
2
3namespace CpChart\Chart;
4
5use CpChart\Data;
6use CpChart\Image;
7
8/**
9 *    Split - class to draw spline splitted charts
10 *
11 *    Version     : 2.1.4
12 *    Made by     : Jean-Damien POGOLOTTI
13 *    Last Update : 19/01/2014
14 *
15 *    This file can be distributed under the license you can find at :
16 *
17 *                      http://www.pchart.net/license
18 *
19 *    You can find the whole class documentation on the pChart web site.
20 */
21class Split
22{
23    /**
24     * @var Image
25     */
26    public $pChartObject;
27
28    /**
29     * Create the encoded string
30     * @param Image $Object
31     * @param Data $Values
32     * @param array $Format
33     */
34    public function drawSplitPath(Image $Object, Data $Values, array $Format = [])
35    {
36        $this->pChartObject = $Object;
37
38        $Spacing = isset($Format["Spacing"]) ? $Format["Spacing"] : 20;
39        $TextPadding = isset($Format["TextPadding"]) ? $Format["TextPadding"] : 2;
40        $TextPos = isset($Format["TextPos"]) ? $Format["TextPos"] : TEXT_POS_TOP;
41        $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : null;
42        $Force = isset($Format["Force"]) ? $Format["Force"] : 70;
43        $Segments = isset($Format["Segments"]) ? $Format["Segments"] : 15;
44        $X1 = $Object->GraphAreaX1;
45        $Y1 = $Object->GraphAreaY1;
46        $X2 = $Object->GraphAreaX2;
47        $Y2 = $Object->GraphAreaY2;
48
49        /* Data Processing */
50        $Data = $Values->getData();
51        $Palette = $Values->getPalette();
52
53        $LabelSerie = $Data["Abscissa"];
54        $DataSerie = [];
55
56        foreach ($Data["Series"] as $SerieName => $Value) {
57            if ($SerieName != $LabelSerie && empty($DataSerie)) {
58                $DataSerie = $SerieName;
59            }
60        }
61
62        $DataSerieSum = array_sum($Data["Series"][$DataSerie]["Data"]);
63        $DataSerieCount = count($Data["Series"][$DataSerie]["Data"]);
64
65        /* Scale Processing */
66        if ($TextPos == TEXT_POS_RIGHT) {
67            $YScale = (($Y2 - $Y1) - (($DataSerieCount + 1) * $Spacing)) / $DataSerieSum;
68        } else {
69            $YScale = (($Y2 - $Y1) - ($DataSerieCount * $Spacing)) / $DataSerieSum;
70        }
71        $LeftHeight = $DataSerieSum * $YScale;
72
73        /* Re-compute graph width depending of the text mode choosen */
74        if ($TextPos == TEXT_POS_RIGHT) {
75            $MaxWidth = 0;
76            foreach ($Data["Series"][$LabelSerie]["Data"] as $Key => $Label) {
77                $Boundardies = $Object->getTextBox(0, 0, $Object->FontName, $Object->FontSize, 0, $Label);
78                if ($Boundardies[1]["X"] > $MaxWidth) {
79                    $MaxWidth = $Boundardies[1]["X"] + $TextPadding * 2;
80                }
81            }
82            $X2 = $X2 - $MaxWidth;
83        }
84
85        /* Drawing */
86        $LeftY = ((($Y2 - $Y1) / 2) + $Y1) - ($LeftHeight / 2);
87        $RightY = $Y1;
88
89        foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value) {
90            if (isset($Data["Series"][$LabelSerie]["Data"][$Key])) {
91                $Label = $Data["Series"][$LabelSerie]["Data"][$Key];
92            } else {
93                $Label = "-";
94            }
95            $LeftY1 = $LeftY;
96            $LeftY2 = $LeftY + $Value * $YScale;
97
98            $RightY1 = $RightY + $Spacing;
99            $RightY2 = $RightY + $Spacing + $Value * $YScale;
100
101            $Settings = [
102                "R" => $Palette[$Key]["R"],
103                "G" => $Palette[$Key]["G"],
104                "B" => $Palette[$Key]["B"],
105                "Alpha" => $Palette[$Key]["Alpha"],
106                "NoDraw" => true,
107                "Segments" => $Segments,
108                "Surrounding" => $Surrounding
109            ];
110
111
112            $Angle = $Object->getAngle($X2, $RightY1, $X1, $LeftY1);
113            $VectorX1 = cos(deg2rad($Angle + 90)) * $Force + ($X2 - $X1) / 2 + $X1;
114            $VectorY1 = sin(deg2rad($Angle + 90)) * $Force + ($RightY1 - $LeftY1) / 2 + $LeftY1;
115            $VectorX2 = cos(deg2rad($Angle - 90)) * $Force + ($X2 - $X1) / 2 + $X1;
116            $VectorY2 = sin(deg2rad($Angle - 90)) * $Force + ($RightY1 - $LeftY1) / 2 + $LeftY1;
117
118            $Points = $Object->drawBezier(
119                $X1,
120                $LeftY1,
121                $X2,
122                $RightY1,
123                $VectorX1,
124                $VectorY1,
125                $VectorX2,
126                $VectorY2,
127                $Settings
128            );
129
130            $PolyGon = [];
131            foreach ($Points as $Key => $Pos) {
132                $PolyGon[] = $Pos["X"];
133                $PolyGon[] = $Pos["Y"];
134            }
135
136            $Angle = $Object->getAngle($X2, $RightY2, $X1, $LeftY2);
137            $VectorX1 = cos(deg2rad($Angle + 90)) * $Force + ($X2 - $X1) / 2 + $X1;
138            $VectorY1 = sin(deg2rad($Angle + 90)) * $Force + ($RightY2 - $LeftY2) / 2 + $LeftY2;
139            $VectorX2 = cos(deg2rad($Angle - 90)) * $Force + ($X2 - $X1) / 2 + $X1;
140            $VectorY2 = sin(deg2rad($Angle - 90)) * $Force + ($RightY2 - $LeftY2) / 2 + $LeftY2;
141
142            $Points = $Object->drawBezier(
143                $X1,
144                $LeftY2,
145                $X2,
146                $RightY2,
147                $VectorX1,
148                $VectorY1,
149                $VectorX2,
150                $VectorY2,
151                $Settings
152            );
153            $Points = array_reverse($Points);
154            foreach ($Points as $Key => $Pos) {
155                $PolyGon[] = $Pos["X"];
156                $PolyGon[] = $Pos["Y"];
157            }
158
159            $Object->drawPolygon($PolyGon, $Settings);
160
161            if ($TextPos == TEXT_POS_RIGHT) {
162                $Object->drawText(
163                    $X2 + $TextPadding,
164                    ($RightY2 - $RightY1) / 2 + $RightY1,
165                    $Label,
166                    ["Align" => TEXT_ALIGN_MIDDLELEFT]
167                );
168            } else {
169                $Object->drawText(
170                    $X2,
171                    $RightY1 - $TextPadding,
172                    $Label,
173                    ["Align" => TEXT_ALIGN_BOTTOMRIGHT]
174                );
175            }
176            $LeftY = $LeftY2;
177            $RightY = $RightY2;
178        }
179    }
180}
181