d3_rails 0.0.1 → 0.0.2

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