

class TickScale {

    private minPoint: number;
    private maxPoint: number;
    private maxTicks: number;
    private tickSpacing: number;
    private range: number;
    private tickMin: number;
    private tickMax: number;

    /*
    constructor(min: number, max: number, ticks: number) {
        this.minPoint = min;
        this.maxPoint = max;
        this.maxTicks = ticks;
        this.calculate();
    }
    */

    public getTickSpacing() {
        return this.tickSpacing;
    }

    public getRoundedMin() {
        return this.tickMin;
    }

    public getRoundedMax() {
        return this.tickMax;
    }

        private calculate() {
            this.range = this.niceNum(this.maxPoint - this.minPoint, false);
            this.tickSpacing = this.niceNum(this.range / (this.maxTicks - 1), true);
            this.tickMin = Math.floor(this.minPoint / this.tickSpacing) * this.tickSpacing;
            this.tickMax = Math.ceil(this.maxPoint / this.tickSpacing) * this.tickSpacing;
        }

        private niceNum(range: number, round: boolean) {
            var exponent; /** exponent of range */
            var fraction; /** fractional part of range */
            var niceFraction; /** nice, rounded fraction */

            exponent = Math.floor(this.log10(range));
            fraction = range / Math.pow(10, exponent);

            if (round) {
                if (fraction < 1.5)
                    niceFraction = 1;
                else if (fraction < 3)
                    niceFraction = 2;
                else if (fraction < 7)
                    niceFraction = 5;
                else
                    niceFraction = 10;
            } else {
                if (fraction <= 1)
                    niceFraction = 1;
                else if (fraction <= 2)
                    niceFraction = 2;
                else if (fraction <= 5)
                    niceFraction = 5;
                else
                    niceFraction = 10;
            }
            return niceFraction * Math.pow(10, exponent);
        }

        public log10(val: number) {
            return Math.log(val) / Math.LN10;
        }


        public setMinMaxPoints(minPoint: number, maxPoint: number) {
            this.minPoint = minPoint;
            this.maxPoint = maxPoint;
            this.calculate();
        }

        public setMaxTicks(maxTicks: number) {
            this.maxTicks = maxTicks;
            this.calculate();
        }
    }