Merge branch 'maint/7.0'
[ninja.git] / application / vendor / mfchart / PieChart.php
blob82452c4ca8ccbfd71f4a6eb4b0e2fa1e33ff9d46
1 <?php
3 // only 3d for now
5 class PieChart extends Chart {
7 protected $legend_precision = 1; // percentage round
9 protected $spacing = 2; // spacing between slices
12 public function __construct($width=NULL, $height=NULL)
14 $width = 300;
15 $height = 235;
16 parent::__construct($width, $height);
18 $this->set_margins(0);
20 $this->colors['colors'] = array( // for drawing "value lines"
21 array('#f8d01b', NULL, NULL),
22 array('#f1b71e', NULL, NULL),
23 array('#e38a23', NULL, NULL),
24 array('#d65728', NULL, NULL),
25 array('#ca1d2f', NULL, NULL),
26 array('#c8004d', NULL, NULL),
27 array('#db006f', NULL, NULL),
28 array('#ef008f', NULL, NULL),
29 array('#f7009a', NULL, NULL)
31 $this->colors['legend_color'] = array('#fefefe', NULL, NULL); // background legend color
34 public function set_legend_precision($value)
36 $this->legend_precision = (int) $value;
39 public function draw()
41 parent::draw();
43 foreach ($this->values as $i => $value)
44 if ($value < 0)
45 $this->values[$i] = 0;
47 $plot_sizes = $this->get_plot_area(); // size of the graph area
48 $max_diameter = $plot_sizes[1]; // height of the plot area
50 // get size of the percentage legend
51 $t = '100'. ($this->legend_precision ? '.'. str_repeat('0', $this->legend_precision) : '');
52 $box_points = imagettfbbox($this->font_size, 0, $this->font, $t);
53 $legend_slice_width = $box_points[4]-$box_points[6];
54 $legend_slice_height = $box_points[3]-$box_points[5];
56 $width = $max_diameter-$this->spacing;
57 $height = $max_diameter*0.6;
58 $height_3d = $max_diameter*0.1;
60 $this->legend = array_keys($this->values); // set legend
62 // try to determine width of the legend box (exact width depends on relative font size which could be set when calling $this->draw_legend and margins)
63 $legend_width = 0;
64 foreach ($this->legend as $l)
66 $box_points = imagettfbbox($this->font_size, 0, $this->font, $l);
67 $legend_width = $box_points[4]-$box_points[6];
68 if ($legend_width < $width)
69 $legend_width = $width;
72 $legend_width += 0; // some margins
74 $margin_left = ($this->width-$width+35) / 2;
75 $center_x = $width/2+$margin_left;
76 $center_y = $this->margin_top + ($height+$height_3d)/2;
78 $ratio = array_sum($this->values)/360;
80 if ($ratio != 0) // so there is something to display
83 // steps for gradient in 3d
84 $step = 2;
85 $substep = 2;
87 $start = 300;
88 $slices = array();
89 $i = 0;
90 foreach ($this->values as $key => $value)
92 // make the color for 3d darker
93 $hexcolor = $this->get_color('colors', $i, 0);
94 if( $hexcolor !== false ) {
95 $colortop = utilities::hex2rgb($hexcolor);
96 $colorbottom[0] = $colortop[0]-40 < 0 ? 0 : $colortop[0]-40;
97 $colorbottom[1] = $colortop[1]-40 < 0 ? 0 : $colortop[1]-40;
98 $colorbottom[2] = $colortop[2]-40 < 0 ? 0 : $colortop[2]-40;
100 $arc = $value/$ratio;
101 $slices[] = array($start, $start+$arc, $colorbottom, $substep, $colortop, round($arc/3.6, $this->legend_precision));
102 $start += $arc;
104 $i++;
107 // make the 3D effect
108 for ($j=$height_3d; $j>0; $j--)
110 foreach ($slices as $i => $slice)
112 if (round($slice[0]) == round ($slice[1]))
113 continue;
115 $center_x_spaced = $center_x;
116 $center_y_spaced = $center_y;
117 if ($this->spacing)
119 $arc_half = $slice[0] + ($slice[1]-$slice[0])/2;
120 $cos = cos(utilities::deg2rad($arc_half));
121 $sin = sin(utilities::deg2rad($arc_half));
122 $center_x_spaced = $center_x_spaced + $cos*$this->spacing;
123 $center_y_spaced = $center_y_spaced - $sin*$this->spacing;
126 $color = $slice[2];
127 $color[] = 0;
128 imageSmoothArc($this->image, $center_x_spaced, $center_y_spaced+$j, $width, $height, $color, utilities::deg2rad($slice[0]), utilities::deg2rad($slice[1]));
130 // try to determine next color for gradient
131 if ($j % $step == 0)
133 if ($slice[2][0] != 255)
134 $slices[$i][2][0] = ($slice[2][0]+$slice[3] > 255) ? 255 : $slice[2][0]+$slice[3];
135 else
136 $slices[$i][3] += 1;
138 if ($slice[2][1] != 255)
139 $slices[$i][2][1] = ($slice[2][1]+$slice[3] > 255) ? 255 : $slice[2][1]+$slice[3];
140 else
141 $slices[$i][3] += 1;
143 if ($slice[2][2] != 255)
144 $slices[$i][2][2] = ($slice[2][2]+$slice[3] > 255) ? 255 : $slice[2][2]+$slice[3];
145 else
146 $slices[$i][3] += 1;
151 foreach ($slices as $slice)
153 if (round($slice[0]) == round ($slice[1]))
154 continue;
156 $arc_half = ($slice[0] + ($slice[1]-$slice[0])/2) % 360;
157 $cos = cos(utilities::deg2rad($arc_half));
158 $sin = sin(utilities::deg2rad($arc_half));
160 $center_x_spaced = $center_x;
161 $center_y_spaced = $center_y;
162 if ($this->spacing)
164 $center_x_spaced = $center_x_spaced + $cos*$this->spacing;
165 $center_y_spaced = $center_y_spaced - $sin*$this->spacing;
168 // draw the top
170 $color = $slice[4];
171 $color[] = 0;
173 imageSmoothArc($this->image, $center_x_spaced, $center_y_spaced, $width, $height, $color, utilities::deg2rad($slice[0]), utilities::deg2rad($slice[1]));
176 $a = $width/2;
177 $b = $height/2;
179 // radius of an ellipse
180 $r = $a*$b / sqrt(pow($b,2)*pow($cos,2) + pow($a,2)*pow($sin,2));
181 $r += 15; // padding from the graph
183 $legend_slice_x = $center_x_spaced + $cos*$r;
184 $legend_slice_y = (($arc_half > 180 AND $arc_half < 360) ? $center_y_spaced+$height_3d : $center_y_spaced) - $sin*$r;
186 $text = $slice[5].'%';
188 $box_points = imagettfbbox($this->font_size, 0, $this->font, $text);
189 $legend_slice_width = $box_points[4]-$box_points[6];
190 $legend_slice_hheight = ($box_points[3]-$box_points[5]) / 2;
192 if (($arc_half >= 0 AND $arc_half < 90) OR ($arc_half >= 270 AND $arc_half < 360))
194 $legend_slice_x1 = $legend_slice_x+$legend_slice_hheight;
195 $legend_slice_y1 = $legend_slice_y-$legend_slice_hheight;
196 $legend_slice_x2 = $legend_slice_x+$legend_slice_width+$legend_slice_hheight;
197 $legend_slice_y2 = $legend_slice_y+$legend_slice_hheight+5;
199 elseif (($arc_half >= 90 AND $arc_half < 180) OR ($arc_half >= 180 AND $arc_half < 270))
201 $legend_slice_x1 = $legend_slice_x-$legend_slice_width-$legend_slice_hheight;
202 $legend_slice_y1 = $legend_slice_y-$legend_slice_hheight;
203 $legend_slice_x2 = $legend_slice_x-$legend_slice_hheight;
204 $legend_slice_y2 = $legend_slice_y+$legend_slice_hheight+5;
207 # print percent value
208 utilities::imagestringbox($this->image, $this->font, $this->font_size, $legend_slice_x1, $legend_slice_y1, $legend_slice_x2, $legend_slice_y2, ALIGN_CENTER, VALIGN_MIDDLE, 0, $text, $this->get_color('font_color'));
213 # print legend
214 //$this->draw_legend('colors', 0, $center_x+$width/2-20+$legend_slice_width*3, $this->height/2-$height/2);
215 $this->draw_legend('colors', 0, 20, $this->height/2+62);