Skip to content

Commit 76599aa

Browse files
committed
faceted stacks
1 parent 5998da3 commit 76599aa

File tree

1 file changed

+52
-34
lines changed

1 file changed

+52
-34
lines changed

src/transforms/stack.js

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ export function stackY(data, {x, y, z, zOrder, offset, ...options}) {
1111
const Y = valueof(data, y);
1212
const n = X.length;
1313
const I = range(n);
14-
const Yp = new InternMap();
15-
const Yn = new InternMap();
1614
const Y1 = new Float64Array(n);
1715
const Y2 = new Float64Array(n);
1816

@@ -23,41 +21,61 @@ export function stackY(data, {x, y, z, zOrder, offset, ...options}) {
2321
I.sort((i, j) => ascending(Z[i], Z[j]));
2422
}
2523

26-
// stack
27-
for (const i of I) {
28-
const k = X[i];
29-
const v = +Y[i];
30-
const [Y0, ceil, floor] = v < 0 ? [Yn, Y1, Y2] : [Yp ,Y2, Y1];
31-
const y1 = floor[i] = Y0.has(k) ? Y0.get(k) : 0;
32-
const y2 = ceil[i] = y1 + +Y[i];
33-
Y0.set(k, isNaN(y2) ? y1 : y2);
34-
}
35-
36-
// offset
37-
if (offset === "expand") {
38-
for (const i of I) {
39-
const k = X[i];
40-
const floor = Yn.has(k) ? Yn.get(k) : 0;
41-
const ceil = Yp.has(k) ? Yp.get(k) : 0;
42-
const m = 1 / (ceil - floor || 1);
43-
Y1[i] = m * (-floor + Y1[i]);
44-
Y2[i] = m * (-floor + Y2[i]);
45-
}
46-
}
47-
if (offset === "silhouette") {
48-
for (const i of I) {
49-
const k = X[i];
50-
const floor = Yn.has(k) ? Yn.get(k) : 0;
51-
const ceil = Yp.has(k) ? Yp.get(k) : 0;
52-
const m = (ceil + floor) / 2;
53-
Y1[i] -= m;
54-
Y2[i] -= m;
24+
const transform = (data, facets) => {
25+
const index = [];
26+
for (const facet of (facets === undefined ? [I] : facets)) {
27+
const Yp = new InternMap();
28+
const Yn = new InternMap();
29+
30+
// stack
31+
for (const i of facet) {
32+
const k = X[i];
33+
const v = +Y[i];
34+
const [Y0, ceil, floor] = v < 0 ? [Yn, Y1, Y2] : [Yp ,Y2, Y1];
35+
const y1 = floor[i] = Y0.has(k) ? Y0.get(k) : 0;
36+
const y2 = ceil[i] = y1 + +Y[i];
37+
Y0.set(k, isNaN(y2) ? y1 : y2);
38+
}
39+
40+
// offset
41+
if (offset === "expand") {
42+
for (const i of facet) {
43+
const k = X[i];
44+
const floor = Yn.has(k) ? Yn.get(k) : 0;
45+
const ceil = Yp.has(k) ? Yp.get(k) : 0;
46+
const m = 1 / (ceil - floor || 1);
47+
Y1[i] = m * (-floor + Y1[i]);
48+
Y2[i] = m * (-floor + Y2[i]);
49+
}
50+
}
51+
if (offset === "silhouette") {
52+
for (const i of facet) {
53+
const k = X[i];
54+
const floor = Yn.has(k) ? Yn.get(k) : 0;
55+
const ceil = Yp.has(k) ? Yp.get(k) : 0;
56+
const m = (ceil + floor) / 2;
57+
Y1[i] -= m;
58+
Y2[i] -= m;
59+
}
60+
}
61+
// todo "wiggle"
62+
63+
index.push(facet);
5564
}
56-
}
57-
// todo "wiggle"
65+
66+
return {index: facets === undefined ? I : index, data};
67+
};
5868

5969
const ym = Y1.map((y1, i) => (y1 + Y2[i]) / 2);
60-
return [data, {...options, x: maybeLabel(X, x), y1: maybeLabel(Y1, y), y2: Y2, ym, z}];
70+
return [data, {
71+
...options,
72+
transform,
73+
x: maybeLabel(X, x),
74+
y1: maybeLabel(Y1, y),
75+
y2: Y2,
76+
ym,
77+
z
78+
}];
6179
}
6280

6381
// If x is a labeled value, propagate the label to the returned value array.

0 commit comments

Comments
 (0)