Rev 5 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/*=======================================================================// File: JPGRAPH_LOG.PHP// Description: Log scale plot extension for JpGraph// Created: 2001-01-08// Ver: $Id: jpgraph_log.php 820 2006-12-14 01:04:01Z ljp $//// Copyright (c) Aditus Consulting. All rights reserved.//========================================================================*/DEFINE('LOGLABELS_PLAIN',0);DEFINE('LOGLABELS_MAGNITUDE',1);//===================================================// CLASS LogScale// Description: Logarithmic scale between world and screen//===================================================class LogScale extends LinearScale {//---------------// CONSTRUCTOR// Log scale is specified using the log of min and maxfunction LogScale($min,$max,$type="y") {$this->LinearScale($min,$max,$type);$this->ticks = new LogTicks();$this->name = 'log';}//----------------// PUBLIC METHODS// Translate between world and screenfunction Translate($a) {if( !is_numeric($a) ) {if( $a != '' && $a != '-' && $a != 'x' )JpGraphError::RaiseL(11001);//('Your data contains non-numeric values.');return 1;}if( $a < 0 ) {JpGraphError::RaiseL(11002);//("Negative data values can not be used in a log scale.");exit(1);}if( $a==0 ) $a=1;$a=log10($a);return ceil($this->off + ($a*1.0 - $this->scale[0]) * $this->scale_factor);}// Relative translate (don't include offset) usefull when we just want// to know the relative position (in pixels) on the axisfunction RelTranslate($a) {if( !is_numeric($a) ) {if( $a != '' && $a != '-' && $a != 'x' )JpGraphError::RaiseL(11001);//('Your data contains non-numeric values.');return 1;}if( $a==0 ) $a=1;$a=log10($a);return round(($a*1.0 - $this->scale[0]) * $this->scale_factor);}// Use bcpow() for increased precisionfunction GetMinVal() {if( function_exists("bcpow") )return round(bcpow(10,$this->scale[0],15),14);elsereturn round(pow(10,$this->scale[0]),14);}function GetMaxVal() {if( function_exists("bcpow") )return round(bcpow(10,$this->scale[1],15),14);elsereturn round(pow(10,$this->scale[1]),14);}// Logarithmic autoscaling is much simplier since we just// set the min and max to logs of the min and max values.// Note that for log autoscale the "maxstep" the fourth argument// isn't used. This is just included to give the method the same// signature as the linear counterpart.function AutoScale(&$img,$min,$max,$dummy) {if( $min==0 ) $min=1;if( $max <= 0 ) {JpGraphError::RaiseL(11004);//('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.');}if( is_numeric($this->autoscale_min) ) {$smin = round($this->autoscale_min);$smax = ceil(log10($max));if( $min >= $max ) {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.');}}else {$smin = floor(log10($min));if( is_numeric($this->autoscale_max) ) {$smax = round($this->autoscale_max);if( $smin >= $smax ) {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.');}}else$smax = ceil(log10($max));}$this->Update($img,$smin,$smax);}//---------------// PRIVATE METHODS} // Class//===================================================// CLASS LogTicks// Description://===================================================class LogTicks extends Ticks{var $label_logtype=LOGLABELS_MAGNITUDE;//---------------// CONSTRUCTORfunction LogTicks() {}//---------------// PUBLIC METHODSfunction IsSpecified() {return true;}function SetLabelLogType($aType) {$this->label_logtype = $aType;}// For log scale it's meaningless to speak about a major step// We just return -1 to make the framework happy (specifically// StrokeLabels() )function GetMajor() {return -1;}function SetTextLabelStart($aStart) {JpGraphError::RaiseL(11005);//('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.');}function SetXLabelOffset($dummy) {// For log scales we dont care about XLabel offset}// Draw ticks on image "img" using scale "scale". The axis absolute// position in the image is specified in pos, i.e. for an x-axis// it specifies the absolute y-coord and for Y-ticks it specified the// absolute x-position.function Stroke(&$img,&$scale,$pos) {$start = $scale->GetMinVal();$limit = $scale->GetMaxVal();$nextMajor = 10*$start;$step = $nextMajor / 10.0;$img->SetLineWeight($this->weight);if( $scale->type == "y" ) {// member direction specified if the ticks should be on// left or right side.$a=$pos + $this->direction*$this->GetMinTickAbsSize();$a2=$pos + $this->direction*$this->GetMajTickAbsSize();$count=1;$this->maj_ticks_pos[0]=$scale->Translate($start);$this->maj_ticklabels_pos[0]=$scale->Translate($start);if( $this->supress_first )$this->maj_ticks_label[0]="";else {if( $this->label_formfunc != '' ) {$f = $this->label_formfunc;$this->maj_ticks_label[0]=call_user_func($f,$start);}elseif( $this->label_logtype == LOGLABELS_PLAIN )$this->maj_ticks_label[0]=$start;else$this->maj_ticks_label[0]='10^'.round(log10($start));}$i=1;for($y=$start; $y<=$limit; $y+=$step,++$count ) {$ys=$scale->Translate($y);$this->ticks_pos[]=$ys;$this->ticklabels_pos[]=$ys;if( $count % 10 == 0 ) {if( !$this->supress_tickmarks ) {if( $this->majcolor!="" ) {$img->PushColor($this->majcolor);$img->Line($pos,$ys,$a2,$ys);$img->PopColor();}else$img->Line($pos,$ys,$a2,$ys);}$this->maj_ticks_pos[$i]=$ys;$this->maj_ticklabels_pos[$i]=$ys;if( $this->label_formfunc != '' ) {$f = $this->label_formfunc;$this->maj_ticks_label[$i]=call_user_func($f,$nextMajor);}elseif( $this->label_logtype == 0 )$this->maj_ticks_label[$i]=$nextMajor;else$this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));++$i;$nextMajor *= 10;$step *= 10;$count=1;}else {if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {if( $this->mincolor!="" ) $img->PushColor($this->mincolor);$img->Line($pos,$ys,$a,$ys);if( $this->mincolor!="" ) $img->PopColor();}}}}else {$a=$pos - $this->direction*$this->GetMinTickAbsSize();$a2=$pos - $this->direction*$this->GetMajTickAbsSize();$count=1;$this->maj_ticks_pos[0]=$scale->Translate($start);$this->maj_ticklabels_pos[0]=$scale->Translate($start);if( $this->supress_first )$this->maj_ticks_label[0]="";else {if( $this->label_formfunc != '' ) {$f = $this->label_formfunc;$this->maj_ticks_label[0]=call_user_func($f,$start);}elseif( $this->label_logtype == 0 )$this->maj_ticks_label[0]=$start;else$this->maj_ticks_label[0]='10^'.round(log10($start));}$i=1;for($x=$start; $x<=$limit; $x+=$step,++$count ) {$xs=$scale->Translate($x);$this->ticks_pos[]=$xs;$this->ticklabels_pos[]=$xs;if( $count % 10 == 0 ) {if( !$this->supress_tickmarks ) {$img->Line($xs,$pos,$xs,$a2);}$this->maj_ticks_pos[$i]=$xs;$this->maj_ticklabels_pos[$i]=$xs;if( $this->label_formfunc != '' ) {$f = $this->label_formfunc;$this->maj_ticks_label[$i]=call_user_func($f,$nextMajor);}elseif( $this->label_logtype == 0 )$this->maj_ticks_label[$i]=$nextMajor;else$this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));++$i;$nextMajor *= 10;$step *= 10;$count=1;}else {if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {$img->Line($xs,$pos,$xs,$a);}}}}return true;}} // Class/* EOF */?>