# Commits

committed f71c9c3

Added algorithm to compute nice tick intervals when number of ticks is specified. Now working.

• Participants
• Parent commits 3e312c6

# File src/jqplot.linearTickGenerator.js

`     };`
` `
`     // This will return an interval of form 2 * 10^n, 5 * 10^n or 10 * 10^n`
`+    // it is based soley on the range and number of ticks.  So if user specifies`
`+    // number of ticks, use this.`
`+    function bestInterval(range, numberTicks) {`
`+        var minimum = range / (numberTicks - 1);`
`+        var magnitude = Math.pow(10, Math.floor(Math.log(minimum) / Math.LN10));`
`+        var residual = minimum / magnitude;`
`+        var interval;`
`+        // "nicest" ranges are 1, 2, 5 or powers of these.`
`+        if (magnitude < 100) {`
`+            if (residual > 5) {`
`+                interval = 10 * magnitude;`
`+            }`
`+            else if (residual > 2) {`
`+                interval = 5 * magnitude;`
`+            }`
`+            else if (residual > 1) {`
`+                interval = 2 * magnitude;`
`+            }`
`+            else {`
`+                interval = magnitude;`
`+            }`
`+        }`
`+        // for large ranges, allow intervals like 300, 400 or powers of these.`
`+        // this helps a lot with poor choices for number of ticks. `
`+        else {`
`+            if (residual > 5) {`
`+                interval = 10 * magnitude;`
`+            }`
`+            else if (residual > 4) {`
`+                interval = 5 * magnitude;`
`+            }`
`+            else if (residual > 3) {`
`+                interval = 4 * magnitude;`
`+            }`
`+            else if (residual > 2) {`
`+                interval = 3 * magnitude;`
`+            }`
`+            else if (residual > 1) {`
`+                interval = 2 * magnitude;`
`+            }`
`+            else {`
`+                interval = magnitude;`
`+            }`
`+        }`
`+`
`+        return interval;`
`+    }`
`+`
`+    // This will return an interval of form 2 * 10^n, 5 * 10^n or 10 * 10^n`
`+    // it is based soley on the range of data, number of ticks must be computed later.`
`     function bestLinearInterval(range, scalefact) {`
`         var expv = Math.floor(Math.log(range)/Math.LN10);`
`         var magnitude = Math.pow(10, expv);`
`         return fact*magnitude; `
`     }`
` `
`-    // This will return an interval of form 2 * 10^n, 5 * 10^n or 10 * 10^n`
`     function bestLinearComponents(range, scalefact) {`
`         var expv = Math.floor(Math.log(range)/Math.LN10);`
`         var magnitude = Math.pow(10, expv);`
`         }`
` `
`         var r = [];`
`+        var ss = bestLinearInterval(axis_max - axis_min, scalefact);`
`         `
`         if (numberTicks === undefined) {`
`-            var ss = bestLinearInterval(axis_max - axis_min, scalefact);`
` `
`             // Figure out the axis min, max and number of ticks`
`             // the min and max will be some multiple of the tick interval,`
`         else {`
`             // console.log('number ticks: ', numberTicks);`
`             // console.log('axis_min: %s, axis_max: %s', axis_min, axis_max);`
`-            var ss = bestLinearInterval(axis_max - axis_min, scalefact);`
`             var tempr = [];`
` `
`             // Figure out the axis min, max and number of ticks`
` `
`             // console.log('tempr: ', tempr);`
` `
`+            // first, see if we happen to get the right number of ticks`
`             if (tempr[2] === numberTicks) {`
`                 r = tempr;`
`             }`
` `
`             else {`
`-                // returns interval, factor, magnitude`
`-                var c = bestLinearComponents(axis_max - axis_min, scalefact);`
`-                var m = Math;`
` `
`-                // var mag = c[2];`
`-                // var magExp = Math.floor(Math.log(mag)/Math.LN10);`
`+                var newti = bestInterval(tempr[1] - tempr[0], numberTicks);`
`+                // console.log('new ti: ', newti);`
` `
`-                // get an exact tick interval`
`-                var exactti = (axis_max - axis_min) / (numberTicks - 1);`
`-                var exacttiExp = Math.floor(Math.log(exactti)/Math.LN10);`
`-`
`-                // approximate where the new min will be`
`-                // var temp_min = Math.floor(axis_min / exactti) * exactti;`
`-                // var temp_min = Math.floor(axis_min / Math.pow(10, exacttiExp)) * Math.powexactti;`
`-`
`-                var minExp = m.floor(m.log(axis_min)/m.LN10);`
`-                var maxExp = m.floor(m.log(axis_max)/m.LN10);`
`-`
`-                // console.log('minExp: %s, exacttiExp: %s', minExp, exacttiExp);`
`-`
`-                minExp = minExp > 0 ? minExp : minExp + 1;`
`-                // exacttiExp = exacttiExp > 0 ? exacttiExp : exacttiExp + 1;`
`-                // var tempmin = m.floor(axis_min/m.pow(10, minExp)) * m.pow(10, minExp);`
`-                var tempmin = m.floor(axis_min/m.pow(10, exacttiExp)) * m.pow(10, exacttiExp);`
`-                var tempmax = m.ceil(axis_max/m.pow(10, maxExp-1)) * m.pow(10, maxExp-1);`
`-                var tempmax = m.ceil(axis_max/m.pow(10, exacttiExp)) * m.pow(10, exacttiExp);`
`-`
`-                // var tti = (axis_max - temp_min) / (numberTicks - 1);`
`-                var tti = (tempmax - tempmin) / (numberTicks - 1);`
`-`
`-                var ttiExp = Math.floor(Math.log(tti)/Math.LN10);`
`-`
`-                // var precisionExp = (ttiExp > 0) ? ttiExp - 1 : ttiExp; //magExp - 1 - ttiExp;`
`-`
`-                // var tempti = tti * Math.pow(10, precisionExp);`
`-`
`-                if (ttiExp < 0) {`
`-                    var newti = Math.ceil(tti/Math.pow(10, ttiExp)) * Math.pow(10, ttiExp);`
`-                }`
`-                // else if (ttiExp < 2) {`
`-                //     var newti = Math.ceil(tti);`
`-                // }`
`-                else {`
`-                    var newti = Math.ceil(tti/Math.pow(10, ttiExp-1)) * Math.pow(10, ttiExp-1);`
`-                }`
`-                // var newti = Math.ceil(tti/Math.pow(10, ttiExp-1)) * Math.pow(10, ttiExp-1);`
`-`
`-                // console.log('tempmin: %s, range: %s, exactti: %s, tti: %s, ttiExp: %s, newti: %s', temp_min, axis_max-temp_min, exactti, tti, ttiExp, newti);`
`-                // console.log('tempmin: %s, minExp: %s, tempmax: %s, maxExp: %s, exacttiExp: %s, tti: %s, newti: %s', tempmin, minExp, tempmax, maxExp, exacttiExp, tti, newti);`
`-`
`+                r[0] = tempr[0];`
`+                r[2] = numberTicks;`
`                 r[4] = newti;`
`-                // r[0] = Math.floor(axis_min/r[4]) * r[4];`
`-                // r[0] = Math.floor(axis_min / Math.pow(10, ttiExp)) * Math.pow(10, ttiExp);`
`-                r[0] = tempmin;`
`-                r[2] = numberTicks;`
`-                r[3] = bestFormatString(r[4]);`
`+                r[3] = bestFormatString(newti);`
`                 r[1] = r[0] + (r[2] - 1) * r[4];        // max`
`-                `
`             }`
`-`
`-            // Not enough ticks, add some`
`-            // else if (tempr[2] < numberTicks) {`
`-            //     console.log('too few');`
`-            //     // returns interval, factor, magnitude`
`-            //     var c = bestLinearComponents(axis_max - axis_min, scalefact);`
`-            //     console.log('max: %s, min: %s, scale: %s', axis_max, axis_min, scalefact);`
`-            //     console.log('interval: %s, factor: %s, magnitude: %s', c[0], c[1], c[2]);`
`-            //     // the offset we would get by simply adding more ticks;`
`-            //     var error = numberTicks - tempr[2] * ss;`
`-`
`-            //     var ntmult = Math.ceil(numberTicks / tempr[2]);`
`-`
`-            //     var range = tempr[1] - tempr[0];`
`-`
`-            //     var curf = c[1];`
`-            //     var curti = c[0];`
`-            //     var curnt = tempr[2];`
`-`
`-            //     var count = 0;`
`-`
`-            //     function getMoreTicks(f, mag, r) {`
`-            //         // try to adjust factor and see what we get`
`-            //         var newf = _getLowerFactor(f);`
`-            //         var newti = newf * mag;`
`-            //         var newnt = r / newti + 1;`
`-            //         // new factor, tickInterval, numberTicks`
`-            //         return [newf, newti, newnt];`
`-            //     }`
`-`
`-            //     function findMoreTicks(f, mag, r) {`
`-            //         var getMore = getMoreTicks(f, mag, r);`
`-            //         console.log('getting some more: ', getMore);`
`-`
`-            //         if (count < 2*(ntmult+1)) {`
`-            //             if (getMore[2] < numberTicks) {`
`-            //                 curf = getMore[0];`
`-            //                 curti = getMore[1];`
`-            //                 curnt = getMore[2];`
`-            //                 count++;`
`-            //                 getMore = findMoreTicks(getMore[0], mag, r);`
`-            //             }`
`-`
`-            //             else if (getMore[2] > numberTicks) {`
`-            //                 getMore = [curf, curti, curnt];`
`-            //             }`
`-            //         }`
`-`
`-            //         return getMore;`
`-            //     }`
`-`
`-            //     // Try getting more ticks at nice interval.`
`-            //     // return:`
`-            //     //          0: factor`
`-            //     //          1: tick interval`
`-            //     //          2: number ticks`
`-            //     var gotMore = findMoreTicks(c[1], c[2], range);`
`-            //     console.log('got more: ', gotMore);`
`-`
`-            //     // Have 3 conditions now.`
`-            //     //`
`-            //     // gotMore has too many ticks, add some more ticks at existing interval and expand max.`
`-            //     if (gotMore[2] > numberTicks) {`
`-            //         r[0] = Math.floor(axis_min / ss) * ss;  // min`
`-            //         r[2] = numberTicks;                     // number of ticks`
`-            //         r[3] = bestFormatString(ss);            // format string`
`-            //         r[4] = ss;                              // tick Interval`
`-            //         r[1] = r[0] + (r[2] - 1) * r[4];        // max`
`-            //     }`
`-`
`-            //     // gotMore has just enough ticks, use them.`
`-            //     else if (gotMore[2] === numberTicks) {`
`-            //         r[0] = Math.floor(axis_min / gotMore[1]) * gotMore[1];  // minimum`
`-            //         r[1] = Math.ceil(axis_max / gotMore[1]) * gotMore[1];   // maximum`
`-            //         r[2] = numberTicks;                                     // number ticks`
`-            //         r[3] = bestFormatString(gotMore[1]);                    // format string`
`-            //         r[4] = gotMore[1];                                      // tick interval`
`-            //         r[1] = r[0] + (r[2] - 1) * r[4];                        // max`
`-            //     }`
`-`
`-            //     // gotMore doesn't have enough ticks, add some at gotMore interval.`
`-            //     else {`
`-            //         r[0] = Math.floor(axis_min / gotMore[1]) * gotMore[1];  // minimum`
`-            //         r[2] = numberTicks;                                     // number of ticks`
`-            //         r[3] = bestFormatString(gotMore[1]);                    // format string`
`-            //         r[4] = gotMore[1];                                      // tick interval`
`-            //         r[1] = r[0] + (r[2] - 1) * r[4];                        // max`
`-            //     }`
`-                `
`-            // }`
`-`
`-            // // too many ticks, take away some`
`-            // else {`
`-            //     console.log('too many');`
`-            //     // returns interval, factor, magnitude`
`-            //     var c = bestLinearComponents(axis_max - axis_min, scalefact);`
`-            //     console.log('max: %s, min: %s, scale: %s', axis_max, axis_min, scalefact);`
`-            //     console.log('interval: %s, factor: %s, magnitude: %s', c[0], c[1], c[2]);`
`-            //     // the offset we would get by simply adding more ticks;`
`-            //     var error = numberTicks - tempr[2] * ss;`
`-`
`-            //     var ntmult = Math.ceil(numberTicks / tempr[2]);`
`-            //     var count = 0;`
`-`
`-            //     var range = tempr[1] - tempr[0];`
`-`
`-            //     function getLessTicks(f, mag, r) {`
`-            //         // try to adjust factor and see what we get`
`-            //         var newf = _getHigherFactor(f);`
`-            //         var newti = newf * mag;`
`-            //         var newnt = Math.round(r / newti + 1);`
`-            //         // new factor, tickInterval, numberTicks`
`-            //         return [newf, newti, newnt];`
`-            //     }`
`-`
`-            //     function findLessTicks(f, mag, r) {`
`-            //         var getLess = getLessTicks(f, mag, r);`
`-            //         console.log('getting less: ', getLess);`
`-`
`-            //         if (count < 2 * (ntmult+1)) {`
`-`
`-            //             if (getLess[2] > numberTicks) {`
`-            //                 count++;`
`-            //                 getLess = findLessTicks(getLess[0], mag, r);`
`-            //             }`
`-                        `
`-            //         }`
`-`
`-            //         return  getLess;`
`-            //     }`
`-`
`-            //     // Try getting more ticks at nice interval.`
`-            //     // return:`
`-            //     //          0: factor`
`-            //     //          1: tick interval`
`-            //     //          2: number ticks`
`-            //     var gotLess = findLessTicks(c[1], c[2], range);`
`-            //     console.log('got less: ', gotLess);`
`-`
`-            //     //`
`-            //     // gotLess has too few ticks, add some more ticks at gotless interval and expand max.`
`-            //     if (gotLess[2] < numberTicks) {`
`-            //         r[0] = Math.floor(axis_min / gotLess[1]) * gotLess[1];  // min`
`-            //         r[2] = numberTicks;                     // number of ticks`
`-            //         r[3] = bestFormatString(ss);            // format string`
`-            //         r[4] = gotLess[1];                              // tick Interval`
`-            //         r[1] = r[0] + (r[2] - 1) * r[4];        // max`
`-            //     }`
`-`
`-            //     // gotLess has just enough ticks, use them.`
`-            //     else if (gotLess[2] === numberTicks) {`
`-            //         r[0] = Math.floor(axis_min / gotLess[1]) * gotLess[1];  // minimum`
`-            //         r[2] = numberTicks;                                     // number ticks`
`-            //         r[3] = bestFormatString(gotLess[1]);                    // format string`
`-            //         r[4] = gotLess[1];                                      // tick interval`
`-            //         r[1] = r[0] + (r[2] - 1) * r[4];        // max`
`-            //     }`
`-            // }`
`         }`
` `
`         // console.log('r is: ', r);`
`     };`
` `
`     \$.jqplot.LinearTickGenerator.bestLinearInterval = bestLinearInterval;`
`+    \$.jqplot.LinearTickGenerator.bestInterval = bestInterval;`
`     \$.jqplot.LinearTickGenerator.bestLinearComponents = bestLinearComponents;`
` `
` })(jQuery);`