2
/*=======================================================================
3
// File: JPGRAPH_LOG.PHP
4
// Description: Log scale plot extension for JpGraph
6
// Ver: $Id: jpgraph_log.php 820 2006-12-14 01:04:01Z ljp $
8
// Copyright (c) Aditus Consulting. All rights reserved.
9
//========================================================================
13
DEFINE('LOGLABELS_PLAIN',0);
14
DEFINE('LOGLABELS_MAGNITUDE',1);
16
//===================================================
18
// Description: Logarithmic scale between world and screen
19
//===================================================
20
class LogScale extends LinearScale {
24
// Log scale is specified using the log of min and max
25
function LogScale($min,$max,$type="y") {
26
$this->LinearScale($min,$max,$type);
27
$this->ticks = new LogTicks();
34
// Translate between world and screen
35
function Translate($a) {
36
if( !is_numeric($a) ) {
37
if( $a != '' && $a != '-' && $a != 'x' )
38
JpGraphError::RaiseL(11001);
39
//('Your data contains non-numeric values.');
43
JpGraphError::RaiseL(11002);
44
//("Negative data values can not be used in a log scale.");
49
return ceil($this->off + ($a*1.0 - $this->scale[0]) * $this->scale_factor);
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.');
63
return round(($a*1.0 - $this->scale[0]) * $this->scale_factor);
66
// Use bcpow() for increased precision
67
function GetMinVal() {
68
if( function_exists("bcpow") )
69
return round(bcpow(10,$this->scale[0],15),14);
71
return round(pow(10,$this->scale[0]),14);
74
function GetMaxVal() {
75
if( function_exists("bcpow") )
76
return round(bcpow(10,$this->scale[1],15),14);
78
return round(pow(10,$this->scale[1]),14);
81
// Logarithmic autoscaling is much simplier since we just
82
// set the min and max to logs of the min and max values.
83
// Note that for log autoscale the "maxstep" the fourth argument
84
// isn't used. This is just included to give the method the same
85
// signature as the linear counterpart.
86
function AutoScale(&$img,$min,$max,$dummy) {
90
JpGraphError::RaiseL(11004);
91
//('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.');
93
if( is_numeric($this->autoscale_min) ) {
94
$smin = round($this->autoscale_min);
95
$smax = ceil(log10($max));
97
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.');
101
$smin = floor(log10($min));
102
if( is_numeric($this->autoscale_max) ) {
103
$smax = round($this->autoscale_max);
104
if( $smin >= $smax ) {
105
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.');
109
$smax = ceil(log10($max));
111
$this->Update($img,$smin,$smax);
117
//===================================================
120
//===================================================
121
class LogTicks extends Ticks{
122
var $label_logtype=LOGLABELS_MAGNITUDE;
125
function LogTicks() {
129
function IsSpecified() {
133
function SetLabelLogType($aType) {
134
$this->label_logtype = $aType;
137
// For log scale it's meaningless to speak about a major step
138
// We just return -1 to make the framework happy (specifically
140
function GetMajor() {
144
function SetTextLabelStart($aStart) {
145
JpGraphError::RaiseL(11005);
146
//('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.');
149
function SetXLabelOffset($dummy) {
150
// For log scales we dont care about XLabel offset
153
// Draw ticks on image "img" using scale "scale". The axis absolute
154
// position in the image is specified in pos, i.e. for an x-axis
155
// it specifies the absolute y-coord and for Y-ticks it specified the
156
// absolute x-position.
157
function Stroke(&$img,&$scale,$pos) {
158
$start = $scale->GetMinVal();
159
$limit = $scale->GetMaxVal();
160
$nextMajor = 10*$start;
161
$step = $nextMajor / 10.0;
164
$img->SetLineWeight($this->weight);
166
if( $scale->type == "y" ) {
167
// member direction specified if the ticks should be on
168
// left or right side.
169
$a=$pos + $this->direction*$this->GetMinTickAbsSize();
170
$a2=$pos + $this->direction*$this->GetMajTickAbsSize();
173
$this->maj_ticks_pos[0]=$scale->Translate($start);
174
$this->maj_ticklabels_pos[0]=$scale->Translate($start);
175
if( $this->supress_first )
176
$this->maj_ticks_label[0]="";
178
if( $this->label_formfunc != '' ) {
179
$f = $this->label_formfunc;
180
$this->maj_ticks_label[0]=call_user_func($f,$start);
182
elseif( $this->label_logtype == LOGLABELS_PLAIN )
183
$this->maj_ticks_label[0]=$start;
185
$this->maj_ticks_label[0]='10^'.round(log10($start));
188
for($y=$start; $y<=$limit; $y+=$step,++$count ) {
189
$ys=$scale->Translate($y);
190
$this->ticks_pos[]=$ys;
191
$this->ticklabels_pos[]=$ys;
192
if( $count % 10 == 0 ) {
193
if( !$this->supress_tickmarks ) {
194
if( $this->majcolor!="" ) {
195
$img->PushColor($this->majcolor);
196
$img->Line($pos,$ys,$a2,$ys);
200
$img->Line($pos,$ys,$a2,$ys);
203
$this->maj_ticks_pos[$i]=$ys;
204
$this->maj_ticklabels_pos[$i]=$ys;
206
if( $this->label_formfunc != '' ) {
207
$f = $this->label_formfunc;
208
$this->maj_ticks_label[$i]=call_user_func($f,$nextMajor);
210
elseif( $this->label_logtype == 0 )
211
$this->maj_ticks_label[$i]=$nextMajor;
213
$this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));
220
if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
221
if( $this->mincolor!="" ) $img->PushColor($this->mincolor);
222
$img->Line($pos,$ys,$a,$ys);
223
if( $this->mincolor!="" ) $img->PopColor();
229
$a=$pos - $this->direction*$this->GetMinTickAbsSize();
230
$a2=$pos - $this->direction*$this->GetMajTickAbsSize();
232
$this->maj_ticks_pos[0]=$scale->Translate($start);
233
$this->maj_ticklabels_pos[0]=$scale->Translate($start);
234
if( $this->supress_first )
235
$this->maj_ticks_label[0]="";
237
if( $this->label_formfunc != '' ) {
238
$f = $this->label_formfunc;
239
$this->maj_ticks_label[0]=call_user_func($f,$start);
241
elseif( $this->label_logtype == 0 )
242
$this->maj_ticks_label[0]=$start;
244
$this->maj_ticks_label[0]='10^'.round(log10($start));
247
for($x=$start; $x<=$limit; $x+=$step,++$count ) {
248
$xs=$scale->Translate($x);
249
$this->ticks_pos[]=$xs;
250
$this->ticklabels_pos[]=$xs;
251
if( $count % 10 == 0 ) {
252
if( !$this->supress_tickmarks ) {
253
$img->Line($xs,$pos,$xs,$a2);
255
$this->maj_ticks_pos[$i]=$xs;
256
$this->maj_ticklabels_pos[$i]=$xs;
258
if( $this->label_formfunc != '' ) {
259
$f = $this->label_formfunc;
260
$this->maj_ticks_label[$i]=call_user_func($f,$nextMajor);
262
elseif( $this->label_logtype == 0 )
263
$this->maj_ticks_label[$i]=$nextMajor;
265
$this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));
272
if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
273
$img->Line($xs,$pos,$xs,$a);
b'\\ No newline at end of file'