Skip to content

Commit

Permalink
Use ticks from d3-array.
Browse files Browse the repository at this point in the history
As a side-effect, ticks are now generated in the same order as the domain. So,
if you have a descending domain, you get descending ticks, too. Yay!
  • Loading branch information
mbostock committed Dec 16, 2015
1 parent 57505b6 commit fa5db52
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 118 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"prepublish": "npm run test && uglifyjs build/d3-scale.js -c -m -o build/d3-scale.min.js && rm -f build/d3-scale.zip && zip -j build/d3-scale.zip -- LICENSE README.md build/d3-scale.js build/d3-scale.min.js"
},
"dependencies": {
"d3-array": "~0.5.1",
"d3-array": "~0.6.0",
"d3-color": "~0.3.1",
"d3-format": "~0.4.0",
"d3-interpolate": "~0.2.0",
Expand Down
18 changes: 9 additions & 9 deletions src/identity.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
import {ticks} from "d3-array";
import {map, slice} from "./array";
import number from "./number";
import tickFormat from "./tickFormat";
import ticks from "./ticks";

function newIdentity(domain) {
function identity(domain) {

function scale(x) {
return +x;
}

scale.invert = scale;

scale.domain = scale.range = function(x) {
if (!arguments.length) return domain.slice();
domain = x.map(Number);
return scale;
scale.domain = scale.range = function(_) {
return arguments.length ? (domain = map.call(_, number), scale) : domain.slice();
};

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

scale.tickFormat = function(count, specifier) {
return tickFormat(domain, count, specifier);
};

scale.copy = function() {
return newIdentity(domain);
return identity(domain);
};

return scale;
}

export default function() {
return newIdentity([0, 1]);
return identity([0, 1]);
};
19 changes: 11 additions & 8 deletions src/linear.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {ticks, tickStep} from "d3-array";
import {number as reinterpolate} from "d3-interpolate";
import nice from "./nice";
import {default as quantitative, copy, deinterpolateLinear as deinterpolate} from "./quantitative";
import tickFormat from "./tickFormat";
import ticks, {tickRange} from "./ticks";

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

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

scale.tickFormat = function(count, specifier) {
Expand All @@ -17,11 +17,14 @@ export function linearish(scale) {

scale.nice = function(count) {
var d = domain(),
k = tickRange(d, count)[2];
return k ? domain(nice(d, {
floor: function(x) { return Math.floor(x / k) * k; },
ceil: function(x) { return Math.ceil(x / k) * k; }
})) : scale;
i = d.length - 1,
k = tickStep(d[0], d[i], count == null ? 10 : count);
if (k) {
d[0] = Math.floor(d[0] / k) * k;
d[i] = Math.ceil(d[i] / k) * k;
domain(d);
}
return scale;
};

return scale;
Expand Down
26 changes: 10 additions & 16 deletions src/tickFormat.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,30 @@
import {
format,
formatPrefix,
formatSpecifier,
precisionFixed,
precisionPrefix,
precisionRound
} from "d3-format";

import {tickRange} from "./ticks";
import {tickStep} from "d3-array";
import {format, formatPrefix, formatSpecifier, precisionFixed, precisionPrefix, precisionRound} from "d3-format";

export default function(domain, count, specifier) {
var range = tickRange(domain, count);
var start = domain[0],
stop = domain[domain.length - 1],
step = tickStep(start, stop, count == null ? 10 : count);
if (specifier == null) {
specifier = ",." + precisionFixed(range[2]) + "f";
specifier = ",." + precisionFixed(step) + "f";
} else {
switch (specifier = formatSpecifier(specifier), specifier.type) {
case "s": {
var value = Math.max(Math.abs(range[0]), Math.abs(range[1]));
if (specifier.precision == null) specifier.precision = precisionPrefix(range[2], value);
var value = Math.max(Math.abs(start), Math.abs(stop));
if (specifier.precision == null) specifier.precision = precisionPrefix(step, value);
return formatPrefix(specifier, value);
}
case "":
case "e":
case "g":
case "p":
case "r": {
if (specifier.precision == null) specifier.precision = precisionRound(range[2], Math.max(Math.abs(range[0]), Math.abs(range[1]))) - (specifier.type === "e");
if (specifier.precision == null) specifier.precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))) - (specifier.type === "e");
break;
}
case "f":
case "%": {
if (specifier.precision == null) specifier.precision = precisionFixed(range[2]) - (specifier.type === "%") * 2;
if (specifier.precision == null) specifier.precision = precisionFixed(step) - (specifier.type === "%") * 2;
break;
}
}
Expand Down
34 changes: 0 additions & 34 deletions src/ticks.js

This file was deleted.

7 changes: 3 additions & 4 deletions src/time.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import {bisector} from "d3-array";
import {bisector, tickStep} from "d3-array";
import {number as reinterpolate} from "d3-interpolate";
import {year, month, week, day, hour, minute, second, millisecond} from "d3-time";
import {format} from "d3-time-format";
import nice from "./nice";
import {default as quantitative, copy, deinterpolateLinear as deinterpolate} from "./quantitative";
import {tickRange} from "./ticks";

var millisecondsPerSecond = 1000,
millisecondsPerMinute = millisecondsPerSecond * 60,
Expand Down Expand Up @@ -74,14 +73,14 @@ export function calendar(year, month, week, day, hour, minute, second, milliseco
var target = Math.abs(stop - start) / interval,
i = bisectTickIntervals(tickIntervals, target);
if (i === tickIntervals.length) {
step = tickRange([start / millisecondsPerYear, stop / millisecondsPerYear], interval)[2];
step = tickStep(start / millisecondsPerYear, stop / millisecondsPerYear, interval);
interval = year;
} else if (i) {
i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i];
step = i[1];
interval = i[0];
} else {
step = tickRange([start, stop], interval)[2];
step = tickStep(start, stop, interval);
interval = millisecond;
}
}
Expand Down
8 changes: 4 additions & 4 deletions test/identity-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ tape("identity.ticks(count) generates ticks of varying degree", function(test) {
test.deepEqual(s.ticks(5).map(s.tickFormat(5)), ["0.0", "0.2", "0.4", "0.6", "0.8", "1.0"]);
test.deepEqual(s.ticks(10).map(s.tickFormat(10)), ["0.0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0"]);
var s = scale.identity().domain([1, 0]);
test.deepEqual(s.ticks(1).map(s.tickFormat(1)), ["0", "1"]);
test.deepEqual(s.ticks(2).map(s.tickFormat(2)), ["0.0", "0.5", "1.0"]);
test.deepEqual(s.ticks(5).map(s.tickFormat(5)), ["0.0", "0.2", "0.4", "0.6", "0.8", "1.0"]);
test.deepEqual(s.ticks(10).map(s.tickFormat(10)), ["0.0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0"]);
test.deepEqual(s.ticks(1).map(s.tickFormat(1)), ["0", "1"].reverse());
test.deepEqual(s.ticks(2).map(s.tickFormat(2)), ["0.0", "0.5", "1.0"].reverse());
test.deepEqual(s.ticks(5).map(s.tickFormat(5)), ["0.0", "0.2", "0.4", "0.6", "0.8", "1.0"].reverse());
test.deepEqual(s.ticks(10).map(s.tickFormat(10)), ["0.0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0"].reverse());
test.end();
});

Expand Down
42 changes: 21 additions & 21 deletions test/linear-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,27 +279,27 @@ tape("linear.ticks(count) returns the expected ticks for an ascending domain", f

tape("linear.ticks(count) returns the expected ticks for a descending domain", function(test) {
var s = scale.linear().domain([1, 0]);
test.deepEqual(s.ticks(10).map(roundEpsilon), [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]);
test.deepEqual(s.ticks(9).map(roundEpsilon), [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]);
test.deepEqual(s.ticks(8).map(roundEpsilon), [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]);
test.deepEqual(s.ticks(7).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]);
test.deepEqual(s.ticks(6).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]);
test.deepEqual(s.ticks(5).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]);
test.deepEqual(s.ticks(4).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]);
test.deepEqual(s.ticks(3).map(roundEpsilon), [0.0, 0.5, 1.0]);
test.deepEqual(s.ticks(2).map(roundEpsilon), [0.0, 0.5, 1.0]);
test.deepEqual(s.ticks(1).map(roundEpsilon), [0.0, 1.0]);
test.deepEqual(s.ticks(10).map(roundEpsilon), [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0].reverse());
test.deepEqual(s.ticks(9).map(roundEpsilon), [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0].reverse());
test.deepEqual(s.ticks(8).map(roundEpsilon), [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0].reverse());
test.deepEqual(s.ticks(7).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0].reverse());
test.deepEqual(s.ticks(6).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0].reverse());
test.deepEqual(s.ticks(5).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0].reverse());
test.deepEqual(s.ticks(4).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0].reverse());
test.deepEqual(s.ticks(3).map(roundEpsilon), [0.0, 0.5, 1.0].reverse());
test.deepEqual(s.ticks(2).map(roundEpsilon), [0.0, 0.5, 1.0].reverse());
test.deepEqual(s.ticks(1).map(roundEpsilon), [0.0, 1.0].reverse());
s.domain([100, -100]);
test.deepEqual(s.ticks(10), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
test.deepEqual(s.ticks(9), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
test.deepEqual(s.ticks(8), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
test.deepEqual(s.ticks(7), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
test.deepEqual(s.ticks(6), [-100, -50, 0, 50, 100]);
test.deepEqual(s.ticks(5), [-100, -50, 0, 50, 100]);
test.deepEqual(s.ticks(4), [-100, -50, 0, 50, 100]);
test.deepEqual(s.ticks(3), [-100, -50, 0, 50, 100]);
test.deepEqual(s.ticks(2), [-100, 0, 100]);
test.deepEqual(s.ticks(1), [ 0 ]);
test.deepEqual(s.ticks(10), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100].reverse());
test.deepEqual(s.ticks(9), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100].reverse());
test.deepEqual(s.ticks(8), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100].reverse());
test.deepEqual(s.ticks(7), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100].reverse());
test.deepEqual(s.ticks(6), [-100, -50, 0, 50, 100].reverse());
test.deepEqual(s.ticks(5), [-100, -50, 0, 50, 100].reverse());
test.deepEqual(s.ticks(4), [-100, -50, 0, 50, 100].reverse());
test.deepEqual(s.ticks(3), [-100, -50, 0, 50, 100].reverse());
test.deepEqual(s.ticks(2), [-100, 0, 100].reverse());
test.deepEqual(s.ticks(1), [ 0 ].reverse());
test.end();
});

