source: trunk/xgraph/jpgraph/jpgraph_log.php @ 42

Last change on this file since 42 was 42, checked in by marrucho, 10 years ago
File size: 11.1 KB
Line 
1<?php
2/*=======================================================================
3 // File:        JPGRAPH_LOG.PHP
4 // Description: Log scale plot extension for JpGraph
5 // Created:     2001-01-08
6 // Ver:         $Id: jpgraph_log.php 1106 2009-02-22 20:16:35Z ljp $
7 //
8 // Copyright (c) Asial Corporation. All rights reserved.
9 //========================================================================
10 */
11
12DEFINE('LOGLABELS_PLAIN',0);
13DEFINE('LOGLABELS_MAGNITUDE',1);
14
15//===================================================
16// CLASS LogScale
17// Description: Logarithmic scale between world and screen
18//===================================================
19class LogScale extends LinearScale {
20    //---------------
21    // CONSTRUCTOR
22
23    // Log scale is specified using the log of min and max
24    function __construct($min,$max,$type="y") {
25        parent::__construct($min,$max,$type);
26        $this->ticks = new LogTicks();
27        $this->name = 'log';
28    }
29
30    //----------------
31    // PUBLIC METHODS
32
33    // Translate between world and screen
34    function Translate($a) {
35        if( !is_numeric($a) ) {
36            if( $a != '' && $a != '-' && $a != 'x' ) { 
37                JpGraphError::RaiseL(11001);
38                // ('Your data contains non-numeric values.');
39            }
40            return 1;
41        }
42        if( $a < 0 ) {
43            JpGraphError::RaiseL(11002);
44            //("Negative data values can not be used in a log scale.");
45            exit(1);
46        }
47        if( $a==0 ) $a=1;
48        $a=log10($a);
49        return ceil($this->off + ($a*1.0 - $this->scale[0]) * $this->scale_factor);
50    }
51
52    // Relative translate (don't include offset) usefull when we just want
53    // to know the relative position (in pixels) on the axis
54    function RelTranslate($a) {
55        if( !is_numeric($a) ) {
56            if( $a != '' && $a != '-' && $a != 'x' ) {
57                JpGraphError::RaiseL(11001);
58                //('Your data contains non-numeric values.');
59            }
60            return 1;
61        }
62        if( $a==0 ) {
63            $a=1;
64        }
65        $a=log10($a);
66        return round(($a*1.0 - $this->scale[0]) * $this->scale_factor);
67    }
68
69    // Use bcpow() for increased precision
70    function GetMinVal() {
71        if( function_exists("bcpow") ) {
72            return round(bcpow(10,$this->scale[0],15),14);
73        }
74        else {
75            return round(pow(10,$this->scale[0]),14);
76        }
77    }
78
79    function GetMaxVal() {
80        if( function_exists("bcpow") ) {
81            return round(bcpow(10,$this->scale[1],15),14);
82        }
83        else {
84            return round(pow(10,$this->scale[1]),14);
85        }
86    }
87
88    // Logarithmic autoscaling is much simplier since we just
89    // set the min and max to logs of the min and max values.
90    // Note that for log autoscale the "maxstep" the fourth argument
91    // isn't used. This is just included to give the method the same
92    // signature as the linear counterpart.
93    function AutoScale($img,$min,$max,$maxsteps,$majend=true) {
94        if( $min==0 ) $min=1;
95
96        if( $max <= 0 ) {
97            JpGraphError::RaiseL(11004);
98            //('Scale error for logarithmic scale. You have a problem with your data values. The max value must be greater than 0. It is mathematically impossible to have 0 in a logarithmic scale.');
99        }
100        if( is_numeric($this->autoscale_min) ) {
101            $smin = round($this->autoscale_min);
102            $smax = ceil(log10($max));
103            if( $min >= $max ) {
104                JpGraphError::RaiseL(25071);//('You have specified a min value with SetAutoMin() which is larger than the maximum value used for the scale. This is not possible.');
105            }
106        }
107        else {
108            $smin = floor(log10($min));
109            if( is_numeric($this->autoscale_max) ) {
110                $smax = round($this->autoscale_max);
111                if( $smin >= $smax ) {
112                    JpGraphError::RaiseL(25072);//('You have specified a max value with SetAutoMax() which is smaller than the miminum value used for the scale. This is not possible.');
113                }
114            }
115            else
116            $smax = ceil(log10($max));
117        }
118
119        $this->Update($img,$smin,$smax);
120    }
121    //---------------
122    // PRIVATE METHODS
123} // Class
124
125//===================================================
126// CLASS LogTicks
127// Description:
128//===================================================
129class LogTicks extends Ticks{
130    private $label_logtype=LOGLABELS_MAGNITUDE;
131    private $ticklabels_pos = array();
132    //---------------
133    // CONSTRUCTOR
134    function LogTicks() {
135    }
136    //---------------
137    // PUBLIC METHODS
138    function IsSpecified() {
139        return true;
140    }
141
142    function SetLabelLogType($aType) {
143        $this->label_logtype = $aType;
144    }
145
146    // For log scale it's meaningless to speak about a major step
147    // We just return -1 to make the framework happy (specifically
148    // StrokeLabels() )
149    function GetMajor() {
150        return -1;
151    }
152
153    function SetTextLabelStart($aStart) {
154        JpGraphError::RaiseL(11005);
155        //('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.');
156    }
157
158    function SetXLabelOffset($dummy) {
159        // For log scales we dont care about XLabel offset
160    }
161
162    // Draw ticks on image "img" using scale "scale". The axis absolute
163    // position in the image is specified in pos, i.e. for an x-axis
164    // it specifies the absolute y-coord and for Y-ticks it specified the
165    // absolute x-position.
166    function Stroke($img,$scale,$pos) {
167        $start = $scale->GetMinVal();
168        $limit = $scale->GetMaxVal();
169        $nextMajor = 10*$start;
170        $step = $nextMajor / 10.0;
171
172
173        $img->SetLineWeight($this->weight);
174
175        if( $scale->type == "y" ) {
176            // member direction specified if the ticks should be on
177            // left or right side.
178            $a=$pos + $this->direction*$this->GetMinTickAbsSize();
179            $a2=$pos + $this->direction*$this->GetMajTickAbsSize();
180             
181            $count=1;
182            $this->maj_ticks_pos[0]=$scale->Translate($start);
183            $this->maj_ticklabels_pos[0]=$scale->Translate($start);
184            if( $this->supress_first )
185            $this->maj_ticks_label[0]="";
186            else {
187                if( $this->label_formfunc != '' ) {
188                    $f = $this->label_formfunc;
189                    $this->maj_ticks_label[0]=call_user_func($f,$start);
190                }
191                elseif( $this->label_logtype == LOGLABELS_PLAIN ) {
192                    $this->maj_ticks_label[0]=$start;
193                }
194                else {
195                    $this->maj_ticks_label[0]='10^'.round(log10($start));
196                }
197            }
198            $i=1;
199            for($y=$start; $y<=$limit; $y+=$step,++$count  ) {
200                $ys=$scale->Translate($y);
201                $this->ticks_pos[]=$ys;
202                $this->ticklabels_pos[]=$ys;
203                if( $count % 10 == 0 ) {
204                    if( !$this->supress_tickmarks ) {
205                        if( $this->majcolor!="" ) {
206                            $img->PushColor($this->majcolor);
207                            $img->Line($pos,$ys,$a2,$ys);
208                            $img->PopColor();
209                        }
210                        else {
211                            $img->Line($pos,$ys,$a2,$ys);
212                        }
213                    }
214
215                    $this->maj_ticks_pos[$i]=$ys;
216                    $this->maj_ticklabels_pos[$i]=$ys;
217
218                    if( $this->label_formfunc != '' ) {
219                        $f = $this->label_formfunc;
220                        $this->maj_ticks_label[$i]=call_user_func($f,$nextMajor);
221                    }
222                    elseif( $this->label_logtype == 0 ) {
223                        $this->maj_ticks_label[$i]=$nextMajor;
224                    }
225                    else {
226                        $this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));
227                    }
228                    ++$i;
229                    $nextMajor *= 10;
230                    $step *= 10;
231                    $count=1;
232                }
233                else {
234                    if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
235                        if( $this->mincolor!="" ) {
236                            $img->PushColor($this->mincolor);
237                        }
238                        $img->Line($pos,$ys,$a,$ys);
239                        if( $this->mincolor!="" ) {
240                            $img->PopColor();
241                        }
242                    }
243                }
244            }
245        }
246        else {
247            $a=$pos - $this->direction*$this->GetMinTickAbsSize();
248            $a2=$pos - $this->direction*$this->GetMajTickAbsSize();
249            $count=1;
250            $this->maj_ticks_pos[0]=$scale->Translate($start);
251            $this->maj_ticklabels_pos[0]=$scale->Translate($start);
252            if( $this->supress_first ) {
253                $this->maj_ticks_label[0]="";
254            }
255            else {
256                if( $this->label_formfunc != '' ) {
257                    $f = $this->label_formfunc;
258                    $this->maj_ticks_label[0]=call_user_func($f,$start);
259                }
260                elseif( $this->label_logtype == 0 ) {
261                    $this->maj_ticks_label[0]=$start;
262                }
263                else {
264                    $this->maj_ticks_label[0]='10^'.round(log10($start));
265                }
266            }
267            $i=1;
268            for($x=$start; $x<=$limit; $x+=$step,++$count  ) {
269                $xs=$scale->Translate($x);
270                $this->ticks_pos[]=$xs;
271                $this->ticklabels_pos[]=$xs;
272                if( $count % 10 == 0 ) {
273                    if( !$this->supress_tickmarks ) {
274                        $img->Line($xs,$pos,$xs,$a2);
275                    }
276                    $this->maj_ticks_pos[$i]=$xs;
277                    $this->maj_ticklabels_pos[$i]=$xs;
278
279                    if( $this->label_formfunc != '' ) {
280                        $f = $this->label_formfunc;
281                        $this->maj_ticks_label[$i]=call_user_func($f,$nextMajor);
282                    }
283                    elseif( $this->label_logtype == 0 ) {
284                        $this->maj_ticks_label[$i]=$nextMajor;
285                    }
286                    else {
287                        $this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));
288                    }
289                    ++$i;
290                    $nextMajor *= 10;
291                    $step *= 10;
292                    $count=1;
293                }
294                else {
295                    if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
296                        $img->Line($xs,$pos,$xs,$a);
297                    }
298                }
299            }
300        }
301        return true;
302    }
303} // Class
304/* EOF */
305?>
Note: See TracBrowser for help on using the repository browser.