social_stream-base 0.7.11 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1865 @@
1
+ (function(){d3.layout = {};
2
+ // Implements hierarchical edge bundling using Holten's algorithm. For each
3
+ // input link, a path is computed that travels through the tree, up the parent
4
+ // hierarchy to the least common ancestor, and then back down to the destination
5
+ // node. Each path is simply an array of nodes.
6
+ d3.layout.bundle = function() {
7
+ return function(links) {
8
+ var paths = [],
9
+ i = -1,
10
+ n = links.length;
11
+ while (++i < n) paths.push(d3_layout_bundlePath(links[i]));
12
+ return paths;
13
+ };
14
+ };
15
+
16
+ function d3_layout_bundlePath(link) {
17
+ var start = link.source,
18
+ end = link.target,
19
+ lca = d3_layout_bundleLeastCommonAncestor(start, end),
20
+ points = [start];
21
+ while (start !== lca) {
22
+ start = start.parent;
23
+ points.push(start);
24
+ }
25
+ var k = points.length;
26
+ while (end !== lca) {
27
+ points.splice(k, 0, end);
28
+ end = end.parent;
29
+ }
30
+ return points;
31
+ }
32
+
33
+ function d3_layout_bundleAncestors(node) {
34
+ var ancestors = [],
35
+ parent = node.parent;
36
+ while (parent != null) {
37
+ ancestors.push(node);
38
+ node = parent;
39
+ parent = parent.parent;
40
+ }
41
+ ancestors.push(node);
42
+ return ancestors;
43
+ }
44
+
45
+ function d3_layout_bundleLeastCommonAncestor(a, b) {
46
+ if (a === b) return a;
47
+ var aNodes = d3_layout_bundleAncestors(a),
48
+ bNodes = d3_layout_bundleAncestors(b),
49
+ aNode = aNodes.pop(),
50
+ bNode = bNodes.pop(),
51
+ sharedNode = null;
52
+ while (aNode === bNode) {
53
+ sharedNode = aNode;
54
+ aNode = aNodes.pop();
55
+ bNode = bNodes.pop();
56
+ }
57
+ return sharedNode;
58
+ }
59
+ d3.layout.chord = function() {
60
+ var chord = {},
61
+ chords,
62
+ groups,
63
+ matrix,
64
+ n,
65
+ padding = 0,
66
+ sortGroups,
67
+ sortSubgroups,
68
+ sortChords;
69
+
70
+ function relayout() {
71
+ var subgroups = {},
72
+ groupSums = [],
73
+ groupIndex = d3.range(n),
74
+ subgroupIndex = [],
75
+ k,
76
+ x,
77
+ x0,
78
+ i,
79
+ j;
80
+
81
+ chords = [];
82
+ groups = [];
83
+
84
+ // Compute the sum.
85
+ k = 0, i = -1; while (++i < n) {
86
+ x = 0, j = -1; while (++j < n) {
87
+ x += matrix[i][j];
88
+ }
89
+ groupSums.push(x);
90
+ subgroupIndex.push(d3.range(n));
91
+ k += x;
92
+ }
93
+
94
+ // Sort groups…
95
+ if (sortGroups) {
96
+ groupIndex.sort(function(a, b) {
97
+ return sortGroups(groupSums[a], groupSums[b]);
98
+ });
99
+ }
100
+
101
+ // Sort subgroups…
102
+ if (sortSubgroups) {
103
+ subgroupIndex.forEach(function(d, i) {
104
+ d.sort(function(a, b) {
105
+ return sortSubgroups(matrix[i][a], matrix[i][b]);
106
+ });
107
+ });
108
+ }
109
+
110
+ // Convert the sum to scaling factor for [0, 2pi].
111
+ // TODO Allow start and end angle to be specified.
112
+ // TODO Allow padding to be specified as percentage?
113
+ k = (2 * Math.PI - padding * n) / k;
114
+
115
+ // Compute the start and end angle for each group and subgroup.
116
+ x = 0, i = -1; while (++i < n) {
117
+ x0 = x, j = -1; while (++j < n) {
118
+ var di = groupIndex[i],
119
+ dj = subgroupIndex[i][j],
120
+ v = matrix[di][dj];
121
+ subgroups[di + "-" + dj] = {
122
+ index: di,
123
+ subindex: dj,
124
+ startAngle: x,
125
+ endAngle: x += v * k,
126
+ value: v
127
+ };
128
+ }
129
+ groups.push({
130
+ index: di,
131
+ startAngle: x0,
132
+ endAngle: x,
133
+ value: (x - x0) / k
134
+ });
135
+ x += padding;
136
+ }
137
+
138
+ // Generate chords for each (non-empty) subgroup-subgroup link.
139
+ i = -1; while (++i < n) {
140
+ j = i - 1; while (++j < n) {
141
+ var source = subgroups[i + "-" + j],
142
+ target = subgroups[j + "-" + i];
143
+ if (source.value || target.value) {
144
+ chords.push(source.value < target.value
145
+ ? {source: target, target: source}
146
+ : {source: source, target: target});
147
+ }
148
+ }
149
+ }
150
+
151
+ if (sortChords) resort();
152
+ }
153
+
154
+ function resort() {
155
+ chords.sort(function(a, b) {
156
+ return sortChords(a.target.value, b.target.value);
157
+ });
158
+ }
159
+
160
+ chord.matrix = function(x) {
161
+ if (!arguments.length) return matrix;
162
+ n = (matrix = x) && matrix.length;
163
+ chords = groups = null;
164
+ return chord;
165
+ };
166
+
167
+ chord.padding = function(x) {
168
+ if (!arguments.length) return padding;
169
+ padding = x;
170
+ chords = groups = null;
171
+ return chord;
172
+ };
173
+
174
+ chord.sortGroups = function(x) {
175
+ if (!arguments.length) return sortGroups;
176
+ sortGroups = x;
177
+ chords = groups = null;
178
+ return chord;
179
+ };
180
+
181
+ chord.sortSubgroups = function(x) {
182
+ if (!arguments.length) return sortSubgroups;
183
+ sortSubgroups = x;
184
+ chords = null;
185
+ return chord;
186
+ };
187
+
188
+ chord.sortChords = function(x) {
189
+ if (!arguments.length) return sortChords;
190
+ sortChords = x;
191
+ if (chords) resort();
192
+ return chord;
193
+ };
194
+
195
+ chord.chords = function() {
196
+ if (!chords) relayout();
197
+ return chords;
198
+ };
199
+
200
+ chord.groups = function() {
201
+ if (!groups) relayout();
202
+ return groups;
203
+ };
204
+
205
+ return chord;
206
+ };
207
+ // A rudimentary force layout using Gauss-Seidel.
208
+ d3.layout.force = function() {
209
+ var force = {},
210
+ event = d3.dispatch("tick"),
211
+ size = [1, 1],
212
+ drag,
213
+ alpha,
214
+ friction = .9,
215
+ linkDistance = d3_layout_forceLinkDistance,
216
+ linkStrength = d3_layout_forceLinkStrength,
217
+ charge = -30,
218
+ gravity = .1,
219
+ theta = .8,
220
+ interval,
221
+ nodes = [],
222
+ links = [],
223
+ distances,
224
+ strengths;
225
+
226
+ function repulse(node, kc) {
227
+ return function(quad, x1, y1, x2, y2) {
228
+ if (quad.point !== node) {
229
+ var dx = quad.cx - node.x,
230
+ dy = quad.cy - node.y,
231
+ dn = 1 / Math.sqrt(dx * dx + dy * dy);
232
+
233
+ /* Barnes-Hut criterion. */
234
+ if ((x2 - x1) * dn < theta) {
235
+ var k = kc * quad.count * dn * dn;
236
+ node.px -= dx * k;
237
+ node.py -= dy * k;
238
+ return true;
239
+ }
240
+
241
+ if (quad.point && isFinite(dn)) {
242
+ var k = kc * dn * dn;
243
+ node.px -= dx * k;
244
+ node.py -= dy * k;
245
+ }
246
+ }
247
+ };
248
+ }
249
+
250
+ function tick() {
251
+ var n = nodes.length,
252
+ m = links.length,
253
+ q,
254
+ i, // current index
255
+ o, // current object
256
+ s, // current source
257
+ t, // current target
258
+ l, // current distance
259
+ k, // current force
260
+ x, // x-distance
261
+ y; // y-distance
262
+
263
+ // gauss-seidel relaxation for links
264
+ for (i = 0; i < m; ++i) {
265
+ o = links[i];
266
+ s = o.source;
267
+ t = o.target;
268
+ x = t.x - s.x;
269
+ y = t.y - s.y;
270
+ if (l = (x * x + y * y)) {
271
+ l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
272
+ x *= l;
273
+ y *= l;
274
+ t.x -= x * (k = s.weight / (t.weight + s.weight));
275
+ t.y -= y * k;
276
+ s.x += x * (k = 1 - k);
277
+ s.y += y * k;
278
+ }
279
+ }
280
+
281
+ // apply gravity forces
282
+ if (k = alpha * gravity) {
283
+ x = size[0] / 2;
284
+ y = size[1] / 2;
285
+ i = -1; if (k) while (++i < n) {
286
+ o = nodes[i];
287
+ o.x += (x - o.x) * k;
288
+ o.y += (y - o.y) * k;
289
+ }
290
+ }
291
+
292
+ // compute quadtree center of mass and apply charge forces
293
+ if (k = alpha * charge) {
294
+ d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes));
295
+ i = -1; while (++i < n) {
296
+ if (!(o = nodes[i]).fixed) {
297
+ q.visit(repulse(o, k));
298
+ }
299
+ }
300
+ }
301
+
302
+ // position verlet integration
303
+ i = -1; while (++i < n) {
304
+ o = nodes[i];
305
+ if (o.fixed) {
306
+ o.x = o.px;
307
+ o.y = o.py;
308
+ } else {
309
+ o.x -= (o.px - (o.px = o.x)) * friction;
310
+ o.y -= (o.py - (o.py = o.y)) * friction;
311
+ }
312
+ }
313
+
314
+ event.tick.dispatch({type: "tick", alpha: alpha});
315
+
316
+ // simulated annealing, basically
317
+ return (alpha *= .99) < .005;
318
+ }
319
+
320
+ force.on = function(type, listener) {
321
+ event[type].add(listener);
322
+ return force;
323
+ };
324
+
325
+ force.nodes = function(x) {
326
+ if (!arguments.length) return nodes;
327
+ nodes = x;
328
+ return force;
329
+ };
330
+
331
+ force.links = function(x) {
332
+ if (!arguments.length) return links;
333
+ links = x;
334
+ return force;
335
+ };
336
+
337
+ force.size = function(x) {
338
+ if (!arguments.length) return size;
339
+ size = x;
340
+ return force;
341
+ };
342
+
343
+ force.linkDistance = function(x) {
344
+ if (!arguments.length) return linkDistance;
345
+ linkDistance = d3.functor(x);
346
+ return force;
347
+ };
348
+
349
+ // For backwards-compatibility.
350
+ force.distance = force.linkDistance;
351
+
352
+ force.linkStrength = function(x) {
353
+ if (!arguments.length) return linkStrength;
354
+ linkStrength = d3.functor(x);
355
+ return force;
356
+ };
357
+
358
+ force.friction = function(x) {
359
+ if (!arguments.length) return friction;
360
+ friction = x;
361
+ return force;
362
+ };
363
+
364
+ force.charge = function(x) {
365
+ if (!arguments.length) return charge;
366
+ charge = x;
367
+ return force;
368
+ };
369
+
370
+ force.gravity = function(x) {
371
+ if (!arguments.length) return gravity;
372
+ gravity = x;
373
+ return force;
374
+ };
375
+
376
+ force.theta = function(x) {
377
+ if (!arguments.length) return theta;
378
+ theta = x;
379
+ return force;
380
+ };
381
+
382
+ force.start = function() {
383
+ var i,
384
+ j,
385
+ n = nodes.length,
386
+ m = links.length,
387
+ w = size[0],
388
+ h = size[1],
389
+ neighbors,
390
+ o;
391
+
392
+ for (i = 0; i < n; ++i) {
393
+ (o = nodes[i]).index = i;
394
+ o.weight = 0;
395
+ }
396
+
397
+ distances = [];
398
+ strengths = [];
399
+ for (i = 0; i < m; ++i) {
400
+ o = links[i];
401
+ if (typeof o.source == "number") o.source = nodes[o.source];
402
+ if (typeof o.target == "number") o.target = nodes[o.target];
403
+ distances[i] = linkDistance.call(this, o, i);
404
+ strengths[i] = linkStrength.call(this, o, i);
405
+ ++o.source.weight;
406
+ ++o.target.weight;
407
+ }
408
+
409
+ for (i = 0; i < n; ++i) {
410
+ o = nodes[i];
411
+ if (isNaN(o.x)) o.x = position("x", w);
412
+ if (isNaN(o.y)) o.y = position("y", h);
413
+ if (isNaN(o.px)) o.px = o.x;
414
+ if (isNaN(o.py)) o.py = o.y;
415
+ }
416
+
417
+ // initialize node position based on first neighbor
418
+ function position(dimension, size) {
419
+ var neighbors = neighbor(i),
420
+ j = -1,
421
+ m = neighbors.length,
422
+ x;
423
+ while (++j < m) if (!isNaN(x = neighbors[j][dimension])) return x;
424
+ return Math.random() * size;
425
+ }
426
+
427
+ // initialize neighbors lazily
428
+ function neighbor() {
429
+ if (!neighbors) {
430
+ neighbors = [];
431
+ for (j = 0; j < n; ++j) {
432
+ neighbors[j] = [];
433
+ }
434
+ for (j = 0; j < m; ++j) {
435
+ var o = links[j];
436
+ neighbors[o.source.index].push(o.target);
437
+ neighbors[o.target.index].push(o.source);
438
+ }
439
+ }
440
+ return neighbors[i];
441
+ }
442
+
443
+ return force.resume();
444
+ };
445
+
446
+ force.resume = function() {
447
+ alpha = .1;
448
+ d3.timer(tick);
449
+ return force;
450
+ };
451
+
452
+ force.stop = function() {
453
+ alpha = 0;
454
+ return force;
455
+ };
456
+
457
+ // use `node.call(force.drag)` to make nodes draggable
458
+ force.drag = function() {
459
+ if (!drag) drag = d3.behavior.drag()
460
+ .on("dragstart", dragstart)
461
+ .on("drag", d3_layout_forceDrag)
462
+ .on("dragend", d3_layout_forceDragEnd);
463
+
464
+ this.on("mouseover.force", d3_layout_forceDragOver)
465
+ .on("mouseout.force", d3_layout_forceDragOut)
466
+ .call(drag);
467
+ };
468
+
469
+ function dragstart(d) {
470
+ d3_layout_forceDragOver(d3_layout_forceDragNode = d);
471
+ d3_layout_forceDragForce = force;
472
+ }
473
+
474
+ return force;
475
+ };
476
+
477
+ var d3_layout_forceDragForce,
478
+ d3_layout_forceDragNode;
479
+
480
+ function d3_layout_forceDragOver(d) {
481
+ d.fixed |= 2;
482
+ }
483
+
484
+ function d3_layout_forceDragOut(d) {
485
+ if (d !== d3_layout_forceDragNode) d.fixed &= 1;
486
+ }
487
+
488
+ function d3_layout_forceDragEnd() {
489
+ d3_layout_forceDrag();
490
+ d3_layout_forceDragNode.fixed &= 1;
491
+ d3_layout_forceDragForce = d3_layout_forceDragNode = null;
492
+ }
493
+
494
+ function d3_layout_forceDrag() {
495
+ d3_layout_forceDragNode.px += d3.event.dx;
496
+ d3_layout_forceDragNode.py += d3.event.dy;
497
+ d3_layout_forceDragForce.resume(); // restart annealing
498
+ }
499
+
500
+ function d3_layout_forceAccumulate(quad) {
501
+ var cx = 0,
502
+ cy = 0;
503
+ quad.count = 0;
504
+ if (!quad.leaf) {
505
+ var nodes = quad.nodes,
506
+ n = nodes.length,
507
+ i = -1,
508
+ c;
509
+ while (++i < n) {
510
+ c = nodes[i];
511
+ if (c == null) continue;
512
+ d3_layout_forceAccumulate(c);
513
+ quad.count += c.count;
514
+ cx += c.count * c.cx;
515
+ cy += c.count * c.cy;
516
+ }
517
+ }
518
+ if (quad.point) {
519
+ // jitter internal nodes that are coincident
520
+ if (!quad.leaf) {
521
+ quad.point.x += Math.random() - .5;
522
+ quad.point.y += Math.random() - .5;
523
+ }
524
+ quad.count++;
525
+ cx += quad.point.x;
526
+ cy += quad.point.y;
527
+ }
528
+ quad.cx = cx / quad.count;
529
+ quad.cy = cy / quad.count;
530
+ }
531
+
532
+ function d3_layout_forceLinkDistance(link) {
533
+ return 20;
534
+ }
535
+
536
+ function d3_layout_forceLinkStrength(link) {
537
+ return 1;
538
+ }
539
+ d3.layout.partition = function() {
540
+ var hierarchy = d3.layout.hierarchy(),
541
+ size = [1, 1]; // width, height
542
+
543
+ function position(node, x, dx, dy) {
544
+ var children = node.children;
545
+ node.x = x;
546
+ node.y = node.depth * dy;
547
+ node.dx = dx;
548
+ node.dy = dy;
549
+ if (children) {
550
+ var i = -1,
551
+ n = children.length,
552
+ c,
553
+ d;
554
+ dx = node.value ? dx / node.value : 0;
555
+ while (++i < n) {
556
+ position(c = children[i], x, d = c.value * dx, dy);
557
+ x += d;
558
+ }
559
+ }
560
+ }
561
+
562
+ function depth(node) {
563
+ var children = node.children,
564
+ d = 0;
565
+ if (children) {
566
+ var i = -1,
567
+ n = children.length;
568
+ while (++i < n) d = Math.max(d, depth(children[i]));
569
+ }
570
+ return 1 + d;
571
+ }
572
+
573
+ function partition(d, i) {
574
+ var nodes = hierarchy.call(this, d, i);
575
+ position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
576
+ return nodes;
577
+ }
578
+
579
+ partition.size = function(x) {
580
+ if (!arguments.length) return size;
581
+ size = x;
582
+ return partition;
583
+ };
584
+
585
+ return d3_layout_hierarchyRebind(partition, hierarchy);
586
+ };
587
+ d3.layout.pie = function() {
588
+ var value = Number,
589
+ sort = null,
590
+ startAngle = 0,
591
+ endAngle = 2 * Math.PI;
592
+
593
+ function pie(data, i) {
594
+
595
+ // Compute the start angle.
596
+ var a = +(typeof startAngle === "function"
597
+ ? startAngle.apply(this, arguments)
598
+ : startAngle);
599
+
600
+ // Compute the angular range (end - start).
601
+ var k = (typeof endAngle === "function"
602
+ ? endAngle.apply(this, arguments)
603
+ : endAngle) - startAngle;
604
+
605
+ // Optionally sort the data.
606
+ var index = d3.range(data.length);
607
+ if (sort != null) index.sort(function(i, j) {
608
+ return sort(data[i], data[j]);
609
+ });
610
+
611
+ // Compute the numeric values for each data element.
612
+ var values = data.map(value);
613
+
614
+ // Convert k into a scale factor from value to angle, using the sum.
615
+ k /= values.reduce(function(p, d) { return p + d; }, 0);
616
+
617
+ // Compute the arcs!
618
+ var arcs = index.map(function(i) {
619
+ return {
620
+ data: data[i],
621
+ value: d = values[i],
622
+ startAngle: a,
623
+ endAngle: a += d * k
624
+ };
625
+ });
626
+
627
+ // Return the arcs in the original data's order.
628
+ return data.map(function(d, i) {
629
+ return arcs[index[i]];
630
+ });
631
+ }
632
+
633
+ /**
634
+ * Specifies the value function *x*, which returns a nonnegative numeric value
635
+ * for each datum. The default value function is `Number`. The value function
636
+ * is passed two arguments: the current datum and the current index.
637
+ */
638
+ pie.value = function(x) {
639
+ if (!arguments.length) return value;
640
+ value = x;
641
+ return pie;
642
+ };
643
+
644
+ /**
645
+ * Specifies a sort comparison operator *x*. The comparator is passed two data
646
+ * elements from the data array, a and b; it returns a negative value if a is
647
+ * less than b, a positive value if a is greater than b, and zero if a equals
648
+ * b.
649
+ */
650
+ pie.sort = function(x) {
651
+ if (!arguments.length) return sort;
652
+ sort = x;
653
+ return pie;
654
+ };
655
+
656
+ /**
657
+ * Specifies the overall start angle of the pie chart. Defaults to 0. The
658
+ * start angle can be specified either as a constant or as a function; in the
659
+ * case of a function, it is evaluated once per array (as opposed to per
660
+ * element).
661
+ */
662
+ pie.startAngle = function(x) {
663
+ if (!arguments.length) return startAngle;
664
+ startAngle = x;
665
+ return pie;
666
+ };
667
+
668
+ /**
669
+ * Specifies the overall end angle of the pie chart. Defaults to 2π. The
670
+ * end angle can be specified either as a constant or as a function; in the
671
+ * case of a function, it is evaluated once per array (as opposed to per
672
+ * element).
673
+ */
674
+ pie.endAngle = function(x) {
675
+ if (!arguments.length) return endAngle;
676
+ endAngle = x;
677
+ return pie;
678
+ };
679
+
680
+ return pie;
681
+ };
682
+ // data is two-dimensional array of x,y; we populate y0
683
+ d3.layout.stack = function() {
684
+ var values = Object,
685
+ order = d3_layout_stackOrders["default"],
686
+ offset = d3_layout_stackOffsets["zero"],
687
+ out = d3_layout_stackOut,
688
+ x = d3_layout_stackX,
689
+ y = d3_layout_stackY;
690
+
691
+ function stack(data, index) {
692
+
693
+ // Convert series to canonical two-dimensional representation.
694
+ var series = data.map(function(d, i) {
695
+ return values.call(stack, d, i);
696
+ });
697
+
698
+ // Convert each series to canonical [[x,y]] representation.
699
+ var points = series.map(function(d, i) {
700
+ return d.map(function(v, i) {
701
+ return [x.call(stack, v, i), y.call(stack, v, i)];
702
+ });
703
+ });
704
+
705
+ // Compute the order of series, and permute them.
706
+ var orders = order.call(stack, points, index);
707
+ series = d3.permute(series, orders);
708
+ points = d3.permute(points, orders);
709
+
710
+ // Compute the baseline…
711
+ var offsets = offset.call(stack, points, index);
712
+
713
+ // And propagate it to other series.
714
+ var n = series.length,
715
+ m = series[0].length,
716
+ i,
717
+ j,
718
+ o;
719
+ for (j = 0; j < m; ++j) {
720
+ out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
721
+ for (i = 1; i < n; ++i) {
722
+ out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
723
+ }
724
+ }
725
+
726
+ return data;
727
+ }
728
+
729
+ stack.values = function(x) {
730
+ if (!arguments.length) return values;
731
+ values = x;
732
+ return stack;
733
+ };
734
+
735
+ stack.order = function(x) {
736
+ if (!arguments.length) return order;
737
+ order = typeof x === "function" ? x : d3_layout_stackOrders[x];
738
+ return stack;
739
+ };
740
+
741
+ stack.offset = function(x) {
742
+ if (!arguments.length) return offset;
743
+ offset = typeof x === "function" ? x : d3_layout_stackOffsets[x];
744
+ return stack;
745
+ };
746
+
747
+ stack.x = function(z) {
748
+ if (!arguments.length) return x;
749
+ x = z;
750
+ return stack;
751
+ };
752
+
753
+ stack.y = function(z) {
754
+ if (!arguments.length) return y;
755
+ y = z;
756
+ return stack;
757
+ };
758
+
759
+ stack.out = function(z) {
760
+ if (!arguments.length) return out;
761
+ out = z;
762
+ return stack;
763
+ };
764
+
765
+ return stack;
766
+ }
767
+
768
+ function d3_layout_stackX(d) {
769
+ return d.x;
770
+ }
771
+
772
+ function d3_layout_stackY(d) {
773
+ return d.y;
774
+ }
775
+
776
+ function d3_layout_stackOut(d, y0, y) {
777
+ d.y0 = y0;
778
+ d.y = y;
779
+ }
780
+
781
+ var d3_layout_stackOrders = {
782
+
783
+ "inside-out": function(data) {
784
+ var n = data.length,
785
+ i,
786
+ j,
787
+ max = data.map(d3_layout_stackMaxIndex),
788
+ sums = data.map(d3_layout_stackReduceSum),
789
+ index = d3.range(n).sort(function(a, b) { return max[a] - max[b]; }),
790
+ top = 0,
791
+ bottom = 0,
792
+ tops = [],
793
+ bottoms = [];
794
+ for (i = 0; i < n; ++i) {
795
+ j = index[i];
796
+ if (top < bottom) {
797
+ top += sums[j];
798
+ tops.push(j);
799
+ } else {
800
+ bottom += sums[j];
801
+ bottoms.push(j);
802
+ }
803
+ }
804
+ return bottoms.reverse().concat(tops);
805
+ },
806
+
807
+ "reverse": function(data) {
808
+ return d3.range(data.length).reverse();
809
+ },
810
+
811
+ "default": function(data) {
812
+ return d3.range(data.length);
813
+ }
814
+
815
+ };
816
+
817
+ var d3_layout_stackOffsets = {
818
+
819
+ "silhouette": function(data) {
820
+ var n = data.length,
821
+ m = data[0].length,
822
+ sums = [],
823
+ max = 0,
824
+ i,
825
+ j,
826
+ o,
827
+ y0 = [];
828
+ for (j = 0; j < m; ++j) {
829
+ for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
830
+ if (o > max) max = o;
831
+ sums.push(o);
832
+ }
833
+ for (j = 0; j < m; ++j) {
834
+ y0[j] = (max - sums[j]) / 2;
835
+ }
836
+ return y0;
837
+ },
838
+
839
+ "wiggle": function(data) {
840
+ var n = data.length,
841
+ x = data[0],
842
+ m = x.length,
843
+ max = 0,
844
+ i,
845
+ j,
846
+ k,
847
+ s1,
848
+ s2,
849
+ s3,
850
+ dx,
851
+ o,
852
+ o0,
853
+ y0 = [];
854
+ y0[0] = o = o0 = 0;
855
+ for (j = 1; j < m; ++j) {
856
+ for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
857
+ for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
858
+ for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
859
+ s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
860
+ }
861
+ s2 += s3 * data[i][j][1];
862
+ }
863
+ y0[j] = o -= s1 ? s2 / s1 * dx : 0;
864
+ if (o < o0) o0 = o;
865
+ }
866
+ for (j = 0; j < m; ++j) y0[j] -= o0;
867
+ return y0;
868
+ },
869
+
870
+ "expand": function(data) {
871
+ var n = data.length,
872
+ m = data[0].length,
873
+ k = 1 / n,
874
+ i,
875
+ j,
876
+ o,
877
+ y0 = [];
878
+ for (j = 0; j < m; ++j) {
879
+ for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
880
+ if (o) for (i = 0; i < n; i++) data[i][j][1] /= o;
881
+ else for (i = 0; i < n; i++) data[i][j][1] = k;
882
+ }
883
+ for (j = 0; j < m; ++j) y0[j] = 0;
884
+ return y0;
885
+ },
886
+
887
+ "zero": function(data) {
888
+ var j = -1,
889
+ m = data[0].length,
890
+ y0 = [];
891
+ while (++j < m) y0[j] = 0;
892
+ return y0;
893
+ }
894
+
895
+ };
896
+
897
+ function d3_layout_stackMaxIndex(array) {
898
+ var i = 1,
899
+ j = 0,
900
+ v = array[0][1],
901
+ k,
902
+ n = array.length;
903
+ for (; i < n; ++i) {
904
+ if ((k = array[i][1]) > v) {
905
+ j = i;
906
+ v = k;
907
+ }
908
+ }
909
+ return j;
910
+ }
911
+
912
+ function d3_layout_stackReduceSum(d) {
913
+ return d.reduce(d3_layout_stackSum, 0);
914
+ }
915
+
916
+ function d3_layout_stackSum(p, d) {
917
+ return p + d[1];
918
+ }
919
+ d3.layout.histogram = function() {
920
+ var frequency = true,
921
+ valuer = Number,
922
+ ranger = d3_layout_histogramRange,
923
+ binner = d3_layout_histogramBinSturges;
924
+
925
+ function histogram(data, i) {
926
+ var bins = [],
927
+ values = data.map(valuer, this),
928
+ range = ranger.call(this, values, i),
929
+ thresholds = binner.call(this, range, values, i),
930
+ bin,
931
+ i = -1,
932
+ n = values.length,
933
+ m = thresholds.length - 1,
934
+ k = frequency ? 1 : 1 / n,
935
+ x;
936
+
937
+ // Initialize the bins.
938
+ while (++i < m) {
939
+ bin = bins[i] = [];
940
+ bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
941
+ bin.y = 0;
942
+ }
943
+
944
+ // Fill the bins, ignoring values outside the range.
945
+ i = -1; while(++i < n) {
946
+ x = values[i];
947
+ if ((x >= range[0]) && (x <= range[1])) {
948
+ bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
949
+ bin.y += k;
950
+ bin.push(data[i]);
951
+ }
952
+ }
953
+
954
+ return bins;
955
+ }
956
+
957
+ // Specifies how to extract a value from the associated data. The default
958
+ // value function is `Number`, which is equivalent to the identity function.
959
+ histogram.value = function(x) {
960
+ if (!arguments.length) return valuer;
961
+ valuer = x;
962
+ return histogram;
963
+ };
964
+
965
+ // Specifies the range of the histogram. Values outside the specified range
966
+ // will be ignored. The argument `x` may be specified either as a two-element
967
+ // array representing the minimum and maximum value of the range, or as a
968
+ // function that returns the range given the array of values and the current
969
+ // index `i`. The default range is the extent (minimum and maximum) of the
970
+ // values.
971
+ histogram.range = function(x) {
972
+ if (!arguments.length) return ranger;
973
+ ranger = d3.functor(x);
974
+ return histogram;
975
+ };
976
+
977
+ // Specifies how to bin values in the histogram. The argument `x` may be
978
+ // specified as a number, in which case the range of values will be split
979
+ // uniformly into the given number of bins. Or, `x` may be an array of
980
+ // threshold values, defining the bins; the specified array must contain the
981
+ // rightmost (upper) value, thus specifying n + 1 values for n bins. Or, `x`
982
+ // may be a function which is evaluated, being passed the range, the array of
983
+ // values, and the current index `i`, returning an array of thresholds. The
984
+ // default bin function will divide the values into uniform bins using
985
+ // Sturges' formula.
986
+ histogram.bins = function(x) {
987
+ if (!arguments.length) return binner;
988
+ binner = typeof x === "number"
989
+ ? function(range) { return d3_layout_histogramBinFixed(range, x); }
990
+ : d3.functor(x);
991
+ return histogram;
992
+ };
993
+
994
+ // Specifies whether the histogram's `y` value is a count (frequency) or a
995
+ // probability (density). The default value is true.
996
+ histogram.frequency = function(x) {
997
+ if (!arguments.length) return frequency;
998
+ frequency = !!x;
999
+ return histogram;
1000
+ };
1001
+
1002
+ return histogram;
1003
+ };
1004
+
1005
+ function d3_layout_histogramBinSturges(range, values) {
1006
+ return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
1007
+ }
1008
+
1009
+ function d3_layout_histogramBinFixed(range, n) {
1010
+ var x = -1,
1011
+ b = +range[0],
1012
+ m = (range[1] - b) / n,
1013
+ f = [];
1014
+ while (++x <= n) f[x] = m * x + b;
1015
+ return f;
1016
+ }
1017
+
1018
+ function d3_layout_histogramRange(values) {
1019
+ return [d3.min(values), d3.max(values)];
1020
+ }
1021
+ d3.layout.hierarchy = function() {
1022
+ var sort = d3_layout_hierarchySort,
1023
+ children = d3_layout_hierarchyChildren,
1024
+ value = d3_layout_hierarchyValue;
1025
+
1026
+ // Recursively compute the node depth and value.
1027
+ // Also converts the data representation into a standard hierarchy structure.
1028
+ function recurse(data, depth, nodes) {
1029
+ var childs = children.call(hierarchy, data, depth),
1030
+ node = d3_layout_hierarchyInline ? data : {data: data};
1031
+ node.depth = depth;
1032
+ nodes.push(node);
1033
+ if (childs) {
1034
+ var i = -1,
1035
+ n = childs.length,
1036
+ c = node.children = [],
1037
+ v = 0,
1038
+ j = depth + 1;
1039
+ while (++i < n) {
1040
+ d = recurse(childs[i], j, nodes);
1041
+ d.parent = node;
1042
+ c.push(d);
1043
+ v += d.value;
1044
+ }
1045
+ if (sort) c.sort(sort);
1046
+ if (value) node.value = v;
1047
+ } else if (value) {
1048
+ node.value = +value.call(hierarchy, data, depth) || 0;
1049
+ }
1050
+ return node;
1051
+ }
1052
+
1053
+ // Recursively re-evaluates the node value.
1054
+ function revalue(node, depth) {
1055
+ var children = node.children,
1056
+ v = 0;
1057
+ if (children) {
1058
+ var i = -1,
1059
+ n = children.length,
1060
+ j = depth + 1;
1061
+ while (++i < n) v += revalue(children[i], j);
1062
+ } else if (value) {
1063
+ v = +value.call(hierarchy, d3_layout_hierarchyInline ? node : node.data, depth) || 0;
1064
+ }
1065
+ if (value) node.value = v;
1066
+ return v;
1067
+ }
1068
+
1069
+ function hierarchy(d) {
1070
+ var nodes = [];
1071
+ recurse(d, 0, nodes);
1072
+ return nodes;
1073
+ }
1074
+
1075
+ hierarchy.sort = function(x) {
1076
+ if (!arguments.length) return sort;
1077
+ sort = x;
1078
+ return hierarchy;
1079
+ };
1080
+
1081
+ hierarchy.children = function(x) {
1082
+ if (!arguments.length) return children;
1083
+ children = x;
1084
+ return hierarchy;
1085
+ };
1086
+
1087
+ hierarchy.value = function(x) {
1088
+ if (!arguments.length) return value;
1089
+ value = x;
1090
+ return hierarchy;
1091
+ };
1092
+
1093
+ // Re-evaluates the `value` property for the specified hierarchy.
1094
+ hierarchy.revalue = function(root) {
1095
+ revalue(root, 0);
1096
+ return root;
1097
+ };
1098
+
1099
+ return hierarchy;
1100
+ };
1101
+
1102
+ // A method assignment helper for hierarchy subclasses.
1103
+ function d3_layout_hierarchyRebind(object, hierarchy) {
1104
+ object.sort = d3.rebind(object, hierarchy.sort);
1105
+ object.children = d3.rebind(object, hierarchy.children);
1106
+ object.links = d3_layout_hierarchyLinks;
1107
+ object.value = d3.rebind(object, hierarchy.value);
1108
+
1109
+ // If the new API is used, enabling inlining.
1110
+ object.nodes = function(d) {
1111
+ d3_layout_hierarchyInline = true;
1112
+ return (object.nodes = object)(d);
1113
+ };
1114
+
1115
+ return object;
1116
+ }
1117
+
1118
+ function d3_layout_hierarchyChildren(d) {
1119
+ return d.children;
1120
+ }
1121
+
1122
+ function d3_layout_hierarchyValue(d) {
1123
+ return d.value;
1124
+ }
1125
+
1126
+ function d3_layout_hierarchySort(a, b) {
1127
+ return b.value - a.value;
1128
+ }
1129
+
1130
+ // Returns an array source+target objects for the specified nodes.
1131
+ function d3_layout_hierarchyLinks(nodes) {
1132
+ return d3.merge(nodes.map(function(parent) {
1133
+ return (parent.children || []).map(function(child) {
1134
+ return {source: parent, target: child};
1135
+ });
1136
+ }));
1137
+ }
1138
+
1139
+ // For backwards-compatibility, don't enable inlining by default.
1140
+ var d3_layout_hierarchyInline = false;
1141
+ d3.layout.pack = function() {
1142
+ var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort),
1143
+ size = [1, 1];
1144
+
1145
+ function pack(d, i) {
1146
+ var nodes = hierarchy.call(this, d, i),
1147
+ root = nodes[0];
1148
+
1149
+ // Recursively compute the layout.
1150
+ root.x = 0;
1151
+ root.y = 0;
1152
+ d3_layout_packTree(root);
1153
+
1154
+ // Scale the layout to fit the requested size.
1155
+ var w = size[0],
1156
+ h = size[1],
1157
+ k = 1 / Math.max(2 * root.r / w, 2 * root.r / h);
1158
+ d3_layout_packTransform(root, w / 2, h / 2, k);
1159
+
1160
+ return nodes;
1161
+ }
1162
+
1163
+ pack.size = function(x) {
1164
+ if (!arguments.length) return size;
1165
+ size = x;
1166
+ return pack;
1167
+ };
1168
+
1169
+ return d3_layout_hierarchyRebind(pack, hierarchy);
1170
+ };
1171
+
1172
+ function d3_layout_packSort(a, b) {
1173
+ return a.value - b.value;
1174
+ }
1175
+
1176
+ function d3_layout_packInsert(a, b) {
1177
+ var c = a._pack_next;
1178
+ a._pack_next = b;
1179
+ b._pack_prev = a;
1180
+ b._pack_next = c;
1181
+ c._pack_prev = b;
1182
+ }
1183
+
1184
+ function d3_layout_packSplice(a, b) {
1185
+ a._pack_next = b;
1186
+ b._pack_prev = a;
1187
+ }
1188
+
1189
+ function d3_layout_packIntersects(a, b) {
1190
+ var dx = b.x - a.x,
1191
+ dy = b.y - a.y,
1192
+ dr = a.r + b.r;
1193
+ return (dr * dr - dx * dx - dy * dy) > .001; // within epsilon
1194
+ }
1195
+
1196
+ function d3_layout_packCircle(nodes) {
1197
+ var xMin = Infinity,
1198
+ xMax = -Infinity,
1199
+ yMin = Infinity,
1200
+ yMax = -Infinity,
1201
+ n = nodes.length,
1202
+ a, b, c, j, k;
1203
+
1204
+ function bound(node) {
1205
+ xMin = Math.min(node.x - node.r, xMin);
1206
+ xMax = Math.max(node.x + node.r, xMax);
1207
+ yMin = Math.min(node.y - node.r, yMin);
1208
+ yMax = Math.max(node.y + node.r, yMax);
1209
+ }
1210
+
1211
+ // Create node links.
1212
+ nodes.forEach(d3_layout_packLink);
1213
+
1214
+ // Create first node.
1215
+ a = nodes[0];
1216
+ a.x = -a.r;
1217
+ a.y = 0;
1218
+ bound(a);
1219
+
1220
+ // Create second node.
1221
+ if (n > 1) {
1222
+ b = nodes[1];
1223
+ b.x = b.r;
1224
+ b.y = 0;
1225
+ bound(b);
1226
+
1227
+ // Create third node and build chain.
1228
+ if (n > 2) {
1229
+ c = nodes[2];
1230
+ d3_layout_packPlace(a, b, c);
1231
+ bound(c);
1232
+ d3_layout_packInsert(a, c);
1233
+ a._pack_prev = c;
1234
+ d3_layout_packInsert(c, b);
1235
+ b = a._pack_next;
1236
+
1237
+ // Now iterate through the rest.
1238
+ for (var i = 3; i < n; i++) {
1239
+ d3_layout_packPlace(a, b, c = nodes[i]);
1240
+
1241
+ // Search for the closest intersection.
1242
+ var isect = 0, s1 = 1, s2 = 1;
1243
+ for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
1244
+ if (d3_layout_packIntersects(j, c)) {
1245
+ isect = 1;
1246
+ break;
1247
+ }
1248
+ }
1249
+ if (isect == 1) {
1250
+ for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
1251
+ if (d3_layout_packIntersects(k, c)) {
1252
+ if (s2 < s1) {
1253
+ isect = -1;
1254
+ j = k;
1255
+ }
1256
+ break;
1257
+ }
1258
+ }
1259
+ }
1260
+
1261
+ // Update node chain.
1262
+ if (isect == 0) {
1263
+ d3_layout_packInsert(a, c);
1264
+ b = c;
1265
+ bound(c);
1266
+ } else if (isect > 0) {
1267
+ d3_layout_packSplice(a, j);
1268
+ b = j;
1269
+ i--;
1270
+ } else { // isect < 0
1271
+ d3_layout_packSplice(j, b);
1272
+ a = j;
1273
+ i--;
1274
+ }
1275
+ }
1276
+ }
1277
+ }
1278
+
1279
+ // Re-center the circles and return the encompassing radius.
1280
+ var cx = (xMin + xMax) / 2,
1281
+ cy = (yMin + yMax) / 2,
1282
+ cr = 0;
1283
+ for (var i = 0; i < n; i++) {
1284
+ var node = nodes[i];
1285
+ node.x -= cx;
1286
+ node.y -= cy;
1287
+ cr = Math.max(cr, node.r + Math.sqrt(node.x * node.x + node.y * node.y));
1288
+ }
1289
+
1290
+ // Remove node links.
1291
+ nodes.forEach(d3_layout_packUnlink);
1292
+
1293
+ return cr;
1294
+ }
1295
+
1296
+ function d3_layout_packLink(node) {
1297
+ node._pack_next = node._pack_prev = node;
1298
+ }
1299
+
1300
+ function d3_layout_packUnlink(node) {
1301
+ delete node._pack_next;
1302
+ delete node._pack_prev;
1303
+ }
1304
+
1305
+ function d3_layout_packTree(node) {
1306
+ var children = node.children;
1307
+ if (children) {
1308
+ children.forEach(d3_layout_packTree);
1309
+ node.r = d3_layout_packCircle(children);
1310
+ } else {
1311
+ node.r = Math.sqrt(node.value);
1312
+ }
1313
+ }
1314
+
1315
+ function d3_layout_packTransform(node, x, y, k) {
1316
+ var children = node.children;
1317
+ node.x = (x += k * node.x);
1318
+ node.y = (y += k * node.y);
1319
+ node.r *= k;
1320
+ if (children) {
1321
+ var i = -1, n = children.length;
1322
+ while (++i < n) d3_layout_packTransform(children[i], x, y, k);
1323
+ }
1324
+ }
1325
+
1326
+ function d3_layout_packPlace(a, b, c) {
1327
+ var da = b.r + c.r,
1328
+ db = a.r + c.r,
1329
+ dx = b.x - a.x,
1330
+ dy = b.y - a.y,
1331
+ dc = Math.sqrt(dx * dx + dy * dy),
1332
+ cos = (db * db + dc * dc - da * da) / (2 * db * dc),
1333
+ theta = Math.acos(cos),
1334
+ x = cos * db,
1335
+ h = Math.sin(theta) * db;
1336
+ dx /= dc;
1337
+ dy /= dc;
1338
+ c.x = a.x + x * dx + h * dy;
1339
+ c.y = a.y + x * dy - h * dx;
1340
+ }
1341
+ // Implements a hierarchical layout using the cluster (or dendogram) algorithm.
1342
+ d3.layout.cluster = function() {
1343
+ var hierarchy = d3.layout.hierarchy().sort(null).value(null),
1344
+ separation = d3_layout_treeSeparation,
1345
+ size = [1, 1]; // width, height
1346
+
1347
+ function cluster(d, i) {
1348
+ var nodes = hierarchy.call(this, d, i),
1349
+ root = nodes[0],
1350
+ previousNode,
1351
+ x = 0,
1352
+ kx,
1353
+ ky;
1354
+
1355
+ // First walk, computing the initial x & y values.
1356
+ d3_layout_treeVisitAfter(root, function(node) {
1357
+ if (node.children) {
1358
+ node.x = d3_layout_clusterX(node.children);
1359
+ node.y = d3_layout_clusterY(node.children);
1360
+ } else {
1361
+ node.x = previousNode ? x += separation(node, previousNode) : 0;
1362
+ node.y = 0;
1363
+ previousNode = node;
1364
+ }
1365
+ });
1366
+
1367
+ // Compute the left-most, right-most, and depth-most nodes for extents.
1368
+ var left = d3_layout_clusterLeft(root),
1369
+ right = d3_layout_clusterRight(root),
1370
+ x0 = left.x - separation(left, right) / 2,
1371
+ x1 = right.x + separation(right, left) / 2;
1372
+
1373
+ // Second walk, normalizing x & y to the desired size.
1374
+ d3_layout_treeVisitAfter(root, function(node) {
1375
+ node.x = (node.x - x0) / (x1 - x0) * size[0];
1376
+ node.y = (1 - node.y / root.y) * size[1];
1377
+ });
1378
+
1379
+ return nodes;
1380
+ }
1381
+
1382
+ cluster.separation = function(x) {
1383
+ if (!arguments.length) return separation;
1384
+ separation = x;
1385
+ return cluster;
1386
+ };
1387
+
1388
+ cluster.size = function(x) {
1389
+ if (!arguments.length) return size;
1390
+ size = x;
1391
+ return cluster;
1392
+ };
1393
+
1394
+ return d3_layout_hierarchyRebind(cluster, hierarchy);
1395
+ };
1396
+
1397
+ function d3_layout_clusterY(children) {
1398
+ return 1 + d3.max(children, function(child) {
1399
+ return child.y;
1400
+ });
1401
+ }
1402
+
1403
+ function d3_layout_clusterX(children) {
1404
+ return children.reduce(function(x, child) {
1405
+ return x + child.x;
1406
+ }, 0) / children.length;
1407
+ }
1408
+
1409
+ function d3_layout_clusterLeft(node) {
1410
+ var children = node.children;
1411
+ return children ? d3_layout_clusterLeft(children[0]) : node;
1412
+ }
1413
+
1414
+ function d3_layout_clusterRight(node) {
1415
+ var children = node.children;
1416
+ return children ? d3_layout_clusterRight(children[children.length - 1]) : node;
1417
+ }
1418
+ // Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
1419
+ d3.layout.tree = function() {
1420
+ var hierarchy = d3.layout.hierarchy().sort(null).value(null),
1421
+ separation = d3_layout_treeSeparation,
1422
+ size = [1, 1]; // width, height
1423
+
1424
+ function tree(d, i) {
1425
+ var nodes = hierarchy.call(this, d, i),
1426
+ root = nodes[0];
1427
+
1428
+ function firstWalk(node, previousSibling) {
1429
+ var children = node.children,
1430
+ layout = node._tree;
1431
+ if (children && (n = children.length)) {
1432
+ var n,
1433
+ firstChild = children[0],
1434
+ previousChild,
1435
+ ancestor = firstChild,
1436
+ child,
1437
+ i = -1;
1438
+ while (++i < n) {
1439
+ child = children[i];
1440
+ firstWalk(child, previousChild);
1441
+ ancestor = apportion(child, previousChild, ancestor);
1442
+ previousChild = child;
1443
+ }
1444
+ d3_layout_treeShift(node);
1445
+ var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);
1446
+ if (previousSibling) {
1447
+ layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
1448
+ layout.mod = layout.prelim - midpoint;
1449
+ } else {
1450
+ layout.prelim = midpoint;
1451
+ }
1452
+ } else {
1453
+ if (previousSibling) {
1454
+ layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
1455
+ }
1456
+ }
1457
+ }
1458
+
1459
+ function secondWalk(node, x) {
1460
+ node.x = node._tree.prelim + x;
1461
+ var children = node.children;
1462
+ if (children) {
1463
+ var i = -1,
1464
+ n = children.length;
1465
+ x += node._tree.mod;
1466
+ while (++i < n) {
1467
+ secondWalk(children[i], x);
1468
+ }
1469
+ }
1470
+ }
1471
+
1472
+ function apportion(node, previousSibling, ancestor) {
1473
+ if (previousSibling) {
1474
+ var vip = node,
1475
+ vop = node,
1476
+ vim = previousSibling,
1477
+ vom = node.parent.children[0],
1478
+ sip = vip._tree.mod,
1479
+ sop = vop._tree.mod,
1480
+ sim = vim._tree.mod,
1481
+ som = vom._tree.mod,
1482
+ shift;
1483
+ while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
1484
+ vom = d3_layout_treeLeft(vom);
1485
+ vop = d3_layout_treeRight(vop);
1486
+ vop._tree.ancestor = node;
1487
+ shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);
1488
+ if (shift > 0) {
1489
+ d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);
1490
+ sip += shift;
1491
+ sop += shift;
1492
+ }
1493
+ sim += vim._tree.mod;
1494
+ sip += vip._tree.mod;
1495
+ som += vom._tree.mod;
1496
+ sop += vop._tree.mod;
1497
+ }
1498
+ if (vim && !d3_layout_treeRight(vop)) {
1499
+ vop._tree.thread = vim;
1500
+ vop._tree.mod += sim - sop;
1501
+ }
1502
+ if (vip && !d3_layout_treeLeft(vom)) {
1503
+ vom._tree.thread = vip;
1504
+ vom._tree.mod += sip - som;
1505
+ ancestor = node;
1506
+ }
1507
+ }
1508
+ return ancestor;
1509
+ }
1510
+
1511
+ // Initialize temporary layout variables.
1512
+ d3_layout_treeVisitAfter(root, function(node, previousSibling) {
1513
+ node._tree = {
1514
+ ancestor: node,
1515
+ prelim: 0,
1516
+ mod: 0,
1517
+ change: 0,
1518
+ shift: 0,
1519
+ number: previousSibling ? previousSibling._tree.number + 1 : 0
1520
+ };
1521
+ });
1522
+
1523
+ // Compute the layout using Buchheim et al.'s algorithm.
1524
+ firstWalk(root);
1525
+ secondWalk(root, -root._tree.prelim);
1526
+
1527
+ // Compute the left-most, right-most, and depth-most nodes for extents.
1528
+ var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost),
1529
+ right = d3_layout_treeSearch(root, d3_layout_treeRightmost),
1530
+ deep = d3_layout_treeSearch(root, d3_layout_treeDeepest),
1531
+ x0 = left.x - separation(left, right) / 2,
1532
+ x1 = right.x + separation(right, left) / 2,
1533
+ y1 = deep.depth || 1;
1534
+
1535
+ // Clear temporary layout variables; transform x and y.
1536
+ d3_layout_treeVisitAfter(root, function(node) {
1537
+ node.x = (node.x - x0) / (x1 - x0) * size[0];
1538
+ node.y = node.depth / y1 * size[1];
1539
+ delete node._tree;
1540
+ });
1541
+
1542
+ return nodes;
1543
+ }
1544
+
1545
+ tree.separation = function(x) {
1546
+ if (!arguments.length) return separation;
1547
+ separation = x;
1548
+ return tree;
1549
+ };
1550
+
1551
+ tree.size = function(x) {
1552
+ if (!arguments.length) return size;
1553
+ size = x;
1554
+ return tree;
1555
+ };
1556
+
1557
+ return d3_layout_hierarchyRebind(tree, hierarchy);
1558
+ };
1559
+
1560
+ function d3_layout_treeSeparation(a, b) {
1561
+ return a.parent == b.parent ? 1 : 2;
1562
+ }
1563
+
1564
+ // function d3_layout_treeSeparationRadial(a, b) {
1565
+ // return (a.parent == b.parent ? 1 : 2) / a.depth;
1566
+ // }
1567
+
1568
+ function d3_layout_treeLeft(node) {
1569
+ return node.children ? node.children[0] : node._tree.thread;
1570
+ }
1571
+
1572
+ function d3_layout_treeRight(node) {
1573
+ return node.children ? node.children[node.children.length - 1] : node._tree.thread;
1574
+ }
1575
+
1576
+ function d3_layout_treeSearch(node, compare) {
1577
+ var children = node.children;
1578
+ if (children) {
1579
+ var child,
1580
+ n = children.length,
1581
+ i = -1;
1582
+ while (++i < n) {
1583
+ if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
1584
+ node = child;
1585
+ }
1586
+ }
1587
+ }
1588
+ return node;
1589
+ }
1590
+
1591
+ function d3_layout_treeRightmost(a, b) {
1592
+ return a.x - b.x;
1593
+ }
1594
+
1595
+ function d3_layout_treeLeftmost(a, b) {
1596
+ return b.x - a.x;
1597
+ }
1598
+
1599
+ function d3_layout_treeDeepest(a, b) {
1600
+ return a.depth - b.depth;
1601
+ }
1602
+
1603
+ function d3_layout_treeVisitAfter(node, callback) {
1604
+ function visit(node, previousSibling) {
1605
+ var children = node.children;
1606
+ if (children) {
1607
+ var child,
1608
+ previousChild = null,
1609
+ i = -1,
1610
+ n = children.length;
1611
+ while (++i < n) {
1612
+ child = children[i];
1613
+ visit(child, previousChild);
1614
+ previousChild = child;
1615
+ }
1616
+ }
1617
+ callback(node, previousSibling);
1618
+ }
1619
+ visit(node, null);
1620
+ }
1621
+
1622
+ function d3_layout_treeShift(node) {
1623
+ var shift = 0,
1624
+ change = 0,
1625
+ children = node.children,
1626
+ i = children.length,
1627
+ child;
1628
+ while (--i >= 0) {
1629
+ child = children[i]._tree;
1630
+ child.prelim += shift;
1631
+ child.mod += shift;
1632
+ shift += child.shift + (change += child.change);
1633
+ }
1634
+ }
1635
+
1636
+ function d3_layout_treeMove(ancestor, node, shift) {
1637
+ ancestor = ancestor._tree;
1638
+ node = node._tree;
1639
+ var change = shift / (node.number - ancestor.number);
1640
+ ancestor.change += change;
1641
+ node.change -= change;
1642
+ node.shift += shift;
1643
+ node.prelim += shift;
1644
+ node.mod += shift;
1645
+ }
1646
+
1647
+ function d3_layout_treeAncestor(vim, node, ancestor) {
1648
+ return vim._tree.ancestor.parent == node.parent
1649
+ ? vim._tree.ancestor
1650
+ : ancestor;
1651
+ }
1652
+ // Squarified Treemaps by Mark Bruls, Kees Huizing, and Jarke J. van Wijk
1653
+ // Modified to support a target aspect ratio by Jeff Heer
1654
+ d3.layout.treemap = function() {
1655
+ var hierarchy = d3.layout.hierarchy(),
1656
+ round = Math.round,
1657
+ size = [1, 1], // width, height
1658
+ padding = null,
1659
+ pad = d3_layout_treemapPadNull,
1660
+ sticky = false,
1661
+ stickies,
1662
+ ratio = 0.5 * (1 + Math.sqrt(5)); // golden ratio
1663
+
1664
+ // Compute the area for each child based on value & scale.
1665
+ function scale(children, k) {
1666
+ var i = -1,
1667
+ n = children.length,
1668
+ child,
1669
+ area;
1670
+ while (++i < n) {
1671
+ area = (child = children[i]).value * (k < 0 ? 0 : k);
1672
+ child.area = isNaN(area) || area <= 0 ? 0 : area;
1673
+ }
1674
+ }
1675
+
1676
+ // Recursively arranges the specified node's children into squarified rows.
1677
+ function squarify(node) {
1678
+ if (!node.children) return;
1679
+ var rect = pad(node),
1680
+ row = [],
1681
+ children = node.children.slice(), // copy-on-write
1682
+ child,
1683
+ best = Infinity, // the best row score so far
1684
+ score, // the current row score
1685
+ u = Math.min(rect.dx, rect.dy), // initial orientation
1686
+ n;
1687
+ scale(children, rect.dx * rect.dy / node.value);
1688
+ row.area = 0;
1689
+ while ((n = children.length) > 0) {
1690
+ row.push(child = children[n - 1]);
1691
+ row.area += child.area;
1692
+ if ((score = worst(row, u)) <= best) { // continue with this orientation
1693
+ children.pop();
1694
+ best = score;
1695
+ } else { // abort, and try a different orientation
1696
+ row.area -= row.pop().area;
1697
+ position(row, u, rect, false);
1698
+ u = Math.min(rect.dx, rect.dy);
1699
+ row.length = row.area = 0;
1700
+ best = Infinity;
1701
+ }
1702
+ }
1703
+ if (row.length) {
1704
+ position(row, u, rect, true);
1705
+ row.length = row.area = 0;
1706
+ }
1707
+ node.children.forEach(squarify);
1708
+ }
1709
+
1710
+ // Recursively resizes the specified node's children into existing rows.
1711
+ // Preserves the existing layout!
1712
+ function stickify(node) {
1713
+ if (!node.children) return;
1714
+ var rect = pad(node),
1715
+ children = node.children.slice(), // copy-on-write
1716
+ child,
1717
+ row = [];
1718
+ scale(children, rect.dx * rect.dy / node.value);
1719
+ row.area = 0;
1720
+ while (child = children.pop()) {
1721
+ row.push(child);
1722
+ row.area += child.area;
1723
+ if (child.z != null) {
1724
+ position(row, child.z ? rect.dx : rect.dy, rect, !children.length);
1725
+ row.length = row.area = 0;
1726
+ }
1727
+ }
1728
+ node.children.forEach(stickify);
1729
+ }
1730
+
1731
+ // Computes the score for the specified row, as the worst aspect ratio.
1732
+ function worst(row, u) {
1733
+ var s = row.area,
1734
+ r,
1735
+ rmax = 0,
1736
+ rmin = Infinity,
1737
+ i = -1,
1738
+ n = row.length;
1739
+ while (++i < n) {
1740
+ if (!(r = row[i].area)) continue;
1741
+ if (r < rmin) rmin = r;
1742
+ if (r > rmax) rmax = r;
1743
+ }
1744
+ s *= s;
1745
+ u *= u;
1746
+ return s
1747
+ ? Math.max((u * rmax * ratio) / s, s / (u * rmin * ratio))
1748
+ : Infinity;
1749
+ }
1750
+
1751
+ // Positions the specified row of nodes. Modifies `rect`.
1752
+ function position(row, u, rect, flush) {
1753
+ var i = -1,
1754
+ n = row.length,
1755
+ x = rect.x,
1756
+ y = rect.y,
1757
+ v = u ? round(row.area / u) : 0,
1758
+ o;
1759
+ if (u == rect.dx) { // horizontal subdivision
1760
+ if (flush || v > rect.dy) v = v ? rect.dy : 0; // over+underflow
1761
+ while (++i < n) {
1762
+ o = row[i];
1763
+ o.x = x;
1764
+ o.y = y;
1765
+ o.dy = v;
1766
+ x += o.dx = v ? round(o.area / v) : 0;
1767
+ }
1768
+ o.z = true;
1769
+ o.dx += rect.x + rect.dx - x; // rounding error
1770
+ rect.y += v;
1771
+ rect.dy -= v;
1772
+ } else { // vertical subdivision
1773
+ if (flush || v > rect.dx) v = v ? rect.dx : 0; // over+underflow
1774
+ while (++i < n) {
1775
+ o = row[i];
1776
+ o.x = x;
1777
+ o.y = y;
1778
+ o.dx = v;
1779
+ y += o.dy = v ? round(o.area / v) : 0;
1780
+ }
1781
+ o.z = false;
1782
+ o.dy += rect.y + rect.dy - y; // rounding error
1783
+ rect.x += v;
1784
+ rect.dx -= v;
1785
+ }
1786
+ }
1787
+
1788
+ function treemap(d) {
1789
+ var nodes = stickies || hierarchy(d),
1790
+ root = nodes[0];
1791
+ root.x = 0;
1792
+ root.y = 0;
1793
+ root.dx = size[0];
1794
+ root.dy = size[1];
1795
+ if (stickies) hierarchy.revalue(root);
1796
+ scale([root], root.dx * root.dy / root.value);
1797
+ (stickies ? stickify : squarify)(root);
1798
+ if (sticky) stickies = nodes;
1799
+ return nodes;
1800
+ }
1801
+
1802
+ treemap.size = function(x) {
1803
+ if (!arguments.length) return size;
1804
+ size = x;
1805
+ return treemap;
1806
+ };
1807
+
1808
+ treemap.padding = function(x) {
1809
+ if (!arguments.length) return padding;
1810
+
1811
+ function padFunction(node) {
1812
+ var p = x.call(treemap, node, node.depth);
1813
+ return p == null
1814
+ ? d3_layout_treemapPadNull(node)
1815
+ : d3_layout_treemapPad(node, typeof p === "number" ? [p, p, p, p] : p);
1816
+ }
1817
+
1818
+ function padConstant(node) {
1819
+ return d3_layout_treemapPad(node, x);
1820
+ }
1821
+
1822
+ var type;
1823
+ pad = (padding = x) == null ? d3_layout_treemapPadNull
1824
+ : (type = typeof x) === "function" ? padFunction
1825
+ : type === "number" ? (x = [x, x, x, x], padConstant)
1826
+ : padConstant;
1827
+ return treemap;
1828
+ };
1829
+
1830
+ treemap.round = function(x) {
1831
+ if (!arguments.length) return round != Number;
1832
+ round = x ? Math.round : Number;
1833
+ return treemap;
1834
+ };
1835
+
1836
+ treemap.sticky = function(x) {
1837
+ if (!arguments.length) return sticky;
1838
+ sticky = x;
1839
+ stickies = null;
1840
+ return treemap;
1841
+ };
1842
+
1843
+ treemap.ratio = function(x) {
1844
+ if (!arguments.length) return ratio;
1845
+ ratio = x;
1846
+ return treemap;
1847
+ };
1848
+
1849
+ return d3_layout_hierarchyRebind(treemap, hierarchy);
1850
+ };
1851
+
1852
+ function d3_layout_treemapPadNull(node) {
1853
+ return {x: node.x, y: node.y, dx: node.dx, dy: node.dy};
1854
+ }
1855
+
1856
+ function d3_layout_treemapPad(node, padding) {
1857
+ var x = node.x + padding[3],
1858
+ y = node.y + padding[0],
1859
+ dx = node.dx - padding[1] - padding[3],
1860
+ dy = node.dy - padding[0] - padding[2];
1861
+ if (dx < 0) { x += dx / 2; dx = 0; }
1862
+ if (dy < 0) { y += dy / 2; dy = 0; }
1863
+ return {x: x, y: y, dx: dx, dy: dy};
1864
+ }
1865
+ })();