ticks = new LogTicks(); $this->name = 'log'; } //---------------- // PUBLIC METHODS // Translate between world and screen function 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 axis function 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 precision function GetMinVal() { if( function_exists("bcpow") ) { return round(bcpow(10,$this->scale[0],15),14); } else { return round(pow(10,$this->scale[0]),14); } } function GetMaxVal() { if( function_exists("bcpow") ) { return round(bcpow(10,$this->scale[1],15),14); } else { return 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,$maxsteps,$majend=true) { 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{ private $label_logtype=LOGLABELS_MAGNITUDE; private $ticklabels_pos = array(); //--------------- // CONSTRUCTOR function LogTicks() { } //--------------- // PUBLIC METHODS function 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 */ ?>