diff --git a/src/linear.js b/src/linear.js index b91f712..3617d32 100644 --- a/src/linear.js +++ b/src/linear.js @@ -19,38 +19,36 @@ export function linearish(scale) { scale.nice = function(count) { if (count == null) count = 10; - var d = domain(), - i0 = 0, - i1 = d.length - 1, - start = d[i0], - stop = d[i1], - step; + var d = domain(); + var i0 = 0; + var i1 = d.length - 1; + var start = d[i0]; + var stop = d[i1]; + var prestep; + var step; + var maxIter = 10; if (stop < start) { step = start, start = stop, stop = step; step = i0, i0 = i1, i1 = step; } - - step = tickIncrement(start, stop, count); - - if (step > 0) { - start = Math.floor(start / step) * step; - stop = Math.ceil(stop / step) * step; + + while (maxIter-- > 0) { step = tickIncrement(start, stop, count); - } else if (step < 0) { - start = Math.ceil(start * step) / step; - stop = Math.floor(stop * step) / step; - step = tickIncrement(start, stop, count); - } - - if (step > 0) { - d[i0] = Math.floor(start / step) * step; - d[i1] = Math.ceil(stop / step) * step; - domain(d); - } else if (step < 0) { - d[i0] = Math.ceil(start * step) / step; - d[i1] = Math.floor(stop * step) / step; - domain(d); + if (step === prestep) { + d[i0] = start + d[i1] = stop + return domain(d); + } else if (step > 0) { + start = Math.floor(start / step) * step; + stop = Math.ceil(stop / step) * step; + } else if (step < 0) { + start = Math.ceil(start * step) / step; + stop = Math.floor(stop * step) / step; + } else { + break; + } + prestep = step; } return scale; diff --git a/test/linear-test.js b/test/linear-test.js index 62de558..154760d 100644 --- a/test/linear-test.js +++ b/test/linear-test.js @@ -373,6 +373,36 @@ tape("linear.ticks(count) returns the expected ticks for a polylinear domain", f test.end(); }); +tape("linear.ticks(X) spans linear.nice(X).domain()", function(test) { + function check(domain, count) { + var s = scale.scaleLinear().domain(domain).nice(count); + var ticks = s.ticks(count); + test.deepEqual([ticks[0], ticks[ticks.length - 1]], s.domain()); + } + + check([1, 9], 2); + check([1, 9], 3); + check([1, 9], 4); + + check([8, 9], 2); + check([8, 9], 3); + check([8, 9], 4); + + check([1, 21], 2); + check([2, 21], 2); + check([3, 21], 2); + check([4, 21], 2); + check([5, 21], 2); + check([6, 21], 2); + check([7, 21], 2); + check([8, 21], 2); + check([9, 21], 2); + check([10, 21], 2); + check([11, 21], 2); + + test.end(); +}) + tape("linear.ticks(count) returns the empty array if count is not a positive integer", function(test) { var s = scale.scaleLinear(); test.deepEqual(s.ticks(NaN), []);