Ignore:
Timestamp:
Apr 14, 2019, 2:31:40 PM (5 years ago)
Author:
roby
Message:
 
File:
1 edited

Legend:

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

    r265 r267  
    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 1777 2009-08-23 17:34:36Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. 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 1091 2009-01-18 22:57:40Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. 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 __construct($aFunc,$aXFunc='') {
    21         $this->iFunc = $aFunc;
    22         $this->iXFunc = $aXFunc;
    23     }
    24 
     19       
     20    function FuncGenerator($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);
     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 '';
    45120    }
    46121}
     
    76151
    77152    static function UseWeekFormat($aFlg) {
    78         self::$iUseWeeks = $aFlg;
     153        self::$iUseWeeks = $aFlg;
    79154    }
    80155
    81156    static function doYearly($aType,$aMinor=false) {
    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         }
     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        }
    134209    }
    135210
    136211    static function doDaily($aType,$aMinor=false) {
    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         }
     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        }
    181256    }
    182257
    183258    static function doWeekly($aType,$aMinor=false) {
    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         }
     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        }
    227302    }
    228303
    229304    static function doMonthly($aType,$aMinor=false) {
    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);
     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);
    318393    }
    319394
    320395    static function GetTicks($aData,$aType=1,$aMinor=false,$aEndPoints=false) {
    321         $n = count($aData);
    322         return self::GetTicksFromMinMax($aData[0],$aData[$n-1],$aType,$aMinor,$aEndPoints);
     396        $n = count($aData);
     397        return self::GetTicksFromMinMax($aData[0],$aData[$n-1],$aType,$aMinor,$aEndPoints);
    323398    }
    324399
    325400    static function GetAutoTicks($aMin,$aMax,$aMaxTicks=10,$aMinor=false) {
    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         }
     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        }
    362441    }
    363442
    364443    static function GetTicksFromMinMax($aMin,$aMax,$aType,$aMinor=false,$aEndPoints=false) {
    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     }
     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
    402482}
    403483
     
    406486//=============================================================================
    407487Class ReadFileData {
     488
    408489    //----------------------------------------------------------------------------
    409490    // Desciption:
    410     // Read numeric data from a file.
    411     // Each value should be separated by either a new line or by a specified
     491    // Read numeric data from a file. 
     492    // Each value should be separated by either a new line or by a specified 
    412493    // separator character (default is ',').
    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
     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 
    415496    // file will be discarded.
    416497    //
    417     // Returns:
     498    // Returns: 
    418499    // The number of data values read on success, FALSE on failure
    419500    //----------------------------------------------------------------------------
    420501    static function FromCSV($aFile,&$aData,$aSepChar=',',$aMaxLineLength=1024) {
    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 
     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    }
    594525}
    595526
    596 define('__LR_EPSILON', 1.0e-8);
    597 //=============================================================================
    598 // Class LinearRegression
    599 //=============================================================================
    600 class 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 
    685527?>
Note: See TracChangeset for help on using the changeset viewer.