Subversion Repositories Sites.tela-botanica.org

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 david 1
<?php
2
/*=======================================================================
3
// File: 	JPGRAPH_LOG.PHP
4
// Description:	Log scale plot extension for JpGraph
5
// Created: 	2001-01-08
6
// Author:	Johan Persson (johanp@aditus.nu)
7
// Ver:		$Id: jpgraph_log.php,v 1.1 2004/06/15 10:13:19 jpm Exp $
8
//
9
// License:	This code is released under QPL
10
// Copyright (C) 2001,2002 Johan Persson
11
//========================================================================
12
*/
13
 
14
 
15
DEFINE('LOGLABELS_PLAIN',0);
16
DEFINE('LOGLABELS_MAGNITUDE',1);
17
 
18
//===================================================
19
// CLASS LogScale
20
// Description: Logarithmic scale between world and screen
21
//===================================================
22
class LogScale extends LinearScale {
23
//---------------
24
// CONSTRUCTOR
25
 
26
    // Log scale is specified using the log of min and max
27
    function LogScale($min,$max,$type="y") {
28
	$this->LinearScale($min,$max,$type);
29
	$this->ticks = new LogTicks();
30
	$this->name = 'log';
31
    }
32
 
33
//----------------
34
// PUBLIC METHODS
35
 
36
    // Translate between world and screen
37
    function	Translate($a) {
38
	if( $a < 0 ) {
39
	    JpGraphError::Raise("Negative data values can not be used in a log scale.");
40
	    exit(1);
41
	}
42
	if( $a==0 ) $a=1;
43
	$a=log10($a);
44
	return ceil($this->off + ($a*1.0 - $this->scale[0]) * $this->scale_factor);
45
    }
46
 
47
    // Relative translate (don't include offset) usefull when we just want
48
    // to know the relative position (in pixels) on the axis
49
    function RelTranslate($a) {
50
	if( $a==0 ) $a=1;
51
	$a=log10($a);
52
	return round(($a*1.0 - $this->scale[0]) * $this->scale_factor);
53
    }
54
 
55
    // Use bcpow() for increased precision
56
    function GetMinVal() {
57
	if( function_exists("bcpow") )
58
	    return round(bcpow(10,$this->scale[0],15),14);
59
	else
60
	    return round(pow(10,$this->scale[0]));
61
    }
62
 
63
    function GetMaxVal() {
64
	if( function_exists("bcpow") )
65
	    return round(bcpow(10,$this->scale[1],15),14);
66
	else
67
	    return round(pow(10,$this->scale[1]));
68
    }
69
 
70
    // Logarithmic autoscaling is much simplier since we just
71
    // set the min and max to logs of the min and max values.
72
    // Note that for log autoscale the "maxstep" the fourth argument
73
    // isn't used. This is just included to give the method the same
74
    // signature as the linear counterpart.
75
    function AutoScale(&$img,$min,$max,$dummy) {
76
	if( $min==0 ) $min=1;
77
	assert($max>0);
78
	$smin = floor(log10($min));
79
	$smax = ceil(log10($max));
80
	$this->Update($img,$smin,$smax);
81
    }
82
//---------------
83
// PRIVATE METHODS
84
} // Class
85
 
