Switch to actual public/private/protected indicators instead of @access ones
[isso.git] / graph_pie.php
1 <?php
2 /*=====================================================================*\
3 || ###################################################################
4 || # Blue Static ISSO Framework [#]issoversion[#]
5 || # Copyright ©2002-[#]year[#] Blue Static
6 || #
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version [#]gpl[#] of the License.
10 || #
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 || # more details.
15 || #
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
21
22 /**
23 * Graphing system: pie chart
24 * graph_pie.php
25 *
26 * @package ISSO
27 */
28
29 /**
30 * Graphing System: Pie Chart
31 *
32 * This framework creates pie charts as PNG image strings. Simply add to
33 * the data set and graph to get the byte stream returned.
34 *
35 * @author Blue Static
36 * @copyright Copyright ©2002 - [#]year[#], Blue Static
37 * @version $Revision$
38 * @package ISSO
39 *
40 */
41 class Graph_Pie
42 {
43 /**
44 * Framework registry object
45 * @var object
46 */
47 private $registry = null;
48
49 /**
50 * Graphing data set; 2D array of
51 * array(NAME, PERCENT, COLOR)
52 * @var array
53 */
54 private $dataset = array();
55
56 /**
57 * Image resource
58 * @var resource
59 */
60 private $image = null;
61
62 /**
63 * The dimensions of the image
64 * @var array
65 */
66 private $dimensions = array('width' => 550, 'height' => 350);
67
68 /**
69 * Add a legend to the graph
70 * @var bool
71 */
72 private $legend = true;
73
74 /**
75 * Title of the graph
76 * @var string
77 */
78 private $title = 'ISSO Pie Chart';
79
80 // ###################################################################
81 /**
82 * Constructor
83 */
84 function __construct(&$registry)
85 {
86 $this->registry =& $registry;
87
88 $this->set_scale(0);
89 }
90
91 // ###################################################################
92 /**
93 * (PHP 4) Constructor
94 */
95 function Graph_Pie(&$registry)
96 {
97 $this->__construct($registry);
98 }
99
100 // ###################################################################
101 /**
102 * Graphs the actual graph and returns a byte stream
103 *
104 * @access public
105 *
106 * @return string Byte stream
107 */
108 function graph()
109 {
110 $colours['black'] = imagecolorallocate($this->image, 0, 0, 0);
111 $colours['white'] = imagecolorallocate($this->image, 255, 255, 255);
112 $colours['grey'] = imagecolorallocate($this->image, 121, 121, 123);
113
114 $graphpadding = 10;
115 $graphspacing = 4;
116 $diameter = $this->dimensions['height'] - (5 * $graphpadding);
117 $radius = $diameter / 2;
118 $graphstart = $graphpadding + imagefontheight(5) + $graphpadding;
119 $legendbox = 10;
120
121 // fill background
122 imagefill($this->image, 0, 0, $colours['white']);
123
124 // title the chart
125 imagestring($this->image, 5, ($this->dimensions['width'] - (imagefontwidth(5) * strlen($this->title))) / 2, $graphpadding, $this->title, $colours['black']);
126
127 $center = array(
128 'x' => ($this->legend ? ($radius + $graphpadding) : ($this->dimensions['width'] / 2)),
129 'y' => ($this->dimensions['height'] / 2) + $graphpadding
130 );
131
132 // draw a border
133 imageline($this->image, 0, 0, 0, $this->dimensions['height'], $colours['black']); // left
134 imageline($this->image, 0, $this->dimensions['height'] - 1, $this->dimensions['width'], $this->dimensions['height'] - 1, $colours['black']); // bottom
135 imageline($this->image, $this->dimensions['width'] - 1, 0, $this->dimensions['width'] - 1, $this->dimensions['height'], $colours['black']); // right
136 imageline($this->image, 0, 0, $this->dimensions['width'], 0, $colours['black']); // top
137
138 $legx = (2 * $graphpadding) + $diameter;
139
140 $lastdeg = 0;
141 $boxoffset = 0;
142 foreach ($this->dataset AS $plot)
143 {
144 $deg = (360 / 100) * $plot[1];
145 imagefilledarc($this->image, $center['x'], $center['y'], $diameter, $diameter, $lastdeg, $deg + $lastdeg, $plot[2], IMG_ARC_PIE);
146 imagefilledarc($this->image, $center['x'], $center['y'], $diameter, $diameter, $lastdeg, $deg + $lastdeg, $colours['grey'], IMG_ARC_EDGED | IMG_ARC_NOFILL);
147 $lastdeg += $deg;
148
149 if ($this->legend)
150 {
151 $box = array(
152 $legx + 1 + $graphspacing, $graphstart + 1 + $graphspacing + $boxoffset, // top left
153 $legx + 1 + $graphspacing, $graphstart + 1 + $graphspacing + $boxoffset + $legendbox, // bottom left
154 $legx + 1 + $graphspacing + $legendbox, $graphstart + 1 + $graphspacing + $boxoffset + $legendbox, // bottom right
155 $legx + 1 + $graphspacing + $legendbox, $graphstart + 1 + $graphspacing + $boxoffset // top right
156 );
157 imagefilledpolygon($this->image, $box, 4, $plot[2]);
158
159 imagestring($this->image, 2, ($legx + 1 + $graphspacing + $legendbox + $graphspacing), ($graphstart + $graphspacing + $boxoffset), $plot[0] . " ($plot[1]%)", $colours['black']);
160
161 $boxoffset += $graphspacing + $legendbox;
162 }
163 }
164
165 // draw the ellipse (do here so it cleans up the arc edges)
166 imageellipse($this->image, $center['x'], $center['y'], $diameter, $diameter, $colours['grey']);
167
168 // do the legend
169 if ($this->legend)
170 {
171 imageline($this->image, $legx, $graphstart, $this->dimensions['width'] - $graphpadding, $graphstart, $colours['black']); // top
172 imageline($this->image, $legx, $graphstart, $legx, $legy = ($graphstart + $graphspacing + $boxoffset + 1), $colours['black']); // left
173 imageline($this->image, $legx, $legy, $this->dimensions['width'] - $graphpadding, $legy, $colours['black']); // bottom
174 imageline($this->image, $this->dimensions['width'] - $graphpadding, $graphstart, $this->dimensions['width'] - $graphpadding, $legy, $colours['black']); // right
175 }
176
177 ob_start();
178 imagepng($this->image);
179 $data = ob_get_contents();
180 if ($data === false)
181 {
182 $data = ob_get_clean();
183 }
184 ob_clean();
185 ob_end_clean();
186
187 return $data;
188 }
189
190 // ###################################################################
191 /**
192 * Sets the width and height by using scale factors of 550x350; you
193 * can specify a positive value to multiply by that many times or a
194 * negative one to divide
195 *
196 * @access public
197 *
198 * @param float Scale factor
199 */
200 function set_scale($scale)
201 {
202 $this->dimensions['width'] = 550;
203 $this->dimensions['height'] = 350;
204
205 if ($scale > 0)
206 {
207 $this->dimensions['width'] *= $scale;
208 $this->dimensions['height'] *= $scale;
209 }
210 else if ($scale < 0)
211 {
212 $scale = abs($scale);
213 $this->dimensions['width'] /= $scale;
214 $this->dimensions['height'] /= $scale;
215 }
216
217 if (!is_null($this->image))
218 {
219 imagedestroy($this->image);
220 }
221
222 $this->image = imagecreate($this->dimensions['width'], $this->dimensions['height']);
223 }
224
225 // ###################################################################
226 /**
227 * Sets whether or not a legend is created for the graph
228 *
229 * @access public
230 *
231 * @param bool Draw a legend?
232 */
233 function set_legend($yesno)
234 {
235 $this->legend = (bool)$yesno;
236 }
237
238 // ###################################################################
239 /**
240 * Sets the title of the chart to be drawn above the graph
241 *
242 * @access public
243 *
244 * @param string Title of the chart
245 */
246 function set_title($title)
247 {
248 $this->title = $title;
249 }
250
251 // ###################################################################
252 /**
253 * Adds an entry to the data set without specifying a colour to add.
254 * This is the standard method as the colour should only be overridden
255 * if necessary.
256 *
257 * @access public
258 *
259 * @param string Data column name
260 * @param integer Percentage of 100
261 */
262 function add_data_set($name, $percent)
263 {
264 $this->dataset[] = array($name, intval($percent), $this->fetch_colour());
265 }
266
267 // ###################################################################
268 /**
269 * Adds an entry ot the data set with specifying a colour. This works
270 * the same as add_data_st() but requires an array() as the 3rd parameter
271 * of R,G,B values
272 *
273 * @access public
274 *
275 * @param string Data column name
276 * @param integer Percent of 100
277 * @param array Array of R,G,B values
278 */
279 function add_data_set_colour($name, $percent, $colour)
280 {
281 $this->dataset[] = array($name, intval($percent), imagecolorallocate($this->image, $colour[0], $colour[1], $colour[2]));
282 }
283
284 // ###################################################################
285 /**
286 * Fetches a colour from the allocated colour list and returns the value
287 *
288 * @access private
289 *
290 * @return integer Allocated colour resource
291 */
292 function fetch_colour()
293 {
294 static $colourlist = array(
295 array(100, 60, 175),
296 array(221, 110, 21),
297 array(179, 34, 31),
298 array(69, 196, 243),
299 array(128, 186, 33),
300 array(28, 101, 155),
301 array(246, 204, 95),
302 array(6, 43, 147),
303 array(204, 61, 7),
304 array(170, 169, 174),
305 array(90, 15, 24),
306 array(45, 130, 195)
307 );
308 static $allocated = 0;
309
310 $colour = $colourlist["$allocated"];
311 $allocated++;
312
313 return imagecolorallocate($this->image, $colour[0], $colour[1], $colour[2]);
314 }
315 }
316
317 /*=====================================================================*\
318 || ###################################################################
319 || # $HeadURL$
320 || # $Id$
321 || ###################################################################
322 \*=====================================================================*/
323 ?>