|
import {bisect} from "d3-array"; |
|
import {interpolate as interpolateValue, interpolateNumber, interpolateRound} from "d3-interpolate"; |
|
import constant from "./constant.js"; |
|
import number from "./number.js"; |
|
|
|
var unit = [0, 1]; |
|
|
|
export function identity(x) { |
|
return x; |
|
} |
|
|
|
function normalize(a, b) { |
|
return (b -= (a = +a)) |
|
? function(x) { return (x - a) / b; } |
|
: constant(isNaN(b) ? NaN : 0.5); |
|
} |
|
|
|
function clamper(a, b) { |
|
var t; |
|
if (a > b) t = a, a = b, b = t; |
|
return function(x) { return Math.max(a, Math.min(b, x)); }; |
|
} |
|
|
|
|
|
|
|
function bimap(domain, range, interpolate) { |
|
var d0 = domain[0], d1 = domain[1], r0 = range[0], r1 = range[1]; |
|
if (d1 < d0) d0 = normalize(d1, d0), r0 = interpolate(r1, r0); |
|
else d0 = normalize(d0, d1), r0 = interpolate(r0, r1); |
|
return function(x) { return r0(d0(x)); }; |
|
} |
|
|
|
function polymap(domain, range, interpolate) { |
|
var j = Math.min(domain.length, range.length) - 1, |
|
d = new Array(j), |
|
r = new Array(j), |
|
i = -1; |
|
|
|
|
|
if (domain[j] < domain[0]) { |
|
domain = domain.slice().reverse(); |
|
range = range.slice().reverse(); |
|
} |
|
|
|
while (++i < j) { |
|
d[i] = normalize(domain[i], domain[i + 1]); |
|
r[i] = interpolate(range[i], range[i + 1]); |
|
} |
|
|
|
return function(x) { |
|
var i = bisect(domain, x, 1, j) - 1; |
|
return r[i](d[i](x)); |
|
}; |
|
} |
|
|
|
export function copy(source, target) { |
|
return target |
|
.domain(source.domain()) |
|
.range(source.range()) |
|
.interpolate(source.interpolate()) |
|
.clamp(source.clamp()) |
|
.unknown(source.unknown()); |
|
} |
|
|
|
export function transformer() { |
|
var domain = unit, |
|
range = unit, |
|
interpolate = interpolateValue, |
|
transform, |
|
untransform, |
|
unknown, |
|
clamp = identity, |
|
piecewise, |
|
output, |
|
input; |
|
|
|
function rescale() { |
|
var n = Math.min(domain.length, range.length); |
|
if (clamp !== identity) clamp = clamper(domain[0], domain[n - 1]); |
|
piecewise = n > 2 ? polymap : bimap; |
|
output = input = null; |
|
return scale; |
|
} |
|
|
|
function scale(x) { |
|
return x == null || isNaN(x = +x) ? unknown : (output || (output = piecewise(domain.map(transform), range, interpolate)))(transform(clamp(x))); |
|
} |
|
|
|
scale.invert = function(y) { |
|
return clamp(untransform((input || (input = piecewise(range, domain.map(transform), interpolateNumber)))(y))); |
|
}; |
|
|
|
scale.domain = function(_) { |
|
return arguments.length ? (domain = Array.from(_, number), rescale()) : domain.slice(); |
|
}; |
|
|
|
scale.range = function(_) { |
|
return arguments.length ? (range = Array.from(_), rescale()) : range.slice(); |
|
}; |
|
|
|
scale.rangeRound = function(_) { |
|
return range = Array.from(_), interpolate = interpolateRound, rescale(); |
|
}; |
|
|
|
scale.clamp = function(_) { |
|
return arguments.length ? (clamp = _ ? true : identity, rescale()) : clamp !== identity; |
|
}; |
|
|
|
scale.interpolate = function(_) { |
|
return arguments.length ? (interpolate = _, rescale()) : interpolate; |
|
}; |
|
|
|
scale.unknown = function(_) { |
|
return arguments.length ? (unknown = _, scale) : unknown; |
|
}; |
|
|
|
return function(t, u) { |
|
transform = t, untransform = u; |
|
return rescale(); |
|
}; |
|
} |
|
|
|
export default function continuous() { |
|
return transformer()(identity, identity); |
|
} |
|
|