Expand All @@ -315,7 +315,7 @@ tape("linear.ticks(count) returns the expected ticks for a polylinear domain", f
test.deepEqual(s.ticks(3).map(roundEpsilon), [0.0, 0.5, 1.0]);
test.deepEqual(s.ticks(2).map(roundEpsilon), [0.0, 0.5, 1.0]);
test.deepEqual(s.ticks(1).map(roundEpsilon), [0.0, 1.0]);
s.domain([100, 0, -100]);
s.domain([-100, 0, 100]);
test.deepEqual(s.ticks(10), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
test.deepEqual(s.ticks(9), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
test.deepEqual(s.ticks(8), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
Expand Down
42 changes: 21 additions & 21 deletions test/pow-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -315,27 +315,27 @@ tape("pow.ticks(count) returns the expected ticks for an ascending domain", func

tape("pow.ticks(count) returns the expected ticks for a descending domain", function(test) {
var s = scale.pow().domain([1, 0]);
test.deepEqual(s.ticks(10).map(roundEpsilon), [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]);
test.deepEqual(s.ticks(9).map(roundEpsilon), [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]);
test.deepEqual(s.ticks(8).map(roundEpsilon), [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]);
test.deepEqual(s.ticks(7).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]);
test.deepEqual(s.ticks(6).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]);
test.deepEqual(s.ticks(5).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]);
test.deepEqual(s.ticks(4).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]);
test.deepEqual(s.ticks(3).map(roundEpsilon), [0.0, 0.5, 1.0]);
test.deepEqual(s.ticks(2).map(roundEpsilon), [0.0, 0.5, 1.0]);
test.deepEqual(s.ticks(1).map(roundEpsilon), [0.0, 1.0]);
test.deepEqual(s.ticks(10).map(roundEpsilon), [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0].reverse());
test.deepEqual(s.ticks(9).map(roundEpsilon), [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0].reverse());
test.deepEqual(s.ticks(8).map(roundEpsilon), [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0].reverse());
test.deepEqual(s.ticks(7).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0].reverse());
test.deepEqual(s.ticks(6).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0].reverse());
test.deepEqual(s.ticks(5).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0].reverse());
test.deepEqual(s.ticks(4).map(roundEpsilon), [0.0, 0.2, 0.4, 0.6, 0.8, 1.0].reverse());
test.deepEqual(s.ticks(3).map(roundEpsilon), [0.0, 0.5, 1.0].reverse());
test.deepEqual(s.ticks(2).map(roundEpsilon), [0.0, 0.5, 1.0].reverse());
test.deepEqual(s.ticks(1).map(roundEpsilon), [0.0, 1.0].reverse());
s.domain([100, -100]);
test.deepEqual(s.ticks(10), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
test.deepEqual(s.ticks(9), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
test.deepEqual(s.ticks(8), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
test.deepEqual(s.ticks(7), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
test.deepEqual(s.ticks(6), [-100, -50, 0, 50, 100]);
test.deepEqual(s.ticks(5), [-100, -50, 0, 50, 100]);
test.deepEqual(s.ticks(4), [-100, -50, 0, 50, 100]);
test.deepEqual(s.ticks(3), [-100, -50, 0, 50, 100]);
test.deepEqual(s.ticks(2), [-100, 0, 100]);
test.deepEqual(s.ticks(1), [ 0 ]);
test.deepEqual(s.ticks(10), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100].reverse());
test.deepEqual(s.ticks(9), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100].reverse());
test.deepEqual(s.ticks(8), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100].reverse());
test.deepEqual(s.ticks(7), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100].reverse());
test.deepEqual(s.ticks(6), [-100, -50, 0, 50, 100].reverse());
test.deepEqual(s.ticks(5), [-100, -50, 0, 50, 100].reverse());
test.deepEqual(s.ticks(4), [-100, -50, 0, 50, 100].reverse());
test.deepEqual(s.ticks(3), [-100, -50, 0, 50, 100].reverse());
test.deepEqual(s.ticks(2), [-100, 0, 100].reverse());
test.deepEqual(s.ticks(1), [ 0 ].reverse());
test.end();
});

Expand All @@ -351,7 +351,7 @@ tape("pow.ticks(count) returns the expected ticks for a polypow domain", functio
test.deepEqual(s.ticks(3).map(roundEpsilon), [0.0, 0.5, 1.0]);
test.deepEqual(s.ticks(2).map(roundEpsilon), [0.0, 0.5, 1.0]);
test.deepEqual(s.ticks(1).map(roundEpsilon), [0.0, 1.0]);
s.domain([100, 0, -100]);
s.domain([-100, 0, 100]);
test.deepEqual(s.ticks(10), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
test.deepEqual(s.ticks(9), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
test.deepEqual(s.ticks(8), [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100]);
Expand Down

0 comments on commit fa5db52

Please sign in to comment.