Skip to content

Commit

Permalink
Ensure that niced domains always span ticks
Browse files Browse the repository at this point in the history
fixes d3#209
  • Loading branch information
domoritz committed May 20, 2020
1 parent 732ed4b commit 694ed8f
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 33 deletions.
62 changes: 29 additions & 33 deletions src/linear.js
Expand Up @@ -4,63 +4,59 @@ import {initRange} from "./init.js";
import tickFormat from "./tickFormat.js";

export function linearish(scale) {
var domain = scale.domain;
const domain = scale.domain;

scale.ticks = function(count) {
var d = domain();
const d = domain();
return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
};

scale.tickFormat = function(count, specifier) {
var d = domain();
const d = domain();
return tickFormat(d[0], d[d.length - 1], count == null ? 10 : count, specifier);
};

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;
const d = domain();
let i0 = 0;
let i1 = d.length - 1;
let start = d[i0];
let stop = d[i1];
let prestep;
let step;

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;
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);

// eslint-disable-next-line no-constant-condition
while (true) {
const step = tickIncrement(start, stop, count);
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 {
return scale;
}
prestep = step;
}

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);
}

return scale;
};

return scale;
}

export default function linear() {
var scale = continuous();
const scale = continuous();

scale.copy = function() {
return copy(scale, linear());
Expand Down
30 changes: 30 additions & 0 deletions test/linear-test.js
Expand Up @@ -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), []);
Expand Down

0 comments on commit 694ed8f

Please sign in to comment.