[ Index ] |
|
Code source de jpGraph 2.2 |
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 781 2006-10-08 08:07:47Z 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 //=================================================== 17 class 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 //============================================================================= 54 class 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 99 $n = count($iSymbols); 100 $i=0; 101 $found = false; 102 $aSymb = strtolower($aSymb); 103 while( $i < $n && !$found ) { 104 $found = $aSymb === $iSymbols[$i++][0]; 105 } 106 if( $found ) { 107 $ca = $iSymbols[--$i]; 108 if( $aCapital && count($ca)==3 ) 109 $s = $ca[2]; 110 else 111 $s = $ca[1]; 112 return sprintf('&#%04d;',hexdec($s)); 113 } 114 else 115 return ''; 116 } 117 } 118 119 120 //============================================================================= 121 // CLASS DateScaleUtils 122 // Description: Help to create a manual date scale 123 //============================================================================= 124 DEFINE('DSUTILS_MONTH',1); // Major and minor ticks on a monthly basis 125 DEFINE('DSUTILS_MONTH1',1); // Major and minor ticks on a monthly basis 126 DEFINE('DSUTILS_MONTH2',2); // Major ticks on a bi-monthly basis 127 DEFINE('DSUTILS_MONTH3',3); // Major icks on a tri-monthly basis 128 DEFINE('DSUTILS_MONTH6',4); // Major on a six-monthly basis 129 DEFINE('DSUTILS_WEEK1',5); // Major ticks on a weekly basis 130 DEFINE('DSUTILS_WEEK2',6); // Major ticks on a bi-weekly basis 131 DEFINE('DSUTILS_WEEK4',7); // Major ticks on a quod-weekly basis 132 DEFINE('DSUTILS_DAY1',8); // Major ticks on a daily basis 133 DEFINE('DSUTILS_DAY2',9); // Major ticks on a bi-daily basis 134 DEFINE('DSUTILS_DAY4',10); // Major ticks on a qoud-daily basis 135 DEFINE('DSUTILS_YEAR1',11); // Major ticks on a yearly basis 136 DEFINE('DSUTILS_YEAR2',12); // Major ticks on a bi-yearly basis 137 DEFINE('DSUTILS_YEAR5',13); // Major ticks on a five-yearly basis 138 139 140 class DateScaleUtils { 141 private $starthour,$startmonth, $startday, $startyear; 142 private $endmonth, $endyear, $endday; 143 private $tickPositions=array(),$minTickPositions=array(); 144 private $iUseWeeks = true; 145 146 function UseWeekFormat($aFlg) { 147 $this->iUseWeeks = $aFlg; 148 } 149 150 function doYearly($aType,$aMinor=false) { 151 $i=0; $j=0; 152 $m = $this->startmonth; 153 $y = $this->startyear; 154 155 if( $this->startday == 1 ) { 156 $this->tickPositions[$i++] = mktime(0,0,0,$m,1,$y); 157 } 158 ++$m; 159 160 161 switch( $aType ) { 162 case DSUTILS_YEAR1: 163 for($y=$this->startyear; $y <= $this->endyear; ++$y ) { 164 if( $aMinor ) { 165 while( $m <= 12 ) { 166 if( !($y == $this->endyear && $m > $this->endmonth) ) { 167 $this->minTickPositions[$j++] = mktime(0,0,0,$m,1,$y); 168 } 169 ++$m; 170 } 171 $m=1; 172 } 173 $this->tickPositions[$i++] = mktime(0,0,0,1,1,$y); 174 } 175 break; 176 case DSUTILS_YEAR2: 177 $y=$this->startyear; 178 while( $y <= $this->endyear ) { 179 $this->tickPositions[$i++] = mktime(0,0,0,1,1,$y); 180 for($k=0; $k < 1; ++$k ) { 181 ++$y; 182 if( $aMinor ) { 183 $this->minTickPositions[$j++] = mktime(0,0,0,1,1,$y); 184 } 185 } 186 ++$y; 187 } 188 break; 189 case DSUTILS_YEAR5: 190 $y=$this->startyear; 191 while( $y <= $this->endyear ) { 192 $this->tickPositions[$i++] = mktime(0,0,0,1,1,$y); 193 for($k=0; $k < 4; ++$k ) { 194 ++$y; 195 if( $aMinor ) { 196 $this->minTickPositions[$j++] = mktime(0,0,0,1,1,$y); 197 } 198 } 199 ++$y; 200 } 201 break; 202 } 203 } 204 205 function doDaily($aType,$aMinor=false) { 206 $m = $this->startmonth; 207 $y = $this->startyear; 208 $d = $this->startday; 209 $h = $this->starthour; 210 $i=0;$j=0; 211 212 if( $h == 0 ) { 213 $this->tickPositions[$i++] = mktime(0,0,0,$m,$d,$y); 214 $t = mktime(0,0,0,$m,$d,$y); 215 } 216 else { 217 $t = mktime(0,0,0,$m,$d,$y); 218 } 219 switch($aType) { 220 case DSUTILS_DAY1: 221 while( $t <= $this->iMax ) { 222 $t += 3600*24; 223 $this->tickPositions[$i++] = $t; 224 } 225 break; 226 case DSUTILS_DAY2: 227 while( $t <= $this->iMax ) { 228 $t += 3600*24; 229 if( $aMinor ) { 230 $this->minTickPositions[$j++] = $t; 231 } 232 $t += 3600*24; 233 $this->tickPositions[$i++] = $t; 234 } 235 break; 236 case DSUTILS_DAY4: 237 while( $t <= $this->iMax ) { 238 for($k=0; $k < 3; ++$k ) { 239 $t += 3600*24; 240 if( $aMinor ) { 241 $this->minTickPositions[$j++] = $t; 242 } 243 } 244 $t += 3600*24; 245 $this->tickPositions[$i++] = $t; 246 } 247 break; 248 } 249 } 250 251 function doWeekly($aType,$aMinor=false) { 252 $hpd = 3600*24; 253 $hpw = 3600*24*7; 254 // Find out week number of min date 255 $thursday = $this->iMin + $hpd * (3 - (date('w', $this->iMin) + 6) % 7); 256 $week = 1 + (date('z', $thursday) - (11 - date('w', mktime(0, 0, 0, 1, 1, date('Y', $thursday)))) % 7) / 7; 257 $daynumber = date('w',$this->iMin); 258 if( $daynumber == 0 ) $daynumber = 7; 259 $m = $this->startmonth; 260 $y = $this->startyear; 261 $d = $this->startday; 262 $i=0;$j=0; 263 // The assumption is that the weeks start on Monday. If the first day 264 // is later in the week then the first week tick has to be on the following 265 // week. 266 if( $daynumber == 1 ) { 267 $this->tickPositions[$i++] = mktime(0,0,0,$m,$d,$y); 268 $t = mktime(0,0,0,$m,$d,$y) + $hpw; 269 } 270 else { 271 $t = mktime(0,0,0,$m,$d,$y) + $hpd*(8-$daynumber); 272 } 273 274 switch($aType) { 275 case DSUTILS_WEEK1: 276 $cnt=0; 277 break; 278 case DSUTILS_WEEK2: 279 $cnt=1; 280 break; 281 case DSUTILS_WEEK4: 282 $cnt=3; 283 break; 284 } 285 while( $t <= $this->iMax ) { 286 $this->tickPositions[$i++] = $t; 287 for($k=0; $k < $cnt; ++$k ) { 288 $t += $hpw; 289 if( $aMinor ) { 290 $this->minTickPositions[$j++] = $t; 291 } 292 } 293 $t += $hpw; 294 } 295 } 296 297 function doMonthly($aType,$aMinor=false) { 298 $monthcount=0; 299 $m = $this->startmonth; 300 $y = $this->startyear; 301 $i=0; $j=0; 302 303 // Skip the first month label if it is before the startdate 304 if( $this->startday == 1 ) { 305 $this->tickPositions[$i++] = mktime(0,0,0,$m,1,$y); 306 $monthcount=1; 307 } 308 if( $aType == 1 ) { 309 if( $this->startday < 15 ) { 310 $this->minTickPositions[$j++] = mktime(0,0,0,$m,15,$y); 311 } 312 } 313 ++$m; 314 315 // Loop through all the years included in the scale 316 for($y=$this->startyear; $y <= $this->endyear; ++$y ) { 317 // Loop through all the months. There are three cases to consider: 318 // 1. We are in the first year and must start with the startmonth 319 // 2. We are in the end year and we must stop at last month of the scale 320 // 3. A year in between where we run through all the 12 months 321 $stopmonth = $y == $this->endyear ? $this->endmonth : 12; 322 while( $m <= $stopmonth ) { 323 switch( $aType ) { 324 case DSUTILS_MONTH1: 325 // Set minor tick at the middle of the month 326 if( $aMinor ) { 327 if( $m <= $stopmonth ) { 328 if( !($y==$this->endyear && $m==$stopmonth && $this->endday < 15) ) 329 $this->minTickPositions[$j++] = mktime(0,0,0,$m,15,$y); 330 } 331 } 332 // Major at month 333 // Get timestamp of first hour of first day in each month 334 $this->tickPositions[$i++] = mktime(0,0,0,$m,1,$y); 335 336 break; 337 case DSUTILS_MONTH2: 338 if( $aMinor ) { 339 // Set minor tick at start of each month 340 $this->minTickPositions[$j++] = mktime(0,0,0,$m,1,$y); 341 } 342 343 // Major at every second month 344 // Get timestamp of first hour of first day in each month 345 if( $monthcount % 2 == 0 ) { 346 $this->tickPositions[$i++] = mktime(0,0,0,$m,1,$y); 347 } 348 break; 349 case DSUTILS_MONTH3: 350 if( $aMinor ) { 351 // Set minor tick at start of each month 352 $this->minTickPositions[$j++] = mktime(0,0,0,$m,1,$y); 353 } 354 // Major at every third month 355 // Get timestamp of first hour of first day in each month 356 if( $monthcount % 3 == 0 ) { 357 $this->tickPositions[$i++] = mktime(0,0,0,$m,1,$y); 358 } 359 break; 360 case DSUTILS_MONTH6: 361 if( $aMinor ) { 362 // Set minor tick at start of each month 363 $this->minTickPositions[$j++] = mktime(0,0,0,$m,1,$y); 364 } 365 // Major at every third month 366 // Get timestamp of first hour of first day in each month 367 if( $monthcount % 6 == 0 ) { 368 $this->tickPositions[$i++] = mktime(0,0,0,$m,1,$y); 369 } 370 break; 371 } 372 ++$m; 373 ++$monthcount; 374 } 375 $m=1; 376 } 377 378 // For the case where all dates are within the same month 379 // we want to make sure we have at least two ticks on the scale 380 // since the scale want work properly otherwise 381 if($this->startmonth == $this->endmonth && $this->startyear == $this->endyear && $aType==1 ) { 382 $this->tickPositions[$i++] = mktime(0 ,0 ,0, $this->startmonth + 1, 1, $this->startyear); 383 } 384 385 return array($this->tickPositions,$this->minTickPositions); 386 } 387 388 function GetTicks($aData,$aType=1,$aMinor=false,$aEndPoints=false) { 389 $n = count($aData); 390 return $this->GetTicksFromMinMax($aData[0],$aData[$n-1],$aType,$aMinor,$aEndPoints); 391 } 392 393 function GetAutoTicks($aMin,$aMax,$aMaxTicks=10,$aMinor=false) { 394 $diff = $aMax - $aMin; 395 $spd = 3600*24; 396 $spw = $spd*7; 397 $spm = $spd*30; 398 $spy = $spd*352; 399 400 if( $this->iUseWeeks ) 401 $w = 'W'; 402 else 403 $w = 'd M'; 404 405 // Decision table for suitable scales 406 // First value: Main decision point 407 // Second value: Array of formatting depending on divisor for wanted max number of ticks. <divisor><formatting><format-string>,.. 408 $tt = array( 409 array($spw, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',-1,DSUTILS_DAY4,'d M')), 410 array($spm, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',4,DSUTILS_DAY4,'d M', 411 7,DSUTILS_WEEK1,$w,-1,DSUTILS_WEEK2,$w)), 412 array($spy, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',4,DSUTILS_DAY4,'d M', 413 7,DSUTILS_WEEK1,$w,14,DSUTILS_WEEK2,$w, 414 30,DSUTILS_MONTH1,'M',60,DSUTILS_MONTH2,'M',-1,DSUTILS_MONTH3,'M')), 415 array(-1, array(30,DSUTILS_MONTH1,'M-Y',60,DSUTILS_MONTH2,'M-Y',90,DSUTILS_MONTH3,'M-Y', 416 180,DSUTILS_MONTH6,'M-Y',352,DSUTILS_YEAR1,'Y',704,DSUTILS_YEAR2,'Y',-1,DSUTILS_YEAR5,'Y'))); 417 418 $ntt = count($tt); 419 $nd = floor($diff/$spd); 420 for($i=0; $i < $ntt; ++$i ) { 421 if( $diff <= $tt[$i][0] || $i==$ntt-1) { 422 $t = $tt[$i][1]; 423 $n = count($t)/3; 424 for( $j=0; $j < $n; ++$j ) { 425 if( $nd/$t[3*$j] <= $aMaxTicks || $j==$n-1) { 426 $type = $t[3*$j+1]; 427 $fs = $t[3*$j+2]; 428 list($tickPositions,$minTickPositions) = $this->GetTicksFromMinMax($aMin,$aMax,$type,$aMinor); 429 return array($fs,$tickPositions,$minTickPositions,$type); 430 } 431 } 432 } 433 } 434 } 435 436 function GetTicksFromMinMax($aMin,$aMax,$aType,$aMinor=false,$aEndPoints=false) { 437 $this->starthour = date('G',$aMin); 438 $this->startmonth = date('n',$aMin); 439 $this->startday = date('j',$aMin); 440 $this->startyear = date('Y',$aMin); 441 $this->endmonth = date('n',$aMax); 442 $this->endyear = date('Y',$aMax); 443 $this->endday = date('j',$aMax); 444 $this->iMin = $aMin; 445 $this->iMax = $aMax; 446 447 if( $aType <= DSUTILS_MONTH6 ) { 448 $this->doMonthly($aType,$aMinor); 449 } 450 elseif( $aType <= DSUTILS_WEEK4 ) { 451 $this->doWeekly($aType,$aMinor); 452 } 453 elseif( $aType <= DSUTILS_DAY4 ) { 454 $this->doDaily($aType,$aMinor); 455 } 456 elseif( $aType <= DSUTILS_YEAR5 ) { 457 $this->doYearly($aType,$aMinor); 458 } 459 else { 460 JpGraphError::RaiseL(24003); 461 } 462 // put a label at the very left data pos 463 if( $aEndPoints ) { 464 $tickPositions[$i++] = $aData[0]; 465 } 466 467 // put a label at the very right data pos 468 if( $aEndPoints ) { 469 $tickPositions[$i] = $aData[$n-1]; 470 } 471 472 return array($this->tickPositions,$this->minTickPositions); 473 } 474 475 } 476 477 //============================================================================= 478 // Class ReadFileData 479 //============================================================================= 480 Class ReadFileData { 481 482 //---------------------------------------------------------------------------- 483 // Desciption: 484 // Read numeric data from a file. 485 // Each value should be separated by either a new line or by a specified 486 // separator character (default is ','). 487 // Before returning the data each value is converted to a proper float 488 // value. The routine is robust in the sense that non numeric data in the 489 // file will be discarded. 490 // 491 // Returns: 492 // The number of data values read on success, FALSE on failure 493 //---------------------------------------------------------------------------- 494 static function FromCSV($aFile,&$aData,$aSepChar=',',$aMaxLineLength=1024) { 495 $rh = fopen($aFile,'r'); 496 if( $rh === false ) 497 return false; 498 $tmp = array(); 499 $lineofdata = fgetcsv($rh, 1000, ','); 500 while ( $lineofdata !== FALSE) { 501 $tmp = array_merge($tmp,$lineofdata); 502 $lineofdata = fgetcsv($rh, $aMaxLineLength, $aSepChar); 503 } 504 fclose($rh); 505 506 // Now make sure that all data is numeric. By default 507 // all data is read as strings 508 $n = count($tmp); 509 $aData = array(); 510 $cnt=0; 511 for($i=0; $i < $n; ++$i) { 512 if( $tmp[$i] !== "" ) { 513 $aData[$cnt++] = floatval($tmp[$i]); 514 } 515 } 516 return $cnt; 517 } 518 } 519 520 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sat Nov 24 09:27:55 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |