Skip to content

Commit

Permalink
Add scaleRadial. Fixes #90.
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Sep 2, 2019
1 parent d021b63 commit e7b8f15
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/index.js
Expand Up @@ -29,6 +29,10 @@ export {
sqrt as scaleSqrt
} from "./pow.js";

export {
default as scaleRadial
} from "./radial.js";

export {
default as scaleQuantile
} from "./quantile.js";
Expand Down
51 changes: 51 additions & 0 deletions src/radial.js
@@ -0,0 +1,51 @@
import linear, {linearish} from "./linear.js";
import number from "./number.js";

function square(x) {
return (x < 0 ? -1 : 1) * x * x;
}

function unsquare(x) {
return (x < 0 ? -1 : 1) * Math.sqrt(Math.abs(x));
}

export default function radial() {
var squared = linear(),
range = [0, 1],
round = false;

function scale(x) {
var y = unsquare(squared(x));
return round ? Math.round(y) : y;
}

scale.invert = function(y) {
return squared.invert(square(y));
};

scale.domain = function(_) {
return arguments.length ? (squared.domain(_), scale) : squared.domain();
};

scale.range = function(_) {
return arguments.length ? (squared.range((range = Array.from(_, number)).map(square)), scale) : range.slice();
};

scale.round = function(_) {
return arguments.length ? (round = !!_, scale) : round;
};

scale.clamp = function(_) {
return arguments.length ? (squared.clamp(_), scale) : squared.clamp();
};

scale.copy = function() {
return radial()
.domain(squared.domain())
.range(range)
.round(round)
.clamp(squared.clamp());
};

return linearish(scale);
}
50 changes: 50 additions & 0 deletions test/radial-test.js
@@ -0,0 +1,50 @@
var tape = require("tape"),
scale = require("../");

tape("scaleRadial() has the expected defaults", function(test) {
var s = scale.scaleRadial();
test.deepEqual(s.domain(), [0, 1]);
test.deepEqual(s.range(), [0, 1]);
test.equal(s.clamp(), false);
test.equal(s.round(), false);
test.end();
});

tape("radial(x) maps a domain value x to a range value y", function(test) {
test.equal(scale.scaleRadial().range([1, 2])(0.5), 1.5811388300841898);
test.end();
});

tape("radial(x) ignores extra range values if the domain is smaller than the range", function(test) {
test.equal(scale.scaleRadial().domain([-10, 0]).range([2, 3, 4]).clamp(true)(-5), 2.5495097567963922);
test.equal(scale.scaleRadial().domain([-10, 0]).range([2, 3, 4]).clamp(true)(50), 3);
test.end();
});

tape("radial(x) ignores extra domain values if the range is smaller than the domain", function(test) {
test.equal(scale.scaleRadial().domain([-10, 0, 100]).range([2, 3]).clamp(true)(-5), 2.5495097567963922);
test.equal(scale.scaleRadial().domain([-10, 0, 100]).range([2, 3]).clamp(true)(50), 3);
test.end();
});

tape("radial(x) maps an empty domain to the middle of the range", function(test) {
test.equal(scale.scaleRadial().domain([0, 0]).range([1, 2])(0), 1.5811388300841898);
test.equal(scale.scaleRadial().domain([0, 0]).range([2, 1])(1), 1.5811388300841898);
test.end();
});

tape("radial(x) can map a bilinear domain with two values to the corresponding range", function(test) {
var s = scale.scaleRadial().domain([1, 2]);
test.deepEqual(s.domain(), [1, 2]);
test.equal(s(0.5), -0.7071067811865476);
test.equal(s(1.0), 0.0);
test.equal(s(1.5), 0.7071067811865476);
test.equal(s(2.0), 1.0);
test.equal(s(2.5), 1.224744871391589);
test.equal(s.invert(-0.5), 0.75);
test.equal(s.invert( 0.0), 1.0);
test.equal(s.invert( 0.5), 1.25);
test.equal(s.invert( 1.0), 2.0);
test.equal(s.invert( 1.5), 3.25);
test.end();
});

0 comments on commit e7b8f15

Please sign in to comment.