Adding the beginnings of the GraphLine system
[isso.git] / GraphLine.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: Line Graph (GraphLine.php)
24 *
25 * @package ISSO
26 */
27
28 require_once('ISSO/Graph.php');
29
30 /**
31 * Graphing System: Line Graph
32 *
33 * This creates a line graph from a set of data; each point requires
34 * a line name (because this supports multi-line graphing), an x-value,
35 * and a y-value. It creates PNG images.
36 *
37 * @author Blue Static
38 * @copyright Copyright (c)2002 - [#]year[#], Blue Static
39 * @version $Revision$
40 * @package ISSO
41 *
42 */
43 class BSGraphLine extends BSGraph
44 {
45 /**
46 * Graphing dataset; 4D array
47 * array(array(name, array(array(xval, yval))), color)
48 * @var string
49 */
50 protected $dataset = array();
51
52 /**
53 * Array of data points that are used to calculate the standard deviation
54 * @var array
55 */
56 private $piles = array(0 => array(), 1 => array());
57
58 // ###################################################################
59 /**
60 * Does the actual graphing and returns a byte stream of a PNG image
61 *
62 * @return string Byte stream
63 */
64 public function graph()
65 {
66 // calculates the standard deviation of the two piles to determine the x and y intervals
67 $xint = $this->_standardDeviation($this->piles[0]);
68 $yint = $this->_standardDeviation($this->piles[1]);
69
70 $xmin = min($this->piles[0]);
71 $xmin = ($xmin - $xint < 0 ? 0 : $xmin - $xint);
72 $xmax = max($this->piles[0]) + $xint;
73
74 $ymin = min($this->piles[1]);
75 $ymin = ($ymin - $int < 0 ? 0 : $ymin - $yint);
76 $ymax = max($this->piles[1]) + $yint;
77
78
79 }
80
81 // ###################################################################
82 /**
83 * Adds a "line" with a given name and a set of datapoints in the form
84 * array(x, y)
85 *
86 * @param string The line's name
87 * @param array Array of array(x,y) as data points
88 */
89 public function addDataSet($name, $points)
90 {
91 $this->_addPoints($points);
92 $this->_sortPoints($points);
93 $this->dataset[] = array($name, $points, $this->_fetchColor());
94 }
95
96 // ###################################################################
97 /**
98 * This does the same thing as addDataSet(), except the client code
99 * can specify the color in the form of array(R, G, B)
100 *
101 * @param string The line's name
102 * @param array Array of array(x,y) as data points
103 * @param array A color in the form of 3 RGB points
104 */
105 public function addDataSetColor($name, $points, $color)
106 {
107 $this->_addPoints($points);
108 $this->_sortPoints($points);
109 $this->dataset[] = array($name, $points, imagecolorallocate($this->image, $color[0], $color[1], $color[2]));
110 }
111
112 // ###################################################################
113 /**
114 * Adds a set of points to the piles and ensures that they are all valid
115 *
116 * @param array Points to add
117 */
118 private function _addPoints($points)
119 {
120 $xpairs = array();
121 foreach ($points AS $point)
122 {
123 if (isset($xpairs["$point[0]"]))
124 {
125 trigger_error('You cannot have more than one of the same x-values for a given data set');
126 }
127 $xpairs["$point[0]"] = $point[0];
128 $this->piles[0][] = $point[0];
129 $this->piles[1][] = $point[1];
130 }
131 }
132
133 // ###################################################################
134 /**
135 * Sorts an array of points using quick sort so they're in x-increasing
136 * order
137 *
138 * @param array Array of points
139 */
140 private function _sortPoints(&$points)
141 {
142 $this->_quickSortPoints($points, 0, sizeof($points) - 1);
143 }
144
145 // ###################################################################
146 /**
147 * Quicksort function for sorting function
148 *
149 * @param array Array of points
150 * @param integer Lower bound
151 * @param integer Upper bound
152 */
153 private function _quickSortPoints(&$points, $low, $high)
154 {
155 if (($high - $low) > 1)
156 {
157 $partition = $this->_partitionPoints($points, $low, $high);
158 $this->_quickSortPoints($points, $low, $partition);
159 $this->_quickSortPoints($points, $partition + 1, $high);
160 }
161 }
162
163 // ###################################################################
164 /**
165 * Quicksort partitioner: returns the index of the pivot element where
166 * all x-coords on the left side of pivot are less than or equal to
167 * pivot, and all x-coords are higher to the right
168 *
169 * @param array Array of points
170 * @param integer Lower bound
171 * @param integer Upper bound
172 *
173 * @return integer Pivot index
174 */
175 private function _partitionPoints(&$points, $low, $high)
176 {
177 $pivot = $low;
178 for ($unsorted = $low + 1; $unsorted <= $high; $unsorted++)
179 {
180 if ($points[$unsorted][0] < $points[$pivot][0])
181 {
182 $temp = $points[$pivot];
183 $points[$pivot] = $points[$unsorted];
184 $points[$unsorted] = $points[$pivot + 1];
185 $points[$pivot + 1] = $temp;
186 $pivot++;
187 }
188 }
189 return $pivot;
190 }
191
192 // ###################################################################
193 /**
194 * Returns the unbiased statistical standard deviation of an array of
195 * values
196 *
197 * @param array Array of values
198 *
199 * @return float Standard deviation (unbiased)
200 */
201 private function _standardDeviation($vals)
202 {
203 $average = $this->_arrayAverage($vals);
204 $popVariance = array();
205
206 foreach ($vals AS $val)
207 {
208 $popVariance[] = pow($val - $average, 2);
209 }
210
211 return sqrt($this->_arrayAverage($popVariance));
212 }
213
214 // ###################################################################
215 /**
216 * Returns the stastical mean of an array of values
217 *
218 * @param array Array of values
219 *
220 * @return float Statistical mean
221 */
222 private function _arrayAverage($vals)
223 {
224 return array_sum($vals) / count($vals);
225 }
226 }
227
228 /*=====================================================================*
229 || ###################################################################
230 || # $HeadURL$
231 || # $Id$
232 || ###################################################################
233 \*=====================================================================*/
234 ?>