Ignore:
Timestamp:
Apr 13, 2019, 8:05:15 PM (6 years ago)
Author:
roby
Message:
 
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/client/modules/Elezioni/grafici/jpgraph_utils.inc.php

    r2 r265  
    11<?php
    22/*=======================================================================
    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 */
     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 1777 2009-08-23 17:34:36Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. All rights reserved.
     9 //========================================================================
     10 */
    1111
    1212//===================================================
    1313// CLASS FuncGenerator
    14 // Description: Utility class to help generate data for function plots. 
     14// Description: Utility class to help generate data for function plots.
    1515// The class supports both parametric and regular functions.
    1616//===================================================
    1717class FuncGenerator {
    1818    private $iFunc='',$iXFunc='',$iMin,$iMax,$iStepSize;
    19        
    20     function FuncGenerator($aFunc,$aXFunc='') {
    21         $this->iFunc = $aFunc;
    22         $this->iXFunc = $aXFunc;
    23     }
    24        
     19
     20    function __construct($aFunc,$aXFunc='') {
     21        $this->iFunc = $aFunc;
     22        $this->iXFunc = $aXFunc;
     23    }
     24
    2525    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         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 '';
     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);
    12045    }
    12146}
     
    15176
    15277    static function UseWeekFormat($aFlg) {
    153         self::$iUseWeeks = $aFlg;
     78        self::$iUseWeeks = $aFlg;
    15479    }
    15580
    15681    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         }
     82        $i=0; $j=0;
     83        $m = self::$startmonth;
     84        $y = self::$startyear;
     85
     86        if( self::$startday == 1 ) {
     87            self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
     88        }
     89        ++$m;
     90
     91
     92        switch( $aType ) {
     93            case DSUTILS_YEAR1:
     94                for($y=self::$startyear; $y <= self::$endyear; ++$y ) {
     95                    if( $aMinor ) {
     96                        while( $m <= 12 ) {
     97                            if( !($y == self::$endyear && $m > self::$endmonth) ) {
     98                                self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
     99                            }
     100                            ++$m;
     101                        }
     102                        $m=1;
     103                    }
     104                    self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);
     105                }
     106                break;
     107            case DSUTILS_YEAR2:
     108                $y=self::$startyear;
     109                while( $y <= self::$endyear ) {
     110                    self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);
     111                    for($k=0; $k < 1; ++$k ) {
     112                        ++$y;
     113                        if( $aMinor ) {
     114                            self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y);
     115                        }
     116                    }
     117                    ++$y;
     118                }
     119                break;
     120            case DSUTILS_YEAR5:
     121                $y=self::$startyear;
     122                while( $y <= self::$endyear ) {
     123                    self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);
     124                    for($k=0; $k < 4; ++$k ) {
     125                        ++$y;
     126                        if( $aMinor ) {
     127                            self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y);
     128                        }
     129                    }
     130                    ++$y;
     131                }
     132                break;
     133        }
    209134    }
    210135
    211136    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         }
     137        $m = self::$startmonth;
     138        $y = self::$startyear;
     139        $d = self::$startday;
     140        $h = self::$starthour;
     141        $i=0;$j=0;
     142
     143        if( $h == 0 ) {
     144            self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y);
     145        }
     146        $t = mktime(0,0,0,$m,$d,$y);
     147
     148        switch($aType) {
     149            case DSUTILS_DAY1:
     150                while( $t <= self::$iMax ) {
     151                    $t = strtotime('+1 day',$t);
     152                    self::$tickPositions[$i++] = $t;
     153                    if( $aMinor ) {
     154                        self::$minTickPositions[$j++] = strtotime('+12 hours',$t);
     155                    }
     156                }
     157                break;
     158            case DSUTILS_DAY2:
     159                while( $t <= self::$iMax ) {
     160                    $t = strtotime('+1 day',$t);
     161                    if( $aMinor ) {
     162                        self::$minTickPositions[$j++] = $t;
     163                    }
     164                    $t = strtotime('+1 day',$t);
     165                    self::$tickPositions[$i++] = $t;
     166                }
     167                break;
     168            case DSUTILS_DAY4:
     169                while( $t <= self::$iMax ) {
     170                    for($k=0; $k < 3; ++$k ) {
     171                        $t = strtotime('+1 day',$t);
     172                        if( $aMinor ) {
     173                            self::$minTickPositions[$j++] = $t;
     174                        }
     175                    }
     176                    $t = strtotime('+1 day',$t);
     177                    self::$tickPositions[$i++] = $t;
     178                }
     179                break;
     180        }
    256181    }
    257182
    258183    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         }
     184        $hpd = 3600*24;
     185        $hpw = 3600*24*7;
     186        // Find out week number of min date
     187        $thursday = self::$iMin + $hpd * (3 - (date('w', self::$iMin) + 6) % 7);
     188        $week = 1 + (date('z', $thursday) - (11 - date('w', mktime(0, 0, 0, 1, 1, date('Y', $thursday)))) % 7) / 7;
     189        $daynumber = date('w',self::$iMin);
     190        if( $daynumber == 0 ) $daynumber = 7;
     191        $m = self::$startmonth;
     192        $y = self::$startyear;
     193        $d = self::$startday;
     194        $i=0;$j=0;
     195        // The assumption is that the weeks start on Monday. If the first day
     196        // is later in the week then the first week tick has to be on the following
     197        // week.
     198        if( $daynumber == 1 ) {
     199            self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y);
     200            $t = mktime(0,0,0,$m,$d,$y) + $hpw;
     201        }
     202        else {
     203            $t = mktime(0,0,0,$m,$d,$y) + $hpd*(8-$daynumber);
     204        }
     205
     206        switch($aType) {
     207            case DSUTILS_WEEK1:
     208                $cnt=0;
     209                break;
     210            case DSUTILS_WEEK2:
     211                $cnt=1;
     212                break;
     213            case DSUTILS_WEEK4:
     214                $cnt=3;
     215                break;
     216        }
     217        while( $t <= self::$iMax ) {
     218            self::$tickPositions[$i++] = $t;
     219            for($k=0; $k < $cnt; ++$k ) {
     220                $t += $hpw;
     221                if( $aMinor ) {
     222                    self::$minTickPositions[$j++] = $t;
     223                }
     224            }
     225            $t += $hpw;
     226        }
    302227    }
    303228
    304229    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);
     230        $monthcount=0;
     231        $m = self::$startmonth;
     232        $y = self::$startyear;
     233        $i=0; $j=0;
     234
     235        // Skip the first month label if it is before the startdate
     236        if( self::$startday == 1 ) {
     237            self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
     238            $monthcount=1;
     239        }
     240        if( $aType == 1 ) {
     241            if( self::$startday < 15 ) {
     242                self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y);
     243            }
     244        }
     245        ++$m;
     246
     247        // Loop through all the years included in the scale
     248        for($y=self::$startyear; $y <= self::$endyear; ++$y ) {
     249            // Loop through all the months. There are three cases to consider:
     250            // 1. We are in the first year and must start with the startmonth
     251            // 2. We are in the end year and we must stop at last month of the scale
     252            // 3. A year in between where we run through all the 12 months
     253            $stopmonth = $y == self::$endyear ? self::$endmonth : 12;
     254            while( $m <= $stopmonth ) {
     255                switch( $aType ) {
     256                    case DSUTILS_MONTH1:
     257                        // Set minor tick at the middle of the month
     258                        if( $aMinor ) {
     259                            if( $m <= $stopmonth ) {
     260                                if( !($y==self::$endyear && $m==$stopmonth && self::$endday < 15) )
     261                                self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y);
     262                            }
     263                        }
     264                        // Major at month
     265                        // Get timestamp of first hour of first day in each month
     266                        self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
     267
     268                        break;
     269                    case DSUTILS_MONTH2:
     270                        if( $aMinor ) {
     271                            // Set minor tick at start of each month
     272                            self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
     273                        }
     274
     275                        // Major at every second month
     276                        // Get timestamp of first hour of first day in each month
     277                        if( $monthcount % 2 == 0 ) {
     278                            self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
     279                        }
     280                        break;
     281                    case DSUTILS_MONTH3:
     282                        if( $aMinor ) {
     283                            // Set minor tick at start of each month
     284                            self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
     285                        }
     286                        // Major at every third month
     287                        // Get timestamp of first hour of first day in each month
     288                        if( $monthcount % 3 == 0 ) {
     289                            self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
     290                        }
     291                        break;
     292                    case DSUTILS_MONTH6:
     293                        if( $aMinor ) {
     294                            // Set minor tick at start of each month
     295                            self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
     296                        }
     297                        // Major at every third month
     298                        // Get timestamp of first hour of first day in each month
     299                        if( $monthcount % 6 == 0 ) {
     300                            self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
     301                        }
     302                        break;
     303                }
     304                ++$m;
     305                ++$monthcount;
     306            }
     307            $m=1;
     308        }
     309
     310        // For the case where all dates are within the same month
     311        // we want to make sure we have at least two ticks on the scale
     312        // since the scale want work properly otherwise
     313        if(self::$startmonth == self::$endmonth && self::$startyear == self::$endyear && $aType==1 ) {
     314            self::$tickPositions[$i++] = mktime(0 ,0 ,0, self::$startmonth + 1, 1, self::$startyear);
     315        }
     316
     317        return array(self::$tickPositions,self::$minTickPositions);
    393318    }
    394319
    395320    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);
     321        $n = count($aData);
     322        return self::GetTicksFromMinMax($aData[0],$aData[$n-1],$aType,$aMinor,$aEndPoints);
    398323    }
    399324
    400325    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         }
     326        $diff = $aMax - $aMin;
     327        $spd = 3600*24;
     328        $spw = $spd*7;
     329        $spm = $spd*30;
     330        $spy = $spd*352;
     331
     332        if( self::$iUseWeeks )
     333        $w = 'W';
     334        else
     335        $w = 'd M';
     336
     337        // Decision table for suitable scales
     338        // First value: Main decision point
     339        // Second value: Array of formatting depending on divisor for wanted max number of ticks. <divisor><formatting><format-string>,..
     340        $tt = array(
     341            array($spw, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',-1,DSUTILS_DAY4,'d M')),
     342            array($spm, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',4,DSUTILS_DAY4,'d M',7,DSUTILS_WEEK1,$w,-1,DSUTILS_WEEK2,$w)),
     343            array($spy, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',4,DSUTILS_DAY4,'d M',7,DSUTILS_WEEK1,$w,14,DSUTILS_WEEK2,$w,30,DSUTILS_MONTH1,'M',60,DSUTILS_MONTH2,'M',-1,DSUTILS_MONTH3,'M')),
     344            array(-1, array(30,DSUTILS_MONTH1,'M-Y',60,DSUTILS_MONTH2,'M-Y',90,DSUTILS_MONTH3,'M-Y',180,DSUTILS_MONTH6,'M-Y',352,DSUTILS_YEAR1,'Y',704,DSUTILS_YEAR2,'Y',-1,DSUTILS_YEAR5,'Y')));
     345
     346        $ntt = count($tt);
     347        $nd = floor($diff/$spd);
     348        for($i=0; $i < $ntt; ++$i ) {
     349            if( $diff <= $tt[$i][0] || $i==$ntt-1) {
     350                $t = $tt[$i][1];
     351                $n = count($t)/3;
     352                for( $j=0; $j < $n; ++$j ) {
     353                    if( $nd/$t[3*$j] <= $aMaxTicks || $j==$n-1) {
     354                        $type = $t[3*$j+1];
     355                        $fs = $t[3*$j+2];
     356                        list($tickPositions,$minTickPositions) = self::GetTicksFromMinMax($aMin,$aMax,$type,$aMinor);
     357                        return array($fs,$tickPositions,$minTickPositions,$type);
     358                    }
     359                }
     360            }
     361        }
    441362    }
    442363
    443364    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 
     365        self::$starthour = date('G',$aMin);
     366        self::$startmonth = date('n',$aMin);
     367        self::$startday = date('j',$aMin);
     368        self::$startyear = date('Y',$aMin);
     369        self::$endmonth = date('n',$aMax);
     370        self::$endyear = date('Y',$aMax);
     371        self::$endday = date('j',$aMax);
     372        self::$iMin = $aMin;
     373        self::$iMax = $aMax;
     374
     375        if( $aType <= DSUTILS_MONTH6 ) {
     376            self::doMonthly($aType,$aMinor);
     377        }
     378        elseif( $aType <= DSUTILS_WEEK4 ) {
     379            self::doWeekly($aType,$aMinor);
     380        }
     381        elseif( $aType <= DSUTILS_DAY4 ) {
     382            self::doDaily($aType,$aMinor);
     383        }
     384        elseif( $aType <= DSUTILS_YEAR5 ) {
     385            self::doYearly($aType,$aMinor);
     386        }
     387        else {
     388            JpGraphError::RaiseL(24003);
     389        }
     390        // put a label at the very left data pos
     391        if( $aEndPoints ) {
     392            $tickPositions[$i++] = $aData[0];
     393        }
     394
     395        // put a label at the very right data pos
     396        if( $aEndPoints ) {
     397            $tickPositions[$i] = $aData[$n-1];
     398        }
     399
     400        return array(self::$tickPositions,self::$minTickPositions);
     401    }
    482402}
    483403
     
    486406//=============================================================================
    487407Class ReadFileData {
    488 
    489408    //----------------------------------------------------------------------------
    490409    // Desciption:
    491     // Read numeric data from a file. 
    492     // Each value should be separated by either a new line or by a specified 
     410    // Read numeric data from a file.
     411    // Each value should be separated by either a new line or by a specified
    493412    // 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 
     413    // Before returning the data each value is converted to a proper float
     414    // value. The routine is robust in the sense that non numeric data in the
    496415    // file will be discarded.
    497416    //
    498     // Returns: 
     417    // Returns:
    499418    // The number of data values read on success, FALSE on failure
    500419    //----------------------------------------------------------------------------
    501420    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     }
     421        $rh = @fopen($aFile,'r');
     422        if( $rh === false ) {
     423                return false;
     424        }
     425        $tmp = array();
     426        $lineofdata = fgetcsv($rh, 1000, ',');
     427        while ( $lineofdata !== FALSE) {
     428            $tmp = array_merge($tmp,$lineofdata);
     429            $lineofdata = fgetcsv($rh, $aMaxLineLength, $aSepChar);
     430        }
     431        fclose($rh);
     432
     433        // Now make sure that all data is numeric. By default
     434        // all data is read as strings
     435        $n = count($tmp);
     436        $aData = array();
     437        $cnt=0;
     438        for($i=0; $i < $n; ++$i) {
     439            if( $tmp[$i] !== "" ) {
     440                $aData[$cnt++] = floatval($tmp[$i]);
     441            }
     442        }
     443        return $cnt;
     444    }
     445
     446    //----------------------------------------------------------------------------
     447    // Desciption:
     448    // Read numeric data from a file.
     449    // Each value should be separated by either a new line or by a specified
     450    // separator character (default is ',').
     451    // Before returning the data each value is converted to a proper float
     452    // value. The routine is robust in the sense that non numeric data in the
     453    // file will be discarded.
     454    //
     455    // Options:
     456    // 'separator'     => ',',
     457    // 'enclosure'     => '"',
     458    // 'readlength'    => 1024,
     459    // 'ignore_first'  => false,
     460    // 'first_as_key'  => false
     461    // 'escape'        => '\',   # PHP >= 5.3 only
     462    //
     463    // Returns:
     464    // The number of lines read on success, FALSE on failure
     465    //----------------------------------------------------------------------------
     466    static function FromCSV2($aFile, &$aData, $aOptions = array()) {
     467        $aDefaults = array(
     468            'separator'     => ',',
     469            'enclosure'     => chr(34),
     470            'escape'        => chr(92),
     471            'readlength'    => 1024,
     472            'ignore_first'  => false,
     473            'first_as_key'  => false
     474            );
     475
     476        $aOptions = array_merge(
     477            $aDefaults, is_array($aOptions) ? $aOptions : array());
     478
     479        if( $aOptions['first_as_key'] ) {
     480            $aOptions['ignore_first'] =  true;
     481        }
     482
     483        $rh = @fopen($aFile, 'r');
     484
     485        if( $rh === false ) {
     486            return false;
     487        }
     488
     489        $aData  = array();
     490        $aLine  = fgetcsv($rh,
     491                          $aOptions['readlength'],
     492                          $aOptions['separator'],
     493                          $aOptions['enclosure']
     494                          /*, $aOptions['escape']     # PHP >= 5.3 only */
     495                          );
     496
     497        // Use numeric array keys for the columns by default
     498        // If specified use first lines values as assoc keys instead
     499        $keys = array_keys($aLine);
     500        if( $aOptions['first_as_key'] ) {
     501            $keys = array_values($aLine);
     502        }
     503
     504        $num_lines = 0;
     505        $num_cols  = count($aLine);
     506
     507        while ($aLine !== false) {
     508            if( is_array($aLine) && count($aLine) != $num_cols ) {
     509                JpGraphError::RaiseL(24004);
     510                // 'ReadCSV2: Column count mismatch in %s line %d'
     511            }
     512
     513            // fgetcsv returns NULL for empty lines
     514            if( !is_null($aLine) ) {
     515                $num_lines++;
     516
     517                if( !($aOptions['ignore_first'] && $num_lines == 1) && is_numeric($aLine[0]) ) {
     518                    for( $i = 0; $i < $num_cols; $i++ ) {
     519                        $aData[ $keys[$i] ][] = floatval($aLine[$i]);
     520                    }
     521                }
     522            }
     523
     524            $aLine = fgetcsv($rh,
     525                             $aOptions['readlength'],
     526                             $aOptions['separator'],
     527                             $aOptions['enclosure']
     528                             /*, $aOptions['escape']     # PHP >= 5.3 only*/
     529                );
     530        }
     531
     532        fclose($rh);
     533
     534        if( $aOptions['ignore_first'] ) {
     535            $num_lines--;
     536        }
     537
     538        return $num_lines;
     539    }
     540
     541    // Read data from two columns in a plain text file
     542    static function From2Col($aFile, $aCol1, $aCol2, $aSepChar=' ') {
     543        $lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
     544        if( $lines === false ) {
     545                return false;
     546        }
     547        $s = '/[\s]+/';
     548        if( $aSepChar == ',' ) {
     549                        $s = '/[\s]*,[\s]*/';
     550        }
     551        elseif( $aSepChar == ';' ) {
     552                        $s = '/[\s]*;[\s]*/';
     553        }
     554        foreach( $lines as $line => $datarow ) {
     555                $split = preg_split($s,$datarow);
     556                $aCol1[] = floatval(trim($split[0]));
     557                $aCol2[] = floatval(trim($split[1]));
     558        }
     559
     560        return count($lines);
     561    }
     562
     563    // Read data from one columns in a plain text file
     564    static function From1Col($aFile, $aCol1) {
     565        $lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
     566        if( $lines === false ) {
     567                return false;
     568        }
     569        foreach( $lines as $line => $datarow ) {
     570                $aCol1[] = floatval(trim($datarow));
     571        }
     572
     573        return count($lines);
     574    }
     575
     576    static function FromMatrix($aFile,$aSepChar=' ') {
     577        $lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
     578        if( $lines === false ) {
     579                return false;
     580        }
     581        $mat = array();
     582        $reg = '/'.$aSepChar.'/';
     583        foreach( $lines as $line => $datarow ) {
     584                $row = preg_split($reg,trim($datarow));
     585                foreach ($row as $key => $cell ) {
     586                        $row[$key] = floatval(trim($cell));
     587                }
     588                $mat[] = $row;
     589        }
     590        return $mat;
     591    }
     592
     593
    525594}
    526595
     596define('__LR_EPSILON', 1.0e-8);
     597//=============================================================================
     598// Class LinearRegression
     599//=============================================================================
     600class LinearRegression {
     601        private $ix=array(),$iy=array();
     602        private $ib=0, $ia=0;
     603        private $icalculated=false;
     604        public $iDet=0, $iCorr=0, $iStdErr=0;
     605
     606        public function __construct($aDataX,$aDataY) {
     607                if( count($aDataX) !== count($aDataY) ) {
     608                        JpGraph::Raise('LinearRegression: X and Y data array must be of equal length.');
     609                }
     610                $this->ix = $aDataX;
     611                $this->iy = $aDataY;
     612        }
     613
     614        public function Calc() {
     615
     616                $this->icalculated = true;
     617
     618                $n = count($this->ix);
     619                $sx2 = 0 ;
     620                $sy2 = 0 ;
     621                $sxy = 0 ;
     622                $sx = 0 ;
     623                $sy = 0 ;
     624
     625                for( $i=0; $i < $n; ++$i ) {
     626                        $sx2 += $this->ix[$i] * $this->ix[$i];
     627                        $sy2 += $this->iy[$i] * $this->iy[$i];
     628                        $sxy += $this->ix[$i] * $this->iy[$i];
     629                        $sx += $this->ix[$i];
     630                        $sy += $this->iy[$i];
     631                }
     632
     633                if( $n*$sx2 - $sx*$sx > __LR_EPSILON ) {
     634                        $this->ib = ($n*$sxy - $sx*$sy) / ( $n*$sx2 - $sx*$sx );
     635                        $this->ia = ( $sy - $this->ib*$sx ) / $n;
     636
     637                        $sx = $this->ib * ( $sxy - $sx*$sy/$n );
     638                        $sy2 = $sy2 - $sy*$sy/$n;
     639                        $sy = $sy2 - $sx;
     640
     641                        $this->iDet = $sx / $sy2;
     642                        $this->iCorr = sqrt($this->iDet);
     643                        if( $n > 2 ) {
     644                                $this->iStdErr = sqrt( $sy / ($n-2) );
     645                        }
     646                        else {
     647                                $this->iStdErr = NAN ;
     648                        }
     649                }
     650                else {
     651                        $this->ib = 0;
     652                        $this->ia = 0;
     653                }
     654
     655        }
     656
     657        public function GetAB() {
     658                if( $this->icalculated == false )
     659                        $this->Calc();
     660                return array($this->ia, $this->ib);
     661        }
     662
     663        public function GetStat() {
     664                if( $this->icalculated == false )
     665                        $this->Calc();
     666                return array($this->iStdErr, $this->iCorr, $this->iDet);
     667        }
     668
     669        public function GetY($aMinX, $aMaxX, $aStep=1) {
     670                if( $this->icalculated == false )
     671                        $this->Calc();
     672
     673                $yy = array();
     674                $i = 0;
     675                for( $x=$aMinX; $x <= $aMaxX; $x += $aStep ) {
     676                        $xx[$i  ] = $x;
     677                        $yy[$i++] = $this->ia + $this->ib * $x;
     678                }
     679
     680                return array($xx,$yy);
     681        }
     682
     683}
     684
    527685?>
Note: See TracChangeset for help on using the changeset viewer.