package flare.scale { import flare.util.Maths; import flare.util.Strings; /** * Scale that performs a log transformation of the data. The base of the * logarithm is determined by the base property. */ public class LogScale extends QuantitativeScale { private var _zero:Boolean = false; /** * Creates a new LogScale. * @param min the minimum data value * @param max the maximum data value * @param base the number base to use * @param flush the flush flag for scale padding * @param labelFormat the formatting pattern for value labels */ public function LogScale(min:Number=0, max:Number=0, base:Number=10, flush:Boolean=false, labelFormat:String=Strings.DEFAULT_NUMBER) { super(min, max, base, flush, labelFormat); } /** @inheritDoc */ public override function get scaleType():String { return ScaleType.LOG; } /** @inheritDoc */ public override function clone():Scale { return new LogScale(_dmin, _dmax, _base, _flush, _format); } /** @inheritDoc */ protected override function interp(val:Number):Number { if (_zero) { return Maths.invAdjLogInterp(val, _smin, _smax, _base); } else { return Maths.invLogInterp(val, _smin, _smax, _base); } } /** @inheritDoc */ public override function lookup(f:Number):Object { if (_zero) { return Maths.adjLogInterp(f, _smin, _smax, _base); } else { return Maths.logInterp(f, _smin, _smax, _base); } } /** @inheritDoc */ protected override function updateScale():void { _zero = (_dmin < 0 && _dmax > 0); if (!_flush) { _smin = Maths.logFloor(_dmin, _base); _smax = Maths.logCeil(_dmax, _base); if (_zero) { if (Math.abs(_dmin) < _base) _smin = Math.floor(_dmin); if (Math.abs(_dmax) < _base) _smax = Math.ceil(_dmax); } } else { _smin = _dmin; _smax = _dmax; } } private function log(x:Number):Number { if (_zero) { // distorts the scale to accomodate zero return Maths.adjLog(x, _base); } else { // uses a zero-symmetric logarithmic scale return Maths.symLog(x, _base); } } /** @inheritDoc */ public override function values(num:int=-1):Vector. { var vals:Vector. = new Vector.(); var beg:int = int(Math.round(log(_smin))); var end:int = int(Math.round(log(_smax))); if (beg == end && beg > 0 && Math.pow(10, beg) > _smin) { --beg; // decrement to generate more values } var i:int, j:int, b:Number, v:Number = _zero?-1:1; for (i = beg; i <= end; ++i) { if (i==0 && v<=0) { vals.push(v); vals.push(0); } v = _zero && i<0 ? -Math.pow(_base,-i) : Math.pow(_base,i); b = _zero && i<0 ? Math.pow(_base,-i-1) : v; for (j = 1; j < _base; ++j, v += b) { if (v > _smax) return vals; vals.push(v); } } return vals; } } // end of class LogScale }