Skip to content

Commit 6530773

Browse files
committed
Add d3.layout.stack, d3.min, d3.max.
1 parent 473ee4f commit 6530773

13 files changed

Lines changed: 435 additions & 200 deletions

File tree

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ d3.core.js: \
3333
src/core/functor.js \
3434
src/core/ascending.js \
3535
src/core/descending.js \
36+
src/core/min.js \
37+
src/core/max.js \
3638
src/core/nest.js \
3739
src/core/keys.js \
3840
src/core/values.js \
@@ -83,6 +85,7 @@ d3.layout.js: \
8385
src/start.js \
8486
src/layout/layout.js \
8587
src/layout/chord.js \
88+
src/layout/stack.js \
8689
src/end.js
8790

8891
d3.geo.js: \

d3.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(function(){d3 = {version: "0.29.1"}; // semver
1+
(function(){d3 = {version: "0.29.2"}; // semver
22
if (!Date.now) Date.now = function() {
33
return +new Date();
44
};
@@ -19,6 +19,32 @@ d3.ascending = function(a, b) {
1919
d3.descending = function(a, b) {
2020
return b < a ? -1 : b > a ? 1 : 0;
2121
};
22+
d3.min = function(array, f) {
23+
var i = 0,
24+
n = array.length,
25+
a = array[0],
26+
b;
27+
if (arguments.length == 1) {
28+
while (++i < n) if (a > (b = array[i])) a = b;
29+
} else {
30+
a = f(array[0]);
31+
while (++i < n) if (a > (b = f(array[i]))) a = b;
32+
}
33+
return a;
34+
};
35+
d3.max = function(array, f) {
36+
var i = 0,
37+
n = array.length,
38+
a = array[0],
39+
b;
40+
if (arguments.length == 1) {
41+
while (++i < n) if (a < (b = array[i])) a = b;
42+
} else {
43+
a = f(a);
44+
while (++i < n) if (a < (b = f(array[i]))) a = b;
45+
}
46+
return a;
47+
};
2248
d3.nest = function() {
2349
var nest = {},
2450
keys = [],

d3.layout.js

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,167 @@ d3.layout.chord = function() {
150150

151151
return chord;
152152
};
153+
// data is two-dimensional array of x,y; we populate y0
154+
// TODO perhaps make the `x`, `y` and `y0` structure customizable
155+
d3.layout.stack = function() {
156+
var order = "default",
157+
offset = "zero";
158+
159+
function stack(data) {
160+
var n = data.length,
161+
m = data[0].length,
162+
i,
163+
j,
164+
y0;
165+
166+
// compute the order of series
167+
var index = d3_layout_stackOrders[order](data);
168+
169+
// set y0 on the baseline
170+
d3_layout_stackOffsets[offset](data, index);
171+
172+
// propagate offset to other series
173+
for (j = 0; j < m; ++j) {
174+
for (i = 1, y0 = data[index[0]][j].y0; i < n; ++i) {
175+
data[index[i]][j].y0 = y0 += data[index[i - 1]][j].y;
176+
}
177+
}
178+
179+
return data;
180+
}
181+
182+
stack.order = function(x) {
183+
if (!arguments.length) return order;
184+
order = x;
185+
return stack;
186+
};
187+
188+
stack.offset = function(x) {
189+
if (!arguments.length) return offset;
190+
offset = x;
191+
return stack;
192+
};
193+
194+
return stack;
195+
}
196+
197+
var d3_layout_stackOrders = {
198+
199+
"inside-out": function(data) {
200+
var n = data.length,
201+
i,
202+
j,
203+
max = data.map(d3_layout_stackMaxIndex),
204+
sums = data.map(d3_layout_stackReduceSum),
205+
index = d3.range(n).sort(function(a, b) { return max[a] - max[b]; }),
206+
top = 0,
207+
bottom = 0,
208+
tops = [],
209+
bottoms = [];
210+
for (i = 0; i < n; i++) {
211+
j = index[i];
212+
if (top < bottom) {
213+
top += sums[j];
214+
tops.push(j);
215+
} else {
216+
bottom += sums[j];
217+
bottoms.push(j);
218+
}
219+
}
220+
return bottoms.reverse().concat(tops);
221+
},
222+
223+
"reverse": function(data) {
224+
return d3.range(data.length).reverse();
225+
},
226+
227+
"default": function(data) {
228+
return d3.range(data.length);
229+
}
230+
231+
};
232+
233+
var d3_layout_stackOffsets = {
234+
235+
"silhouette": function(data, index) {
236+
var n = data.length,
237+
m = data[0].length,
238+
sums = [],
239+
max = 0,
240+
i,
241+
j,
242+
o;
243+
for (j = 0; j < m; ++j) {
244+
for (i = 0, o = 0; i < n; i++) o += data[i][j].y;
245+
if (o > max) max = o;
246+
sums.push(o);
247+
}
248+
for (j = 0, i = index[0]; j < m; ++j) {
249+
data[i][j].y0 = (max - sums[j]) / 2;
250+
}
251+
},
252+
253+
"wiggle": function(data, index) {
254+
var n = data.length,
255+
x = data[0],
256+
m = x.length,
257+
max = 0,
258+
i,
259+
j,
260+
k,
261+
ii,
262+
ik,
263+
i0 = index[0],
264+
s1,
265+
s2,
266+
s3,
267+
dx,
268+
o,
269+
o0;
270+
data[i0][0].y0 = o = o0 = 0;
271+
for (j = 1; j < m; ++j) {
272+
for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j].y;
273+
for (i = 0, s2 = 0, dx = x[j].x - x[j - 1].x; i < n; ++i) {
274+
for (k = 0, ii = index[i], s3 = (data[ii][j].y - data[ii][j - 1].y) / (2 * dx); k < i; ++k) {
275+
s3 += (data[ik = index[k]][j].y - data[ik][j - 1].y) / dx;
276+
}
277+
s2 += s3 * data[ii][j].y;
278+
}
279+
data[i0][j].y0 = o -= s1 ? s2 / s1 * dx : 0;
280+
if (o < o0) o0 = o;
281+
}
282+
for (j = 0; j < m; ++j) data[i0][j].y0 -= o0;
283+
},
284+
285+
"zero": function(data, index) {
286+
var j = 0,
287+
m = data[0].length,
288+
i0 = index[0];
289+
for (; j < m; ++j) data[i0][j].y0 = 0;
290+
}
291+
292+
};
293+
294+
function d3_layout_stackReduceSum(d) {
295+
return d.reduce(d3_layout_stackSum, 0);
296+
}
297+
298+
function d3_layout_stackMaxIndex(array) {
299+
var i = 1,
300+
j = 0,
301+
v = array[0].y,
302+
k,
303+
n = array.length;
304+
for (; i < n; ++i) {
305+
if ((k = array[i].y) > v) {
306+
j = i;
307+
v = k;
308+
}
309+
}
310+
return j;
311+
}
312+
313+
function d3_layout_stackSum(p, d) {
314+
return p + d.y;
315+
}
153316
})()

d3.layout.min.js

Lines changed: 6 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)