86
//===================================================
87
// CLASS LogTicks
88
// Description:
89
//===================================================
90
class LogTicks extends Ticks{
91
    var $label_logtype=LOGLABELS_MAGNITUDE;
92
//---------------
93
// CONSTRUCTOR
94
    function LogTicks() {
95
    }
96
//---------------
97
// PUBLIC METHODS
98
    function IsSpecified() {
99
	return true;
100
    }
101
 
102
    function SetLabelLogType($aType) {
103
	$this->label_logtype = $aType;
104
    }
105
 
106
    // For log scale it's meaningless to speak about a major step
107
    // We just return -1 to make the framework happy (specifically
108
    // StrokeLabels() )
109
    function GetMajor() {
110
	return -1;
111
    }
112
 
113
    function SetTextLabelStart($aStart) {
114
	JpGraphError::Raise('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.');
115
    }
116
 
117
    function SetXLabelOffset($dummy) {
118
	// For log scales we dont care about XLabel offset
119
    }
120
 
121
    // Draw ticks on image "img" using scale "scale". The axis absolute
122
    // position in the image is specified in pos, i.e. for an x-axis
123
    // it specifies the absolute y-coord and for Y-ticks it specified the
124
    // absolute x-position.
125
    function Stroke(&$img,&$scale,$pos) {
126
	$start = $scale->GetMinVal();
127
	$limit = $scale->GetMaxVal();
128
	$nextMajor = 10*$start;
129
	$step = $nextMajor / 10.0;
130
 
131
 
132
	$img->SetLineWeight($this->weight);
133
 
134
	if( $scale->type == "y" ) {
135
	    // member direction specified if the ticks should be on
136
	    // left or right side.
137
	    $a=$pos + $this->direction*$this->GetMinTickAbsSize();
138
	    $a2=$pos + $this->direction*$this->GetMajTickAbsSize();
139
 
140
	    $count=1;
141
	    $this->maj_ticks_pos[0]=$scale->Translate($start);
142
	    $this->maj_ticklabels_pos[0]=$scale->Translate($start);
143
	    if( $this->supress_first )
144
		$this->maj_ticks_label[0]="";
145
	    else {
146
		if( $this->label_formfunc != '' ) {
147
		    $f = $this->label_formfunc;
148
		    $this->maj_ticks_label[0]=$f($start);
149
		}
150
		elseif( $this->label_logtype == LOGLABELS_PLAIN )
151
		    $this->maj_ticks_label[0]=$start;
152
		else
153
		    $this->maj_ticks_label[0]='10^'.round(log10($start));
154
	    }
155
	    $i=1;
156
	    for($y=$start; $y<=$limit; $y+=$step,++$count  ) {
157
		$ys=$scale->Translate($y);
158
		$this->ticks_pos[]=$ys;
159
		$this->ticklabels_pos[]=$ys;
160
		if( $count % 10 == 0 ) {
161
		    if( $this->majcolor!="" ) {
162
			$img->PushColor($this->majcolor);
163
			$img->Line($pos,$ys,$a2,$ys);
164
			$img->PopColor();
165
		    }
166
		    else
167
			$img->Line($pos,$ys,$a2,$ys);
168
 
169
		    $this->maj_ticks_pos[$i]=$ys;
170
		    $this->maj_ticklabels_pos[$i]=$ys;
171
 
172
		    if( $this->label_formfunc != '' ) {
173
			$f = $this->label_formfunc;
174
			$this->maj_ticks_label[$i]=$f($nextMajor);
175
		    }
176
		    elseif( $this->label_logtype == 0 )
177
			$this->maj_ticks_label[$i]=$nextMajor;
178
		    else
179
			$this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));
180
		    ++$i;
181
		    $nextMajor *= 10;
182
		    $step *= 10;
183
		    $count=1;
184
		}
185
		else {
186
		    if( $this->mincolor!="" ) $img->PushColor($this->mincolor);
187
		    $img->Line($pos,$ys,$a,$ys);
188
		    if( $this->mincolor!="" ) $img->PopCOlor();
189
		}
190
	    }
191
	}
192
	else {
193
	    $a=$pos - $this->direction*$this->GetMinTickAbsSize();
194
	    $a2=$pos - $this->direction*$this->GetMajTickAbsSize();
195
	    $count=1;
196
	    $this->maj_ticks_pos[0]=$scale->Translate($start);
197
	    $this->maj_ticklabels_pos[0]=$scale->Translate($start);
198
	    if( $this->supress_first )
199
		$this->maj_ticks_label[0]="";
200
	    else {
201
		if( $this->label_formfunc != '' ) {
202
		    $f = $this->label_formfunc;
203
		    $this->maj_ticks_label[0]=$f($start);
204
		}
205
		elseif( $this->label_logtype == 0 )
206
		    $this->maj_ticks_label[0]=$start;
207
		else
208
		    $this->maj_ticks_label[0]='10^'.round(log10($start));
209
	    }
210
	    $i=1;
211
	    for($x=$start; $x<=$limit; $x+=$step,++$count  ) {
212
		$xs=$scale->Translate($x);
213
		$this->ticks_pos[]=$xs;
214
		$this->ticklabels_pos[]=$xs;
215
		if( $count % 10 == 0 ) {
216
		    $img->Line($xs,$pos,$xs,$a2);
217
		    $this->maj_ticks_pos[$i]=$xs;
218
		    $this->maj_ticklabels_pos[$i]=$xs;
219
 
220
		    if( $this->label_formfunc != '' ) {
221
			$f = $this->label_formfunc;
222
			$this->maj_ticks_label[$i]=$f($nextMajor);
223
		    }
224
		    elseif( $this->label_logtype == 0 )
225
			$this->maj_ticks_label[$i]=$nextMajor;
226
		    else
227
			$this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));
228
		    ++$i;
229
		    $nextMajor *= 10;
230
		    $step *= 10;
231
		    $count=1;
232
		}
233
		else
234
		    $img->Line($xs,$pos,$xs,$a);
235
	    }
236
	}
237
	return true;
238
    }
239
} // Class
240
/* EOF */
241
?>