|
| 1 | +import {valueof} from "../mark"; |
| 2 | + |
| 3 | +// TODO configurable series order |
| 4 | +export function stackX(data, {x, y, ...options}) { |
| 5 | + const X = valueof(data, x); |
| 6 | + const Y = valueof(data, y); |
| 7 | + const n = X.length; |
| 8 | + const X0 = new Map(); |
| 9 | + const X1 = new Float64Array(n); |
| 10 | + const X2 = new Float64Array(n); |
| 11 | + for (let i = 0; i < n; ++i) { |
| 12 | + const k = Y[i] && Y[i].valueOf(); |
| 13 | + const x1 = X1[i] = X0.has(k) ? X0.get(k) : 0; |
| 14 | + const x2 = X2[i] = x1 + +X[i]; |
| 15 | + X0.set(k, isNaN(x2) ? x1 : x2); |
| 16 | + } |
| 17 | + return [data, {...options, x1: maybeLabel(X1, x), x2: X2, y: maybeLabel(Y, y)}]; |
| 18 | +} |
| 19 | + |
| 20 | +// TODO configurable series order |
| 21 | +export function stackY(data, {x, y, ...options}) { |
| 22 | + const X = valueof(data, x); |
| 23 | + const Y = valueof(data, y); |
| 24 | + const n = X.length; |
| 25 | + const Y0 = new Map(); |
| 26 | + const Y1 = new Float64Array(n); |
| 27 | + const Y2 = new Float64Array(n); |
| 28 | + for (let i = 0; i < n; ++i) { |
| 29 | + const k = X[i] && X[i].valueOf(); |
| 30 | + const y1 = Y1[i] = Y0.has(k) ? Y0.get(k) : 0; |
| 31 | + const y2 = Y2[i] = y1 + +Y[i]; |
| 32 | + Y0.set(k, isNaN(y2) ? y1 : y2); |
| 33 | + } |
| 34 | + return [data, {...options, x: maybeLabel(X, x), y1: maybeLabel(Y1, y), y2: Y2}]; |
| 35 | +} |
| 36 | + |
| 37 | +// If x is a labeled value, propagate the label to the returned value array. |
| 38 | +function maybeLabel(X, x) { |
| 39 | + const label = typeof x === "string" ? x : x ? x.label : undefined; |
| 40 | + if (label !== undefined) X.label = label; |
| 41 | + return X; |
| 42 | +} |
0 commit comments