Graph
[ ]
[ ]
[ ]
[ ]
[ ]
Source for file average.php
Documentation is available at average.php
1. <?php
2. /**
3. * File containing the ezcGraphDataSetAverage class
4. *
5. * @package Graph
6. * @version //autogentag//
7. * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
8. * @license http://ez.no/licenses/new_bsd New BSD License
9. */
10. /**
11. * Extension of basic dataset to represent averation.
12. * Algorithm: http://en.wikipedia.org/wiki/Least_squares
13. *
14. * @property int $polynomOrder
15. * Maximum order of polygon to interpolate from points
16. * @property int $resolution
17. * Resolution used to draw line in graph
18. *
19. * @version //autogentag//
20. * @package Graph
21. * @mainclass
22. */
23. class ezcGraphDataSetAveragePolynom extends ezcGraphDataSet
24. {
25.
26. /**
27. * Source dataset to base averation on.
28. *
29. * @var ezcGraphDataSet
30. */
31. protected $source;
32.
33. /**
34. * Calculated averation polynom
35. *
36. * @var ezcGraphPolynom
37. */
38. protected $polynom = false;
39.
40. /**
41. * Minimum key
42. *
43. * @var float
44. */
45. protected $min = false;
46.
47. /**
48. * Maximum key
49. *
50. * @var float
51. */
52. protected $max = false;
53.
54. /**
55. * Position of the data iterator. Depends on the configured resolution.
56. *
57. * @var int
58. */
59. protected $position = 0;
60.
61. /**
62. * Container to hold the properties
63. *
64. * @var array(string=>mixed)
65. */
66. protected $properties;
67.
68. /**
69. * Constructor
70. *
71. * @param ezcGraphDataSet $dataset Dataset to interpolate
72. * @param int $order Maximum order of interpolating polynom
73. * @return void
74. * @ignore
75. */
76. public function __construct( ezcGraphDataSet $dataset, $order = 3 )
77. {
78. parent::__construct();
79.
80. $this->properties['resolution'] = 100;
81. $this->properties['polynomOrder'] = (int) $order;
82.
83. $this->source = $dataset;
84. }
85.
86. /**
87. * Options write access
88. *
89. * @throws ezcBasePropertyNotFoundException
90. * If Option could not be found
91. * @throws ezcBaseValueException
92. * If value is out of range
93. * @param mixed $propertyName Option name
94. * @param mixed $propertyValue Option value;
95. * @return mixed
96. */
97. public function __set( $propertyName, $propertyValue )
98. {
99. switch ( $propertyName ) {
100. case 'polynomOrder':
101. if ( !is_numeric( $propertyValue ) ||
102. ( $propertyValue < 0 ) )
103. {
104. throw new ezcBaseValueException( $propertyName, $propertyValue, 'int > 0' );
105. }
106.
107. $this->properties['polynomOrder'] = (int) $propertyValue;
108. $this->polynom = false;
109. break;
110. case 'resolution':
111. if ( !is_numeric( $propertyValue ) ||
112. ( $propertyValue < 1 ) )
113. {
114. throw new ezcBaseValueException( $propertyName, $propertyValue, 'int > 1' );
115. }
116.
117. $this->properties['resolution'] = (int) $propertyValue;
118. break;
119. default:
120. parent::__set( $propertyName, $propertyValue );
121. break;
122. }
123. }
124.
125. /**
126. * Property get access.
127. * Simply returns a given option.
128. *
129. * @param string $propertyName The name of the option to get.
130. * @return mixed The option value.
131. *
132. * @throws ezcBasePropertyNotFoundException
133. * If a the value for the property options is not an instance of
134. */
135. public function __get( $propertyName )
136. {
137. if ( array_key_exists( $propertyName, $this->properties ) )
138. {
139. return $this->properties[$propertyName];
140. }
141. return parent::__get( $propertyName );
142. }
143.
144. /**
145. * Build the polynom based on the given points.
146. *
147. * @return void
148. */
149. protected function buildPolynom()
150. {
151. $points = array();
152.
153. foreach ( $this->source as $key => $value )
154. {
155. if ( !is_numeric( $key ) )
156. {
157. throw new ezcGraphDatasetAverageInvalidKeysException();
158. }
159.
160. if ( ( $this->min === false ) || ( $this->min > $key ) )
161. {
162. $this->min = (float) $key;
163. }
164.
165. if ( ( $this->max === false ) || ( $this->max < $key ) )
166. {
167. $this->max = (float) $key;
168. }
169.
170. $points[] = new ezcGraphCoordinate( (float) $key, (float) $value );
171. }
172.
173. // Build transposed and normal Matrix out of coordiantes
174. $a = new ezcGraphMatrix( count( $points ), $this->polynomOrder + 1 );
175. $b = new ezcGraphMatrix( count( $points ), 1 );
176.
177. for ( $i = 0; $i <= $this->properties['polynomOrder']; ++$i )
178. {
179. foreach ( $points as $nr => $point )
180. {
181. $a->set( $nr, $i, pow( $point->x, $i ) );
182. $b->set( $nr, 0, $point->y );
183. }
184. }
185.
186. $at = clone $a;
187. $at->transpose();
188.
189. $left = $at->multiply( $a );
190. $right = $at->multiply( $b );
191.
192. $this->polynom = $left->solveNonlinearEquatation( $right );
193. }
194.
195. /**
196. * Returns a polynom of the defined order witch matches the datapoints
197. * using the least squares algorithm.
198. *
199. * @return ezcGraphPolynom Polynom
200. */
201. public function getPolynom()
202. {
203. if ( $this->polynom === false )
204. {
205. $this->buildPolynom();
206. }
207.
208. return $this->polynom;
209. }
210.
211. /**
212. * Get the x coordinate for the current position
213. *
214. * @param int $position Position
215. * @return float x coordinate
216. */
217. protected function getKey()
218. {
219. $polynom = $this->getPolynom();
220. return $this->min +
221. ( $this->max - $this->min ) / $this->resolution * $this->position;
222. }
223.
224. /**
225. * Returns true if the given datapoint exists
226. * Allows isset() using ArrayAccess.
227. *
228. * @param string $key The key of the datapoint to get.
229. * @return bool Wether the key exists.
230. */
231. public function offsetExists( $key )
232. {
233. $polynom = $this->getPolynom();
234. return ( ( $key >= $this->min ) && ( $key <= $this->max ) );
235. }
236.
237. /**
238. * Returns the value for the given datapoint
239. * Get an datapoint value by ArrayAccess.
240. *
241. * @param string $key The key of the datapoint to get.
242. * @return float The datapoint value.
243. */
244. public function offsetGet( $key )
245. {
246. $polynom = $this->getPolynom();
247. return $polynom->evaluate( $key );
248. }
249.
250. /**
251. * Throws a ezcBasePropertyPermissionException because single datapoints
252. * cannot be set in average datasets.
253. *
254. * @param string $key The kex of a datapoint to set.
255. * @param float $value The value for the datapoint.
256. * @throws ezcBasePropertyPermissionException
257. * Always, because access is readonly.
258. * @return void
259. */
260. public function offsetSet( $key, $value )
261. {
262. throw new ezcBasePropertyPermissionException( $key, ezcBasePropertyPermissionException::READ );
263. }
264.
265. /**
266. * Returns the currently selected datapoint.
267. *
268. * This method is part of the Iterator interface to allow access to the
269. * datapoints of this row by iterating over it like an array (e.g. using
270. * foreach).
271. *
272. * @return string The currently selected datapoint.
273. */
274. final public function current()
275. {
276. $polynom = $this->getPolynom();
277. return $polynom->evaluate( $this->getKey() );
278. }
279.
280. /**
281. * Returns the next datapoint and selects it or false on the last datapoint.
282. *
283. * This method is part of the Iterator interface to allow access to the
284. * datapoints of this row by iterating over it like an array (e.g. using
285. * foreach).
286. *
287. * @return float datapoint if it exists, or false.
288. */
289. final public function next()
290. {
291. if ( ++$this->position >= $this->resolution )
292. {
293. return false;
294. }
295. else
296. {
297. return $this->current();
298. }
299. }
300.
301. /**
302. * Returns the key of the currently selected datapoint.
303. *
304. * This method is part of the Iterator interface to allow access to the
305. * datapoints of this row by iterating over it like an array (e.g. using
306. * foreach).
307. *
308. * @return string The key of the currently selected datapoint.
309. */
310. final public function key()
311. {
312. return (string) $this->getKey();
313. }
314.
315. /**
316. * Returns if the current datapoint is valid.
317. *
318. * This method is part of the Iterator interface to allow access to the
319. * datapoints of this row by iterating over it like an array (e.g. using
320. * foreach).
321. *
322. * @return bool If the current datapoint is valid
323. */
324. final public function valid()
325. {
326. $polynom = $this->getPolynom();
327.
328. if ( $this->min >= $this->max )
329. {
330. return false;
331. }
332.
333. return ( ( $this->getKey() >= $this->min ) && ( $this->getKey() <= $this->max ) );
334. }
335.
336. /**
337. * Selects the very first datapoint and returns it.
338. * This method is part of the Iterator interface to allow access to the
339. * datapoints of this row by iterating over it like an array (e.g. using
340. * foreach).
341. *
342. * @return float The very first datapoint.
343. */
344. final public function rewind()
345. {
346. $this->position = 0;
347. }
348.
349. /**
350. * Returns the number of elements in this dataset
351. *
352. * @return int
353. */
354. public function count()
355. {
356. return $this->resolution;
357. }
358. }
359. ?>
Last updated: Mon, 21 Dec 2009