source: trunk/client/modules/Elezioni/grafici/jpgraph_utils.inc.php@ 233

Last change on this file since 233 was 2, checked in by root, 15 years ago

importo il progetto

File size: 15.5 KB
Line 
1<?php
2/*=======================================================================
3// File: JPGRAPH_UTILS.INC
4// Description: Collection of non-essential "nice to have" utilities
5// Created: 2005-11-20
6// Ver: $Id: jpgraph_utils.inc.php 1091 2009-01-18 22:57:40Z ljp $
7//
8// Copyright (c) Aditus Consulting. All rights reserved.
9//========================================================================
10*/
11
12//===================================================
13// CLASS FuncGenerator
14// Description: Utility class to help generate data for function plots.
15// The class supports both parametric and regular functions.
16//===================================================
17class FuncGenerator {
18 private $iFunc='',$iXFunc='',$iMin,$iMax,$iStepSize;
19
20 function FuncGenerator($aFunc,$aXFunc='') {
21 $this->iFunc = $aFunc;
22 $this->iXFunc = $aXFunc;
23 }
24
25 function E($aXMin,$aXMax,$aSteps=50) {
26 $this->iMin = $aXMin;
27 $this->iMax = $aXMax;
28 $this->iStepSize = ($aXMax-$aXMin)/$aSteps;
29
30 if( $this->iXFunc != '' )
31 $t = 'for($i='.$aXMin.'; $i<='.$aXMax.'; $i += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]='.$this->iXFunc.';}';
32 elseif( $this->iFunc != '' )
33 $t = 'for($x='.$aXMin.'; $x<='.$aXMax.'; $x += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]=$x;} $x='.$aXMax.';$ya[]='.$this->iFunc.';$xa[]=$x;';
34 else
35 JpGraphError::RaiseL(24001);//('FuncGenerator : No function specified. ');
36
37 @eval($t);
38
39 // If there is an error in the function specifcation this is the only
40 // way we can discover that.
41 if( empty($xa) || empty($ya) )
42 JpGraphError::RaiseL(24002);//('FuncGenerator : Syntax error in function specification ');
43
44 return array($xa,$ya);
45 }
46}
47
48//=============================================================================
49// CLASS SymChar
50// Description: Code values for some commonly used characters that
51// normally isn't available directly on the keyboard, for example
52// mathematical and greek symbols.
53//=============================================================================
54class SymChar {
55 static function Get($aSymb,$aCapital=FALSE) {
56 $iSymbols = array(
57 /* Greek */
58 array('alpha','03B1','0391'),
59 array('beta','03B2','0392'),
60 array('gamma','03B3','0393'),
61 array('delta','03B4','0394'),
62 array('epsilon','03B5','0395'),
63 array('zeta','03B6','0396'),
64 array('ny','03B7','0397'),
65 array('eta','03B8','0398'),
66 array('theta','03B8','0398'),
67 array('iota','03B9','0399'),
68 array('kappa','03BA','039A'),
69 array('lambda','03BB','039B'),
70 array('mu','03BC','039C'),
71 array('nu','03BD','039D'),
72 array('xi','03BE','039E'),
73 array('omicron','03BF','039F'),
74 array('pi','03C0','03A0'),
75 array('rho','03C1','03A1'),
76 array('sigma','03C3','03A3'),
77 array('tau','03C4','03A4'),
78 array('upsilon','03C5','03A5'),
79 array('phi','03C6','03A6'),
80 array('chi','03C7','03A7'),
81 array('psi','03C8','03A8'),
82 array('omega','03C9','03A9'),
83 /* Money */
84 array('euro','20AC'),
85 array('yen','00A5'),
86 array('pound','20A4'),
87 /* Math */
88 array('approx','2248'),
89 array('neq','2260'),
90 array('not','2310'),
91 array('def','2261'),
92 array('inf','221E'),
93 array('sqrt','221A'),
94 array('int','222B'),
95 /* Misc */
96 array('copy','00A9'),
97 array('para','00A7'),
98 array('tm','2122'), /* Trademark symbol */
99 array('rtm','00AE') /* Registered trademark */
100
101);
102
103 $n = count($iSymbols);
104 $i=0;
105 $found = false;
106 $aSymb = strtolower($aSymb);
107 while( $i < $n && !$found ) {
108 $found = $aSymb === $iSymbols[$i++][0];
109 }
110 if( $found ) {
111 $ca = $iSymbols[--$i];
112 if( $aCapital && count($ca)==3 )
113 $s = $ca[2];
114 else
115 $s = $ca[1];
116 return sprintf('&#%04d;',hexdec($s));
117 }
118 else
119 return '';
120 }
121}
122
123
124//=============================================================================
125// CLASS DateScaleUtils
126// Description: Help to create a manual date scale
127//=============================================================================
128define('DSUTILS_MONTH',1); // Major and minor ticks on a monthly basis
129define('DSUTILS_MONTH1',1); // Major and minor ticks on a monthly basis
130define('DSUTILS_MONTH2',2); // Major ticks on a bi-monthly basis
131define('DSUTILS_MONTH3',3); // Major icks on a tri-monthly basis
132define('DSUTILS_MONTH6',4); // Major on a six-monthly basis
133define('DSUTILS_WEEK1',5); // Major ticks on a weekly basis
134define('DSUTILS_WEEK2',6); // Major ticks on a bi-weekly basis
135define('DSUTILS_WEEK4',7); // Major ticks on a quod-weekly basis
136define('DSUTILS_DAY1',8); // Major ticks on a daily basis
137define('DSUTILS_DAY2',9); // Major ticks on a bi-daily basis
138define('DSUTILS_DAY4',10); // Major ticks on a qoud-daily basis
139define('DSUTILS_YEAR1',11); // Major ticks on a yearly basis
140define('DSUTILS_YEAR2',12); // Major ticks on a bi-yearly basis
141define('DSUTILS_YEAR5',13); // Major ticks on a five-yearly basis
142
143
144class DateScaleUtils {
145 public static $iMin=0, $iMax=0;
146
147 private static $starthour,$startmonth, $startday, $startyear;
148 private static $endmonth, $endyear, $endday;
149 private static $tickPositions=array(),$minTickPositions=array();
150 private static $iUseWeeks = true;
151
152 static function UseWeekFormat($aFlg) {
153 self::$iUseWeeks = $aFlg;
154 }
155
156 static function doYearly($aType,$aMinor=false) {
157 $i=0; $j=0;
158 $m = self::$startmonth;
159 $y = self::$startyear;
160
161 if( self::$startday == 1 ) {
162 self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
163 }
164 ++$m;
165
166
167 switch( $aType ) {
168 case DSUTILS_YEAR1:
169 for($y=self::$startyear; $y <= self::$endyear; ++$y ) {
170 if( $aMinor ) {
171 while( $m <= 12 ) {
172 if( !($y == self::$endyear && $m > self::$endmonth) ) {
173 self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
174 }
175 ++$m;
176 }
177 $m=1;
178 }
179 self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);
180 }
181 break;
182 case DSUTILS_YEAR2:
183 $y=self::$startyear;
184 while( $y <= self::$endyear ) {
185 self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);
186 for($k=0; $k < 1; ++$k ) {
187 ++$y;
188 if( $aMinor ) {
189 self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y);
190 }
191 }
192 ++$y;
193 }
194 break;
195 case DSUTILS_YEAR5:
196 $y=self::$startyear;
197 while( $y <= self::$endyear ) {
198 self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);
199 for($k=0; $k < 4; ++$k ) {
200 ++$y;
201 if( $aMinor ) {
202 self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y);
203 }
204 }
205 ++$y;
206 }
207 break;
208 }
209 }
210
211 static function doDaily($aType,$aMinor=false) {
212 $m = self::$startmonth;
213 $y = self::$startyear;
214 $d = self::$startday;
215 $h = self::$starthour;
216 $i=0;$j=0;
217
218 if( $h == 0 ) {
219 self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y);
220 }
221 $t = mktime(0,0,0,$m,$d,$y);
222
223 switch($aType) {
224 case DSUTILS_DAY1:
225 while( $t <= self::$iMax ) {
226 $t = strtotime('+1 day',$t);
227 self::$tickPositions[$i++] = $t;
228 if( $aMinor ) {
229 self::$minTickPositions[$j++] = strtotime('+12 hours',$t);
230 }
231 }
232 break;
233 case DSUTILS_DAY2:
234 while( $t <= self::$iMax ) {
235 $t = strtotime('+1 day',$t);
236 if( $aMinor ) {
237 self::$minTickPositions[$j++] = $t;
238 }
239 $t = strtotime('+1 day',$t);
240 self::$tickPositions[$i++] = $t;
241 }
242 break;
243 case DSUTILS_DAY4:
244 while( $t <= self::$iMax ) {
245 for($k=0; $k < 3; ++$k ) {
246 $t = strtotime('+1 day',$t);
247 if( $aMinor ) {
248 self::$minTickPositions[$j++] = $t;
249 }
250 }
251 $t = strtotime('+1 day',$t);
252 self::$tickPositions[$i++] = $t;
253 }
254 break;
255 }
256 }
257
258 static function doWeekly($aType,$aMinor=false) {
259 $hpd = 3600*24;
260 $hpw = 3600*24*7;
261 // Find out week number of min date
262 $thursday = self::$iMin + $hpd * (3 - (date('w', self::$iMin) + 6) % 7);
263 $week = 1 + (date('z', $thursday) - (11 - date('w', mktime(0, 0, 0, 1, 1, date('Y', $thursday)))) % 7) / 7;
264 $daynumber = date('w',self::$iMin);
265 if( $daynumber == 0 ) $daynumber = 7;
266 $m = self::$startmonth;
267 $y = self::$startyear;
268 $d = self::$startday;
269 $i=0;$j=0;
270 // The assumption is that the weeks start on Monday. If the first day
271 // is later in the week then the first week tick has to be on the following
272 // week.
273 if( $daynumber == 1 ) {
274 self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y);
275 $t = mktime(0,0,0,$m,$d,$y) + $hpw;
276 }
277 else {
278 $t = mktime(0,0,0,$m,$d,$y) + $hpd*(8-$daynumber);
279 }
280
281 switch($aType) {
282 case DSUTILS_WEEK1:
283 $cnt=0;
284 break;
285 case DSUTILS_WEEK2:
286 $cnt=1;
287 break;
288 case DSUTILS_WEEK4:
289 $cnt=3;
290 break;
291 }
292 while( $t <= self::$iMax ) {
293 self::$tickPositions[$i++] = $t;
294 for($k=0; $k < $cnt; ++$k ) {
295 $t += $hpw;
296 if( $aMinor ) {
297 self::$minTickPositions[$j++] = $t;
298 }
299 }
300 $t += $hpw;
301 }
302 }
303
304 static function doMonthly($aType,$aMinor=false) {
305 $monthcount=0;
306 $m = self::$startmonth;
307 $y = self::$startyear;
308 $i=0; $j=0;
309
310 // Skip the first month label if it is before the startdate
311 if( self::$startday == 1 ) {
312 self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
313 $monthcount=1;
314 }
315 if( $aType == 1 ) {
316 if( self::$startday < 15 ) {
317 self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y);
318 }
319 }
320 ++$m;
321
322 // Loop through all the years included in the scale
323 for($y=self::$startyear; $y <= self::$endyear; ++$y ) {
324 // Loop through all the months. There are three cases to consider:
325 // 1. We are in the first year and must start with the startmonth
326 // 2. We are in the end year and we must stop at last month of the scale
327 // 3. A year in between where we run through all the 12 months
328 $stopmonth = $y == self::$endyear ? self::$endmonth : 12;
329 while( $m <= $stopmonth ) {
330 switch( $aType ) {
331 case DSUTILS_MONTH1:
332 // Set minor tick at the middle of the month
333 if( $aMinor ) {
334 if( $m <= $stopmonth ) {
335 if( !($y==self::$endyear && $m==$stopmonth && self::$endday < 15) )
336 self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y);
337 }
338 }
339 // Major at month
340 // Get timestamp of first hour of first day in each month
341 self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
342
343 break;
344 case DSUTILS_MONTH2:
345 if( $aMinor ) {
346 // Set minor tick at start of each month
347 self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
348 }
349
350 // Major at every second month
351 // Get timestamp of first hour of first day in each month
352 if( $monthcount % 2 == 0 ) {
353 self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
354 }
355 break;
356 case DSUTILS_MONTH3:
357 if( $aMinor ) {
358 // Set minor tick at start of each month
359 self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
360 }
361 // Major at every third month
362 // Get timestamp of first hour of first day in each month
363 if( $monthcount % 3 == 0 ) {
364 self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
365 }
366 break;
367 case DSUTILS_MONTH6:
368 if( $aMinor ) {
369 // Set minor tick at start of each month
370 self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
371 }
372 // Major at every third month
373 // Get timestamp of first hour of first day in each month
374 if( $monthcount % 6 == 0 ) {
375 self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
376 }
377 break;
378 }
379 ++$m;
380 ++$monthcount;
381 }
382 $m=1;
383 }
384
385 // For the case where all dates are within the same month
386 // we want to make sure we have at least two ticks on the scale
387 // since the scale want work properly otherwise
388 if(self::$startmonth == self::$endmonth && self::$startyear == self::$endyear && $aType==1 ) {
389 self::$tickPositions[$i++] = mktime(0 ,0 ,0, self::$startmonth + 1, 1, self::$startyear);
390 }
391
392 return array(self::$tickPositions,self::$minTickPositions);
393 }
394
395 static function GetTicks($aData,$aType=1,$aMinor=false,$aEndPoints=false) {
396 $n = count($aData);
397 return self::GetTicksFromMinMax($aData[0],$aData[$n-1],$aType,$aMinor,$aEndPoints);
398 }
399
400 static function GetAutoTicks($aMin,$aMax,$aMaxTicks=10,$aMinor=false) {
401 $diff = $aMax - $aMin;
402 $spd = 3600*24;
403 $spw = $spd*7;
404 $spm = $spd*30;
405 $spy = $spd*352;
406
407 if( self::$iUseWeeks )
408 $w = 'W';
409 else
410 $w = 'd M';
411
412 // Decision table for suitable scales
413 // First value: Main decision point
414 // Second value: Array of formatting depending on divisor for wanted max number of ticks. <divisor><formatting><format-string>,..
415 $tt = array(
416 array($spw, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',-1,DSUTILS_DAY4,'d M')),
417 array($spm, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',4,DSUTILS_DAY4,'d M',
418 7,DSUTILS_WEEK1,$w,-1,DSUTILS_WEEK2,$w)),
419 array($spy, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',4,DSUTILS_DAY4,'d M',
420 7,DSUTILS_WEEK1,$w,14,DSUTILS_WEEK2,$w,
421 30,DSUTILS_MONTH1,'M',60,DSUTILS_MONTH2,'M',-1,DSUTILS_MONTH3,'M')),
422 array(-1, array(30,DSUTILS_MONTH1,'M-Y',60,DSUTILS_MONTH2,'M-Y',90,DSUTILS_MONTH3,'M-Y',
423 180,DSUTILS_MONTH6,'M-Y',352,DSUTILS_YEAR1,'Y',704,DSUTILS_YEAR2,'Y',-1,DSUTILS_YEAR5,'Y')));
424
425 $ntt = count($tt);
426 $nd = floor($diff/$spd);
427 for($i=0; $i < $ntt; ++$i ) {
428 if( $diff <= $tt[$i][0] || $i==$ntt-1) {
429 $t = $tt[$i][1];
430 $n = count($t)/3;
431 for( $j=0; $j < $n; ++$j ) {
432 if( $nd/$t[3*$j] <= $aMaxTicks || $j==$n-1) {
433 $type = $t[3*$j+1];
434 $fs = $t[3*$j+2];
435 list($tickPositions,$minTickPositions) = self::GetTicksFromMinMax($aMin,$aMax,$type,$aMinor);
436 return array($fs,$tickPositions,$minTickPositions,$type);
437 }
438 }
439 }
440 }
441 }
442
443 static function GetTicksFromMinMax($aMin,$aMax,$aType,$aMinor=false,$aEndPoints=false) {
444 self::$starthour = date('G',$aMin);
445 self::$startmonth = date('n',$aMin);
446 self::$startday = date('j',$aMin);
447 self::$startyear = date('Y',$aMin);
448 self::$endmonth = date('n',$aMax);
449 self::$endyear = date('Y',$aMax);
450 self::$endday = date('j',$aMax);
451 self::$iMin = $aMin;
452 self::$iMax = $aMax;
453
454 if( $aType <= DSUTILS_MONTH6 ) {
455 self::doMonthly($aType,$aMinor);
456 }
457 elseif( $aType <= DSUTILS_WEEK4 ) {
458 self::doWeekly($aType,$aMinor);
459 }
460 elseif( $aType <= DSUTILS_DAY4 ) {
461 self::doDaily($aType,$aMinor);
462 }
463 elseif( $aType <= DSUTILS_YEAR5 ) {
464 self::doYearly($aType,$aMinor);
465 }
466 else {
467 JpGraphError::RaiseL(24003);
468 }
469 // put a label at the very left data pos
470 if( $aEndPoints ) {
471 $tickPositions[$i++] = $aData[0];
472 }
473
474 // put a label at the very right data pos
475 if( $aEndPoints ) {
476 $tickPositions[$i] = $aData[$n-1];
477 }
478
479 return array(self::$tickPositions,self::$minTickPositions);
480 }
481
482}
483
484//=============================================================================
485// Class ReadFileData
486//=============================================================================
487Class ReadFileData {
488
489 //----------------------------------------------------------------------------
490 // Desciption:
491 // Read numeric data from a file.
492 // Each value should be separated by either a new line or by a specified
493 // separator character (default is ',').
494 // Before returning the data each value is converted to a proper float
495 // value. The routine is robust in the sense that non numeric data in the
496 // file will be discarded.
497 //
498 // Returns:
499 // The number of data values read on success, FALSE on failure
500 //----------------------------------------------------------------------------
501 static function FromCSV($aFile,&$aData,$aSepChar=',',$aMaxLineLength=1024) {
502 $rh = fopen($aFile,'r');
503 if( $rh === false )
504 return false;
505 $tmp = array();
506 $lineofdata = fgetcsv($rh, 1000, ',');
507 while ( $lineofdata !== FALSE) {
508 $tmp = array_merge($tmp,$lineofdata);
509 $lineofdata = fgetcsv($rh, $aMaxLineLength, $aSepChar);
510 }
511 fclose($rh);
512
513 // Now make sure that all data is numeric. By default
514 // all data is read as strings
515 $n = count($tmp);
516 $aData = array();
517 $cnt=0;
518 for($i=0; $i < $n; ++$i) {
519 if( $tmp[$i] !== "" ) {
520 $aData[$cnt++] = floatval($tmp[$i]);
521 }
522 }
523 return $cnt;
524 }
525}
526
527?>
Note: See TracBrowser for help on using the repository browser.