tree.rb 0.3.8 → 0.3.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1890 +0,0 @@
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
- })();