ISSO is no longer a product regularly released so we'll remove the issoversion tag...
[isso.git] / graph_pie.php
1 <?php
2 /*=====================================================================*\
3 || ###################################################################
4 || # Blue Static ISSO Framework
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 public function __construct(&$registry)
85 {
86 $this->registry =& $registry;
87
88 $this->set_scale(0);
89 }
90
91 // ###################################################################
92 /**
93 * Graphs the actual graph and returns a byte stream
94 *
95 * @return string Byte stream
96 */
97 public function graph()
98 {
99 $colours['black'] = imagecolorallocate($this->image, 0, 0, 0);
100 $colours['white'] = imagecolorallocate($this->image, 255, 255, 255);
101 $colours['grey'] = imagecolorallocate($this->image, 121, 121, 123);
102
103 $graphpadding = 10;
104 $graphspacing = 4;
105 $diameter = $this->dimensions['height'] - (5 * $graphpadding);
106 $radius = $diameter / 2;
107 $graphstart = $graphpadding + imagefontheight(5) + $graphpadding;
108 $legendbox = 10;
109
110 // fill background
111 imagefill($this->image, 0, 0, $colours['white']);
112
113 // title the chart
114 imagestring($this->image, 5, ($this->dimensions['width'] - (imagefontwidth(5) * strlen($this->title))) / 2, $graphpadding, $this->title, $colours['black']);
115
116 $center = array(
117 'x' => ($this->legend ? ($radius + $graphpadding) : ($this->dimensions['width'] / 2)),
118 'y' => ($this->dimensions['height'] / 2) + $graphpadding
119 );
120
121 // draw a border
122 imageline($this->image, 0, 0, 0, $this->dimensions['height'], $colours['black']); // left
123 imageline($this->image, 0, $this->dimensions['height'] - 1, $this->dimensions['width'], $this->dimensions['height'] - 1, $colours['black']); // bottom
124 imageline($this->image, $this->dimensions['width'] - 1, 0, $this->dimensions['width'] - 1, $this->dimensions['height'], $colours['black']); // right
125 imageline($this->image, 0, 0, $this->dimensions['width'], 0, $colours['black']); // top
126
127 $legx = (2 * $graphpadding) + $diameter;
128
129 $lastdeg = 0;
130 $boxoffset = 0;
131 foreach ($this->dataset AS $plot)
132 {
133 $deg = (360 / 100) * $plot[1];
134 imagefilledarc($this->image, $center['x'], $center['y'], $diameter, $diameter, $lastdeg, $deg + $lastdeg, $plot[2], IMG_ARC_PIE);
135 imagefilledarc($this->image, $center['x'], $center['y'], $diameter, $diameter, $lastdeg, $deg + $lastdeg, $colours['grey'], IMG_ARC_EDGED | IMG_ARC_NOFILL);
136 $lastdeg += $deg;
137
138 if ($this->legend)
139 {
140 $box = array(
141 $legx + 1 + $graphspacing, $graphstart + 1 + $graphspacing + $boxoffset, // top left
142 $legx + 1 + $graphspacing, $graphstart + 1 + $graphspacing + $boxoffset + $legendbox, // bottom left
143 $legx + 1 + $graphspacing + $legendbox, $graphstart + 1 + $graphspacing + $boxoffset + $legendbox, // bottom right
144 $legx + 1 + $graphspacing + $legendbox, $graphstart + 1 + $graphspacing + $boxoffset // top right
145 );
146 imagefilledpolygon($this->image, $box, 4, $plot[2]);
147
148 imagestring($this->image, 2, ($legx + 1 + $graphspacing + $legendbox + $graphspacing), ($graphstart + $graphspacing + $boxoffset), $plot[0] . " ($plot[1]%)", $colours['black']);
149
150 $boxoffset += $graphspacing + $legendbox;
151 }
152 }
153
154 // draw the ellipse (do here so it cleans up the arc edges)
155 imageellipse($this->image, $center['x'], $center['y'], $diameter, $diameter, $colours['grey']);
156
157 // do the legend
158 if ($this->legend)
159 {
160 imageline($this->image, $legx, $graphstart, $this->dimensions['width'] - $graphpadding, $graphstart, $colours['black']); // top
161 imageline($this->image, $legx, $graphstart, $legx, $legy = ($graphstart + $graphspacing + $boxoffset + 1), $colours['black']); // left
162 imageline($this->image, $legx, $legy, $this->dimensions['width'] - $graphpadding, $legy, $colours['black']); // bottom
163 imageline($this->image, $this->dimensions['width'] - $graphpadding, $graphstart, $this->dimensions['width'] - $graphpadding, $legy, $colours['black']); // right
164 }
165
166 ob_start();
167 imagepng($this->image);
168 $data = ob_get_contents();
169 if ($data === false)
170 {
171 $data = ob_get_clean();
172 }
173 ob_clean();
174 ob_end_clean();
175
176 return $data;
177 }
178
179 // ###################################################################
180 /**
181 * Sets the width and height by using scale factors of 550x350; you
182 * can specify a positive value to multiply by that many times or a
183 * negative one to divide
184 *
185 * @param float Scale factor
186 */
187 public function set_scale($scale)
188 {
189 $this->dimensions['width'] = 550;
190 $this->dimensions['height'] = 350;
191
192 if ($scale > 0)
193 {
194 $this->dimensions['width'] *= $scale;
195 $this->dimensions['height'] *= $scale;
196 }
197 else if ($scale < 0)
198 {
199 $scale = abs($scale);
200 $this->dimensions['width'] /= $scale;
201 $this->dimensions['height'] /= $scale;
202 }
203
204 if (!is_null($this->image))
205 {
206 imagedestroy($this->image);
207 }
208
209 $this->image = imagecreate($this->dimensions['width'], $this->dimensions['height']);
210 }
211
212 // ###################################################################
213 /**
214 * Sets whether or not a legend is created for the graph
215 *
216 * @param bool Draw a legend?
217 */
218 public function set_legend($yesno)
219 {
220 $this->legend = (bool)$yesno;
221 }
222
223 // ###################################################################
224 /**
225 * Sets the title of the chart to be drawn above the graph
226 *
227 * @param string Title of the chart
228 */
229 public function set_title($title)
230 {
231 $this->title = $title;
232 }
233
234 // ###################################################################
235 /**
236 * Adds an entry to the data set without specifying a colour to add.
237 * This is the standard method as the colour should only be overridden
238 * if necessary.
239 *
240 * @param string Data column name
241 * @param integer Percentage of 100
242 */
243 public function add_data_set($name, $percent)
244 {
245 $this->dataset[] = array($name, intval($percent), $this->fetch_colour());
246 }
247
248 // ###################################################################
249 /**
250 * Adds an entry ot the data set with specifying a colour. This works
251 * the same as add_data_st() but requires an array() as the 3rd parameter
252 * of R,G,B values
253 *
254 * @param string Data column name
255 * @param integer Percent of 100
256 * @param array Array of R,G,B values
257 */
258 public function add_data_set_colour($name, $percent, $colour)
259 {
260 $this->dataset[] = array($name, intval($percent), imagecolorallocate($this->image, $colour[0], $colour[1], $colour[2]));
261 }
262
263 // ###################################################################
264 /**
265 * Fetches a colour from the allocated colour list and returns the value
266 *
267 * @return integer Allocated colour resource
268 */
269 private function fetch_colour()
270 {
271 static $colourlist = array(
272 array(100, 60, 175),
273 array(221, 110, 21),
274 array(179, 34, 31),
275 array(69, 196, 243),
276 array(128, 186, 33),
277 array(28, 101, 155),
278 array(246, 204, 95),
279 array(6, 43, 147),
280 array(204, 61, 7),
281 array(170, 169, 174),
282 array(90, 15, 24),
283 array(45, 130, 195)
284 );
285 static $allocated = 0;
286
287 $colour = $colourlist["$allocated"];
288 $allocated++;
289
290 return imagecolorallocate($this->image, $colour[0], $colour[1], $colour[2]);
291 }
292 }
293
294 /*=====================================================================*\
295 || ###################################################################
296 || # $HeadURL$
297 || # $Id$
298 || ###################################################################
299 \*=====================================================================*/
300 ?>