source: node_modules/d3-hierarchy/dist/d3-hierarchy.js@ e4c61dd

Last change on this file since e4c61dd was e4c61dd, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Prototype 1.1

  • Property mode set to 100644
File size: 36.0 KB
Line 
1// https://d3js.org/d3-hierarchy/ v3.1.2 Copyright 2010-2021 Mike Bostock
2(function (global, factory) {
3typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
4typeof define === 'function' && define.amd ? define(['exports'], factory) :
5(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.d3 = global.d3 || {}));
6})(this, (function (exports) { 'use strict';
7
8function defaultSeparation$1(a, b) {
9 return a.parent === b.parent ? 1 : 2;
10}
11
12function meanX(children) {
13 return children.reduce(meanXReduce, 0) / children.length;
14}
15
16function meanXReduce(x, c) {
17 return x + c.x;
18}
19
20function maxY(children) {
21 return 1 + children.reduce(maxYReduce, 0);
22}
23
24function maxYReduce(y, c) {
25 return Math.max(y, c.y);
26}
27
28function leafLeft(node) {
29 var children;
30 while (children = node.children) node = children[0];
31 return node;
32}
33
34function leafRight(node) {
35 var children;
36 while (children = node.children) node = children[children.length - 1];
37 return node;
38}
39
40function cluster() {
41 var separation = defaultSeparation$1,
42 dx = 1,
43 dy = 1,
44 nodeSize = false;
45
46 function cluster(root) {
47 var previousNode,
48 x = 0;
49
50 // First walk, computing the initial x & y values.
51 root.eachAfter(function(node) {
52 var children = node.children;
53 if (children) {
54 node.x = meanX(children);
55 node.y = maxY(children);
56 } else {
57 node.x = previousNode ? x += separation(node, previousNode) : 0;
58 node.y = 0;
59 previousNode = node;
60 }
61 });
62
63 var left = leafLeft(root),
64 right = leafRight(root),
65 x0 = left.x - separation(left, right) / 2,
66 x1 = right.x + separation(right, left) / 2;
67
68 // Second walk, normalizing x & y to the desired size.
69 return root.eachAfter(nodeSize ? function(node) {
70 node.x = (node.x - root.x) * dx;
71 node.y = (root.y - node.y) * dy;
72 } : function(node) {
73 node.x = (node.x - x0) / (x1 - x0) * dx;
74 node.y = (1 - (root.y ? node.y / root.y : 1)) * dy;
75 });
76 }
77
78 cluster.separation = function(x) {
79 return arguments.length ? (separation = x, cluster) : separation;
80 };
81
82 cluster.size = function(x) {
83 return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]);
84 };
85
86 cluster.nodeSize = function(x) {
87 return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null);
88 };
89
90 return cluster;
91}
92
93function count(node) {
94 var sum = 0,
95 children = node.children,
96 i = children && children.length;
97 if (!i) sum = 1;
98 else while (--i >= 0) sum += children[i].value;
99 node.value = sum;
100}
101
102function node_count() {
103 return this.eachAfter(count);
104}
105
106function node_each(callback, that) {
107 let index = -1;
108 for (const node of this) {
109 callback.call(that, node, ++index, this);
110 }
111 return this;
112}
113
114function node_eachBefore(callback, that) {
115 var node = this, nodes = [node], children, i, index = -1;
116 while (node = nodes.pop()) {
117 callback.call(that, node, ++index, this);
118 if (children = node.children) {
119 for (i = children.length - 1; i >= 0; --i) {
120 nodes.push(children[i]);
121 }
122 }
123 }
124 return this;
125}
126
127function node_eachAfter(callback, that) {
128 var node = this, nodes = [node], next = [], children, i, n, index = -1;
129 while (node = nodes.pop()) {
130 next.push(node);
131 if (children = node.children) {
132 for (i = 0, n = children.length; i < n; ++i) {
133 nodes.push(children[i]);
134 }
135 }
136 }
137 while (node = next.pop()) {
138 callback.call(that, node, ++index, this);
139 }
140 return this;
141}
142
143function node_find(callback, that) {
144 let index = -1;
145 for (const node of this) {
146 if (callback.call(that, node, ++index, this)) {
147 return node;
148 }
149 }
150}
151
152function node_sum(value) {
153 return this.eachAfter(function(node) {
154 var sum = +value(node.data) || 0,
155 children = node.children,
156 i = children && children.length;
157 while (--i >= 0) sum += children[i].value;
158 node.value = sum;
159 });
160}
161
162function node_sort(compare) {
163 return this.eachBefore(function(node) {
164 if (node.children) {
165 node.children.sort(compare);
166 }
167 });
168}
169
170function node_path(end) {
171 var start = this,
172 ancestor = leastCommonAncestor(start, end),
173 nodes = [start];
174 while (start !== ancestor) {
175 start = start.parent;
176 nodes.push(start);
177 }
178 var k = nodes.length;
179 while (end !== ancestor) {
180 nodes.splice(k, 0, end);
181 end = end.parent;
182 }
183 return nodes;
184}
185
186function leastCommonAncestor(a, b) {
187 if (a === b) return a;
188 var aNodes = a.ancestors(),
189 bNodes = b.ancestors(),
190 c = null;
191 a = aNodes.pop();
192 b = bNodes.pop();
193 while (a === b) {
194 c = a;
195 a = aNodes.pop();
196 b = bNodes.pop();
197 }
198 return c;
199}
200
201function node_ancestors() {
202 var node = this, nodes = [node];
203 while (node = node.parent) {
204 nodes.push(node);
205 }
206 return nodes;
207}
208
209function node_descendants() {
210 return Array.from(this);
211}
212
213function node_leaves() {
214 var leaves = [];
215 this.eachBefore(function(node) {
216 if (!node.children) {
217 leaves.push(node);
218 }
219 });
220 return leaves;
221}
222
223function node_links() {
224 var root = this, links = [];
225 root.each(function(node) {
226 if (node !== root) { // Don’t include the root’s parent, if any.
227 links.push({source: node.parent, target: node});
228 }
229 });
230 return links;
231}
232
233function* node_iterator() {
234 var node = this, current, next = [node], children, i, n;
235 do {
236 current = next.reverse(), next = [];
237 while (node = current.pop()) {
238 yield node;
239 if (children = node.children) {
240 for (i = 0, n = children.length; i < n; ++i) {
241 next.push(children[i]);
242 }
243 }
244 }
245 } while (next.length);
246}
247
248function hierarchy(data, children) {
249 if (data instanceof Map) {
250 data = [undefined, data];
251 if (children === undefined) children = mapChildren;
252 } else if (children === undefined) {
253 children = objectChildren;
254 }
255
256 var root = new Node$1(data),
257 node,
258 nodes = [root],
259 child,
260 childs,
261 i,
262 n;
263
264 while (node = nodes.pop()) {
265 if ((childs = children(node.data)) && (n = (childs = Array.from(childs)).length)) {
266 node.children = childs;
267 for (i = n - 1; i >= 0; --i) {
268 nodes.push(child = childs[i] = new Node$1(childs[i]));
269 child.parent = node;
270 child.depth = node.depth + 1;
271 }
272 }
273 }
274
275 return root.eachBefore(computeHeight);
276}
277
278function node_copy() {
279 return hierarchy(this).eachBefore(copyData);
280}
281
282function objectChildren(d) {
283 return d.children;
284}
285
286function mapChildren(d) {
287 return Array.isArray(d) ? d[1] : null;
288}
289
290function copyData(node) {
291 if (node.data.value !== undefined) node.value = node.data.value;
292 node.data = node.data.data;
293}
294
295function computeHeight(node) {
296 var height = 0;
297 do node.height = height;
298 while ((node = node.parent) && (node.height < ++height));
299}
300
301function Node$1(data) {
302 this.data = data;
303 this.depth =
304 this.height = 0;
305 this.parent = null;
306}
307
308Node$1.prototype = hierarchy.prototype = {
309 constructor: Node$1,
310 count: node_count,
311 each: node_each,
312 eachAfter: node_eachAfter,
313 eachBefore: node_eachBefore,
314 find: node_find,
315 sum: node_sum,
316 sort: node_sort,
317 path: node_path,
318 ancestors: node_ancestors,
319 descendants: node_descendants,
320 leaves: node_leaves,
321 links: node_links,
322 copy: node_copy,
323 [Symbol.iterator]: node_iterator
324};
325
326function optional(f) {
327 return f == null ? null : required(f);
328}
329
330function required(f) {
331 if (typeof f !== "function") throw new Error;
332 return f;
333}
334
335function constantZero() {
336 return 0;
337}
338
339function constant(x) {
340 return function() {
341 return x;
342 };
343}
344
345// https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
346const a = 1664525;
347const c = 1013904223;
348const m = 4294967296; // 2^32
349
350function lcg() {
351 let s = 1;
352 return () => (s = (a * s + c) % m) / m;
353}
354
355function array(x) {
356 return typeof x === "object" && "length" in x
357 ? x // Array, TypedArray, NodeList, array-like
358 : Array.from(x); // Map, Set, iterable, string, or anything else
359}
360
361function shuffle(array, random) {
362 let m = array.length,
363 t,
364 i;
365
366 while (m) {
367 i = random() * m-- | 0;
368 t = array[m];
369 array[m] = array[i];
370 array[i] = t;
371 }
372
373 return array;
374}
375
376function enclose(circles) {
377 return packEncloseRandom(circles, lcg());
378}
379
380function packEncloseRandom(circles, random) {
381 var i = 0, n = (circles = shuffle(Array.from(circles), random)).length, B = [], p, e;
382
383 while (i < n) {
384 p = circles[i];
385 if (e && enclosesWeak(e, p)) ++i;
386 else e = encloseBasis(B = extendBasis(B, p)), i = 0;
387 }
388
389 return e;
390}
391
392function extendBasis(B, p) {
393 var i, j;
394
395 if (enclosesWeakAll(p, B)) return [p];
396
397 // If we get here then B must have at least one element.
398 for (i = 0; i < B.length; ++i) {
399 if (enclosesNot(p, B[i])
400 && enclosesWeakAll(encloseBasis2(B[i], p), B)) {
401 return [B[i], p];
402 }
403 }
404
405 // If we get here then B must have at least two elements.
406 for (i = 0; i < B.length - 1; ++i) {
407 for (j = i + 1; j < B.length; ++j) {
408 if (enclosesNot(encloseBasis2(B[i], B[j]), p)
409 && enclosesNot(encloseBasis2(B[i], p), B[j])
410 && enclosesNot(encloseBasis2(B[j], p), B[i])
411 && enclosesWeakAll(encloseBasis3(B[i], B[j], p), B)) {
412 return [B[i], B[j], p];
413 }
414 }
415 }
416
417 // If we get here then something is very wrong.
418 throw new Error;
419}
420
421function enclosesNot(a, b) {
422 var dr = a.r - b.r, dx = b.x - a.x, dy = b.y - a.y;
423 return dr < 0 || dr * dr < dx * dx + dy * dy;
424}
425
426function enclosesWeak(a, b) {
427 var dr = a.r - b.r + Math.max(a.r, b.r, 1) * 1e-9, dx = b.x - a.x, dy = b.y - a.y;
428 return dr > 0 && dr * dr > dx * dx + dy * dy;
429}
430
431function enclosesWeakAll(a, B) {
432 for (var i = 0; i < B.length; ++i) {
433 if (!enclosesWeak(a, B[i])) {
434 return false;
435 }
436 }
437 return true;
438}
439
440function encloseBasis(B) {
441 switch (B.length) {
442 case 1: return encloseBasis1(B[0]);
443 case 2: return encloseBasis2(B[0], B[1]);
444 case 3: return encloseBasis3(B[0], B[1], B[2]);
445 }
446}
447
448function encloseBasis1(a) {
449 return {
450 x: a.x,
451 y: a.y,
452 r: a.r
453 };
454}
455
456function encloseBasis2(a, b) {
457 var x1 = a.x, y1 = a.y, r1 = a.r,
458 x2 = b.x, y2 = b.y, r2 = b.r,
459 x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1,
460 l = Math.sqrt(x21 * x21 + y21 * y21);
461 return {
462 x: (x1 + x2 + x21 / l * r21) / 2,
463 y: (y1 + y2 + y21 / l * r21) / 2,
464 r: (l + r1 + r2) / 2
465 };
466}
467
468function encloseBasis3(a, b, c) {
469 var x1 = a.x, y1 = a.y, r1 = a.r,
470 x2 = b.x, y2 = b.y, r2 = b.r,
471 x3 = c.x, y3 = c.y, r3 = c.r,
472 a2 = x1 - x2,
473 a3 = x1 - x3,
474 b2 = y1 - y2,
475 b3 = y1 - y3,
476 c2 = r2 - r1,
477 c3 = r3 - r1,
478 d1 = x1 * x1 + y1 * y1 - r1 * r1,
479 d2 = d1 - x2 * x2 - y2 * y2 + r2 * r2,
480 d3 = d1 - x3 * x3 - y3 * y3 + r3 * r3,
481 ab = a3 * b2 - a2 * b3,
482 xa = (b2 * d3 - b3 * d2) / (ab * 2) - x1,
483 xb = (b3 * c2 - b2 * c3) / ab,
484 ya = (a3 * d2 - a2 * d3) / (ab * 2) - y1,
485 yb = (a2 * c3 - a3 * c2) / ab,
486 A = xb * xb + yb * yb - 1,
487 B = 2 * (r1 + xa * xb + ya * yb),
488 C = xa * xa + ya * ya - r1 * r1,
489 r = -(Math.abs(A) > 1e-6 ? (B + Math.sqrt(B * B - 4 * A * C)) / (2 * A) : C / B);
490 return {
491 x: x1 + xa + xb * r,
492 y: y1 + ya + yb * r,
493 r: r
494 };
495}
496
497function place(b, a, c) {
498 var dx = b.x - a.x, x, a2,
499 dy = b.y - a.y, y, b2,
500 d2 = dx * dx + dy * dy;
501 if (d2) {
502 a2 = a.r + c.r, a2 *= a2;
503 b2 = b.r + c.r, b2 *= b2;
504 if (a2 > b2) {
505 x = (d2 + b2 - a2) / (2 * d2);
506 y = Math.sqrt(Math.max(0, b2 / d2 - x * x));
507 c.x = b.x - x * dx - y * dy;
508 c.y = b.y - x * dy + y * dx;
509 } else {
510 x = (d2 + a2 - b2) / (2 * d2);
511 y = Math.sqrt(Math.max(0, a2 / d2 - x * x));
512 c.x = a.x + x * dx - y * dy;
513 c.y = a.y + x * dy + y * dx;
514 }
515 } else {
516 c.x = a.x + c.r;
517 c.y = a.y;
518 }
519}
520
521function intersects(a, b) {
522 var dr = a.r + b.r - 1e-6, dx = b.x - a.x, dy = b.y - a.y;
523 return dr > 0 && dr * dr > dx * dx + dy * dy;
524}
525
526function score(node) {
527 var a = node._,
528 b = node.next._,
529 ab = a.r + b.r,
530 dx = (a.x * b.r + b.x * a.r) / ab,
531 dy = (a.y * b.r + b.y * a.r) / ab;
532 return dx * dx + dy * dy;
533}
534
535function Node(circle) {
536 this._ = circle;
537 this.next = null;
538 this.previous = null;
539}
540
541function packSiblingsRandom(circles, random) {
542 if (!(n = (circles = array(circles)).length)) return 0;
543
544 var a, b, c, n, aa, ca, i, j, k, sj, sk;
545
546 // Place the first circle.
547 a = circles[0], a.x = 0, a.y = 0;
548 if (!(n > 1)) return a.r;
549
550 // Place the second circle.
551 b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0;
552 if (!(n > 2)) return a.r + b.r;
553
554 // Place the third circle.
555 place(b, a, c = circles[2]);
556
557 // Initialize the front-chain using the first three circles a, b and c.
558 a = new Node(a), b = new Node(b), c = new Node(c);
559 a.next = c.previous = b;
560 b.next = a.previous = c;
561 c.next = b.previous = a;
562
563 // Attempt to place each remaining circle…
564 pack: for (i = 3; i < n; ++i) {
565 place(a._, b._, c = circles[i]), c = new Node(c);
566
567 // Find the closest intersecting circle on the front-chain, if any.
568 // “Closeness” is determined by linear distance along the front-chain.
569 // “Ahead” or “behind” is likewise determined by linear distance.
570 j = b.next, k = a.previous, sj = b._.r, sk = a._.r;
571 do {
572 if (sj <= sk) {
573 if (intersects(j._, c._)) {
574 b = j, a.next = b, b.previous = a, --i;
575 continue pack;
576 }
577 sj += j._.r, j = j.next;
578 } else {
579 if (intersects(k._, c._)) {
580 a = k, a.next = b, b.previous = a, --i;
581 continue pack;
582 }
583 sk += k._.r, k = k.previous;
584 }
585 } while (j !== k.next);
586
587 // Success! Insert the new circle c between a and b.
588 c.previous = a, c.next = b, a.next = b.previous = b = c;
589
590 // Compute the new closest circle pair to the centroid.
591 aa = score(a);
592 while ((c = c.next) !== b) {
593 if ((ca = score(c)) < aa) {
594 a = c, aa = ca;
595 }
596 }
597 b = a.next;
598 }
599
600 // Compute the enclosing circle of the front chain.
601 a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = packEncloseRandom(a, random);
602
603 // Translate the circles to put the enclosing circle around the origin.
604 for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y;
605
606 return c.r;
607}
608
609function siblings(circles) {
610 packSiblingsRandom(circles, lcg());
611 return circles;
612}
613
614function defaultRadius(d) {
615 return Math.sqrt(d.value);
616}
617
618function index$1() {
619 var radius = null,
620 dx = 1,
621 dy = 1,
622 padding = constantZero;
623
624 function pack(root) {
625 const random = lcg();
626 root.x = dx / 2, root.y = dy / 2;
627 if (radius) {
628 root.eachBefore(radiusLeaf(radius))
629 .eachAfter(packChildrenRandom(padding, 0.5, random))
630 .eachBefore(translateChild(1));
631 } else {
632 root.eachBefore(radiusLeaf(defaultRadius))
633 .eachAfter(packChildrenRandom(constantZero, 1, random))
634 .eachAfter(packChildrenRandom(padding, root.r / Math.min(dx, dy), random))
635 .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r)));
636 }
637 return root;
638 }
639
640 pack.radius = function(x) {
641 return arguments.length ? (radius = optional(x), pack) : radius;
642 };
643
644 pack.size = function(x) {
645 return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy];
646 };
647
648 pack.padding = function(x) {
649 return arguments.length ? (padding = typeof x === "function" ? x : constant(+x), pack) : padding;
650 };
651
652 return pack;
653}
654
655function radiusLeaf(radius) {
656 return function(node) {
657 if (!node.children) {
658 node.r = Math.max(0, +radius(node) || 0);
659 }
660 };
661}
662
663function packChildrenRandom(padding, k, random) {
664 return function(node) {
665 if (children = node.children) {
666 var children,
667 i,
668 n = children.length,
669 r = padding(node) * k || 0,
670 e;
671
672 if (r) for (i = 0; i < n; ++i) children[i].r += r;
673 e = packSiblingsRandom(children, random);
674 if (r) for (i = 0; i < n; ++i) children[i].r -= r;
675 node.r = e + r;
676 }
677 };
678}
679
680function translateChild(k) {
681 return function(node) {
682 var parent = node.parent;
683 node.r *= k;
684 if (parent) {
685 node.x = parent.x + k * node.x;
686 node.y = parent.y + k * node.y;
687 }
688 };
689}
690
691function roundNode(node) {
692 node.x0 = Math.round(node.x0);
693 node.y0 = Math.round(node.y0);
694 node.x1 = Math.round(node.x1);
695 node.y1 = Math.round(node.y1);
696}
697
698function treemapDice(parent, x0, y0, x1, y1) {
699 var nodes = parent.children,
700 node,
701 i = -1,
702 n = nodes.length,
703 k = parent.value && (x1 - x0) / parent.value;
704
705 while (++i < n) {
706 node = nodes[i], node.y0 = y0, node.y1 = y1;
707 node.x0 = x0, node.x1 = x0 += node.value * k;
708 }
709}
710
711function partition() {
712 var dx = 1,
713 dy = 1,
714 padding = 0,
715 round = false;
716
717 function partition(root) {
718 var n = root.height + 1;
719 root.x0 =
720 root.y0 = padding;
721 root.x1 = dx;
722 root.y1 = dy / n;
723 root.eachBefore(positionNode(dy, n));
724 if (round) root.eachBefore(roundNode);
725 return root;
726 }
727
728 function positionNode(dy, n) {
729 return function(node) {
730 if (node.children) {
731 treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n);
732 }
733 var x0 = node.x0,
734 y0 = node.y0,
735 x1 = node.x1 - padding,
736 y1 = node.y1 - padding;
737 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
738 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
739 node.x0 = x0;
740 node.y0 = y0;
741 node.x1 = x1;
742 node.y1 = y1;
743 };
744 }
745
746 partition.round = function(x) {
747 return arguments.length ? (round = !!x, partition) : round;
748 };
749
750 partition.size = function(x) {
751 return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy];
752 };
753
754 partition.padding = function(x) {
755 return arguments.length ? (padding = +x, partition) : padding;
756 };
757
758 return partition;
759}
760
761var preroot = {depth: -1},
762 ambiguous = {},
763 imputed = {};
764
765function defaultId(d) {
766 return d.id;
767}
768
769function defaultParentId(d) {
770 return d.parentId;
771}
772
773function stratify() {
774 var id = defaultId,
775 parentId = defaultParentId,
776 path;
777
778 function stratify(data) {
779 var nodes = Array.from(data),
780 currentId = id,
781 currentParentId = parentId,
782 n,
783 d,
784 i,
785 root,
786 parent,
787 node,
788 nodeId,
789 nodeKey,
790 nodeByKey = new Map;
791
792 if (path != null) {
793 const I = nodes.map((d, i) => normalize(path(d, i, data)));
794 const P = I.map(parentof);
795 const S = new Set(I).add("");
796 for (const i of P) {
797 if (!S.has(i)) {
798 S.add(i);
799 I.push(i);
800 P.push(parentof(i));
801 nodes.push(imputed);
802 }
803 }
804 currentId = (_, i) => I[i];
805 currentParentId = (_, i) => P[i];
806 }
807
808 for (i = 0, n = nodes.length; i < n; ++i) {
809 d = nodes[i], node = nodes[i] = new Node$1(d);
810 if ((nodeId = currentId(d, i, data)) != null && (nodeId += "")) {
811 nodeKey = node.id = nodeId;
812 nodeByKey.set(nodeKey, nodeByKey.has(nodeKey) ? ambiguous : node);
813 }
814 if ((nodeId = currentParentId(d, i, data)) != null && (nodeId += "")) {
815 node.parent = nodeId;
816 }
817 }
818
819 for (i = 0; i < n; ++i) {
820 node = nodes[i];
821 if (nodeId = node.parent) {
822 parent = nodeByKey.get(nodeId);
823 if (!parent) throw new Error("missing: " + nodeId);
824 if (parent === ambiguous) throw new Error("ambiguous: " + nodeId);
825 if (parent.children) parent.children.push(node);
826 else parent.children = [node];
827 node.parent = parent;
828 } else {
829 if (root) throw new Error("multiple roots");
830 root = node;
831 }
832 }
833
834 if (!root) throw new Error("no root");
835
836 // When imputing internal nodes, only introduce roots if needed.
837 // Then replace the imputed marker data with null.
838 if (path != null) {
839 while (root.data === imputed && root.children.length === 1) {
840 root = root.children[0], --n;
841 }
842 for (let i = nodes.length - 1; i >= 0; --i) {
843 node = nodes[i];
844 if (node.data !== imputed) break;
845 node.data = null;
846 }
847 }
848
849 root.parent = preroot;
850 root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight);
851 root.parent = null;
852 if (n > 0) throw new Error("cycle");
853
854 return root;
855 }
856
857 stratify.id = function(x) {
858 return arguments.length ? (id = optional(x), stratify) : id;
859 };
860
861 stratify.parentId = function(x) {
862 return arguments.length ? (parentId = optional(x), stratify) : parentId;
863 };
864
865 stratify.path = function(x) {
866 return arguments.length ? (path = optional(x), stratify) : path;
867 };
868
869 return stratify;
870}
871
872// To normalize a path, we coerce to a string, strip the trailing slash if any
873// (as long as the trailing slash is not immediately preceded by another slash),
874// and add leading slash if missing.
875function normalize(path) {
876 path = `${path}`;
877 let i = path.length;
878 if (slash(path, i - 1) && !slash(path, i - 2)) path = path.slice(0, -1);
879 return path[0] === "/" ? path : `/${path}`;
880}
881
882// Walk backwards to find the first slash that is not the leading slash, e.g.:
883// "/foo/bar" ⇥ "/foo", "/foo" ⇥ "/", "/" ↦ "". (The root is special-cased
884// because the id of the root must be a truthy value.)
885function parentof(path) {
886 let i = path.length;
887 if (i < 2) return "";
888 while (--i > 1) if (slash(path, i)) break;
889 return path.slice(0, i);
890}
891
892// Slashes can be escaped; to determine whether a slash is a path delimiter, we
893// count the number of preceding backslashes escaping the forward slash: an odd
894// number indicates an escaped forward slash.
895function slash(path, i) {
896 if (path[i] === "/") {
897 let k = 0;
898 while (i > 0 && path[--i] === "\\") ++k;
899 if ((k & 1) === 0) return true;
900 }
901 return false;
902}
903
904function defaultSeparation(a, b) {
905 return a.parent === b.parent ? 1 : 2;
906}
907
908// function radialSeparation(a, b) {
909// return (a.parent === b.parent ? 1 : 2) / a.depth;
910// }
911
912// This function is used to traverse the left contour of a subtree (or
913// subforest). It returns the successor of v on this contour. This successor is
914// either given by the leftmost child of v or by the thread of v. The function
915// returns null if and only if v is on the highest level of its subtree.
916function nextLeft(v) {
917 var children = v.children;
918 return children ? children[0] : v.t;
919}
920
921// This function works analogously to nextLeft.
922function nextRight(v) {
923 var children = v.children;
924 return children ? children[children.length - 1] : v.t;
925}
926
927// Shifts the current subtree rooted at w+. This is done by increasing
928// prelim(w+) and mod(w+) by shift.
929function moveSubtree(wm, wp, shift) {
930 var change = shift / (wp.i - wm.i);
931 wp.c -= change;
932 wp.s += shift;
933 wm.c += change;
934 wp.z += shift;
935 wp.m += shift;
936}
937
938// All other shifts, applied to the smaller subtrees between w- and w+, are
939// performed by this function. To prepare the shifts, we have to adjust
940// change(w+), shift(w+), and change(w-).
941function executeShifts(v) {
942 var shift = 0,
943 change = 0,
944 children = v.children,
945 i = children.length,
946 w;
947 while (--i >= 0) {
948 w = children[i];
949 w.z += shift;
950 w.m += shift;
951 shift += w.s + (change += w.c);
952 }
953}
954
955// If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise,
956// returns the specified (default) ancestor.
957function nextAncestor(vim, v, ancestor) {
958 return vim.a.parent === v.parent ? vim.a : ancestor;
959}
960
961function TreeNode(node, i) {
962 this._ = node;
963 this.parent = null;
964 this.children = null;
965 this.A = null; // default ancestor
966 this.a = this; // ancestor
967 this.z = 0; // prelim
968 this.m = 0; // mod
969 this.c = 0; // change
970 this.s = 0; // shift
971 this.t = null; // thread
972 this.i = i; // number
973}
974
975TreeNode.prototype = Object.create(Node$1.prototype);
976
977function treeRoot(root) {
978 var tree = new TreeNode(root, 0),
979 node,
980 nodes = [tree],
981 child,
982 children,
983 i,
984 n;
985
986 while (node = nodes.pop()) {
987 if (children = node._.children) {
988 node.children = new Array(n = children.length);
989 for (i = n - 1; i >= 0; --i) {
990 nodes.push(child = node.children[i] = new TreeNode(children[i], i));
991 child.parent = node;
992 }
993 }
994 }
995
996 (tree.parent = new TreeNode(null, 0)).children = [tree];
997 return tree;
998}
999
1000// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
1001function tree() {
1002 var separation = defaultSeparation,
1003 dx = 1,
1004 dy = 1,
1005 nodeSize = null;
1006
1007 function tree(root) {
1008 var t = treeRoot(root);
1009
1010 // Compute the layout using Buchheim et al.’s algorithm.
1011 t.eachAfter(firstWalk), t.parent.m = -t.z;
1012 t.eachBefore(secondWalk);
1013
1014 // If a fixed node size is specified, scale x and y.
1015 if (nodeSize) root.eachBefore(sizeNode);
1016
1017 // If a fixed tree size is specified, scale x and y based on the extent.
1018 // Compute the left-most, right-most, and depth-most nodes for extents.
1019 else {
1020 var left = root,
1021 right = root,
1022 bottom = root;
1023 root.eachBefore(function(node) {
1024 if (node.x < left.x) left = node;
1025 if (node.x > right.x) right = node;
1026 if (node.depth > bottom.depth) bottom = node;
1027 });
1028 var s = left === right ? 1 : separation(left, right) / 2,
1029 tx = s - left.x,
1030 kx = dx / (right.x + s + tx),
1031 ky = dy / (bottom.depth || 1);
1032 root.eachBefore(function(node) {
1033 node.x = (node.x + tx) * kx;
1034 node.y = node.depth * ky;
1035 });
1036 }
1037
1038 return root;
1039 }
1040
1041 // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is
1042 // applied recursively to the children of v, as well as the function
1043 // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the
1044 // node v is placed to the midpoint of its outermost children.
1045 function firstWalk(v) {
1046 var children = v.children,
1047 siblings = v.parent.children,
1048 w = v.i ? siblings[v.i - 1] : null;
1049 if (children) {
1050 executeShifts(v);
1051 var midpoint = (children[0].z + children[children.length - 1].z) / 2;
1052 if (w) {
1053 v.z = w.z + separation(v._, w._);
1054 v.m = v.z - midpoint;
1055 } else {
1056 v.z = midpoint;
1057 }
1058 } else if (w) {
1059 v.z = w.z + separation(v._, w._);
1060 }
1061 v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
1062 }
1063
1064 // Computes all real x-coordinates by summing up the modifiers recursively.
1065 function secondWalk(v) {
1066 v._.x = v.z + v.parent.m;
1067 v.m += v.parent.m;
1068 }
1069
1070 // The core of the algorithm. Here, a new subtree is combined with the
1071 // previous subtrees. Threads are used to traverse the inside and outside
1072 // contours of the left and right subtree up to the highest common level. The
1073 // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the
1074 // superscript o means outside and i means inside, the subscript - means left
1075 // subtree and + means right subtree. For summing up the modifiers along the
1076 // contour, we use respective variables si+, si-, so-, and so+. Whenever two
1077 // nodes of the inside contours conflict, we compute the left one of the
1078 // greatest uncommon ancestors using the function ANCESTOR and call MOVE
1079 // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees.
1080 // Finally, we add a new thread (if necessary).
1081 function apportion(v, w, ancestor) {
1082 if (w) {
1083 var vip = v,
1084 vop = v,
1085 vim = w,
1086 vom = vip.parent.children[0],
1087 sip = vip.m,
1088 sop = vop.m,
1089 sim = vim.m,
1090 som = vom.m,
1091 shift;
1092 while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {
1093 vom = nextLeft(vom);
1094 vop = nextRight(vop);
1095 vop.a = v;
1096 shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
1097 if (shift > 0) {
1098 moveSubtree(nextAncestor(vim, v, ancestor), v, shift);
1099 sip += shift;
1100 sop += shift;
1101 }
1102 sim += vim.m;
1103 sip += vip.m;
1104 som += vom.m;
1105 sop += vop.m;
1106 }
1107 if (vim && !nextRight(vop)) {
1108 vop.t = vim;
1109 vop.m += sim - sop;
1110 }
1111 if (vip && !nextLeft(vom)) {
1112 vom.t = vip;
1113 vom.m += sip - som;
1114 ancestor = v;
1115 }
1116 }
1117 return ancestor;
1118 }
1119
1120 function sizeNode(node) {
1121 node.x *= dx;
1122 node.y = node.depth * dy;
1123 }
1124
1125 tree.separation = function(x) {
1126 return arguments.length ? (separation = x, tree) : separation;
1127 };
1128
1129 tree.size = function(x) {
1130 return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]);
1131 };
1132
1133 tree.nodeSize = function(x) {
1134 return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null);
1135 };
1136
1137 return tree;
1138}
1139
1140function treemapSlice(parent, x0, y0, x1, y1) {
1141 var nodes = parent.children,
1142 node,
1143 i = -1,
1144 n = nodes.length,
1145 k = parent.value && (y1 - y0) / parent.value;
1146
1147 while (++i < n) {
1148 node = nodes[i], node.x0 = x0, node.x1 = x1;
1149 node.y0 = y0, node.y1 = y0 += node.value * k;
1150 }
1151}
1152
1153var phi = (1 + Math.sqrt(5)) / 2;
1154
1155function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
1156 var rows = [],
1157 nodes = parent.children,
1158 row,
1159 nodeValue,
1160 i0 = 0,
1161 i1 = 0,
1162 n = nodes.length,
1163 dx, dy,
1164 value = parent.value,
1165 sumValue,
1166 minValue,
1167 maxValue,
1168 newRatio,
1169 minRatio,
1170 alpha,
1171 beta;
1172
1173 while (i0 < n) {
1174 dx = x1 - x0, dy = y1 - y0;
1175
1176 // Find the next non-empty node.
1177 do sumValue = nodes[i1++].value; while (!sumValue && i1 < n);
1178 minValue = maxValue = sumValue;
1179 alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
1180 beta = sumValue * sumValue * alpha;
1181 minRatio = Math.max(maxValue / beta, beta / minValue);
1182
1183 // Keep adding nodes while the aspect ratio maintains or improves.
1184 for (; i1 < n; ++i1) {
1185 sumValue += nodeValue = nodes[i1].value;
1186 if (nodeValue < minValue) minValue = nodeValue;
1187 if (nodeValue > maxValue) maxValue = nodeValue;
1188 beta = sumValue * sumValue * alpha;
1189 newRatio = Math.max(maxValue / beta, beta / minValue);
1190 if (newRatio > minRatio) { sumValue -= nodeValue; break; }
1191 minRatio = newRatio;
1192 }
1193
1194 // Position and record the row orientation.
1195 rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)});
1196 if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);
1197 else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
1198 value -= sumValue, i0 = i1;
1199 }
1200
1201 return rows;
1202}
1203
1204var squarify = (function custom(ratio) {
1205
1206 function squarify(parent, x0, y0, x1, y1) {
1207 squarifyRatio(ratio, parent, x0, y0, x1, y1);
1208 }
1209
1210 squarify.ratio = function(x) {
1211 return custom((x = +x) > 1 ? x : 1);
1212 };
1213
1214 return squarify;
1215})(phi);
1216
1217function index() {
1218 var tile = squarify,
1219 round = false,
1220 dx = 1,
1221 dy = 1,
1222 paddingStack = [0],
1223 paddingInner = constantZero,
1224 paddingTop = constantZero,
1225 paddingRight = constantZero,
1226 paddingBottom = constantZero,
1227 paddingLeft = constantZero;
1228
1229 function treemap(root) {
1230 root.x0 =
1231 root.y0 = 0;
1232 root.x1 = dx;
1233 root.y1 = dy;
1234 root.eachBefore(positionNode);
1235 paddingStack = [0];
1236 if (round) root.eachBefore(roundNode);
1237 return root;
1238 }
1239
1240 function positionNode(node) {
1241 var p = paddingStack[node.depth],
1242 x0 = node.x0 + p,
1243 y0 = node.y0 + p,
1244 x1 = node.x1 - p,
1245 y1 = node.y1 - p;
1246 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
1247 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
1248 node.x0 = x0;
1249 node.y0 = y0;
1250 node.x1 = x1;
1251 node.y1 = y1;
1252 if (node.children) {
1253 p = paddingStack[node.depth + 1] = paddingInner(node) / 2;
1254 x0 += paddingLeft(node) - p;
1255 y0 += paddingTop(node) - p;
1256 x1 -= paddingRight(node) - p;
1257 y1 -= paddingBottom(node) - p;
1258 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
1259 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
1260 tile(node, x0, y0, x1, y1);
1261 }
1262 }
1263
1264 treemap.round = function(x) {
1265 return arguments.length ? (round = !!x, treemap) : round;
1266 };
1267
1268 treemap.size = function(x) {
1269 return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy];
1270 };
1271
1272 treemap.tile = function(x) {
1273 return arguments.length ? (tile = required(x), treemap) : tile;
1274 };
1275
1276 treemap.padding = function(x) {
1277 return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner();
1278 };
1279
1280 treemap.paddingInner = function(x) {
1281 return arguments.length ? (paddingInner = typeof x === "function" ? x : constant(+x), treemap) : paddingInner;
1282 };
1283
1284 treemap.paddingOuter = function(x) {
1285 return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop();
1286 };
1287
1288 treemap.paddingTop = function(x) {
1289 return arguments.length ? (paddingTop = typeof x === "function" ? x : constant(+x), treemap) : paddingTop;
1290 };
1291
1292 treemap.paddingRight = function(x) {
1293 return arguments.length ? (paddingRight = typeof x === "function" ? x : constant(+x), treemap) : paddingRight;
1294 };
1295
1296 treemap.paddingBottom = function(x) {
1297 return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant(+x), treemap) : paddingBottom;
1298 };
1299
1300 treemap.paddingLeft = function(x) {
1301 return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant(+x), treemap) : paddingLeft;
1302 };
1303
1304 return treemap;
1305}
1306
1307function binary(parent, x0, y0, x1, y1) {
1308 var nodes = parent.children,
1309 i, n = nodes.length,
1310 sum, sums = new Array(n + 1);
1311
1312 for (sums[0] = sum = i = 0; i < n; ++i) {
1313 sums[i + 1] = sum += nodes[i].value;
1314 }
1315
1316 partition(0, n, parent.value, x0, y0, x1, y1);
1317
1318 function partition(i, j, value, x0, y0, x1, y1) {
1319 if (i >= j - 1) {
1320 var node = nodes[i];
1321 node.x0 = x0, node.y0 = y0;
1322 node.x1 = x1, node.y1 = y1;
1323 return;
1324 }
1325
1326 var valueOffset = sums[i],
1327 valueTarget = (value / 2) + valueOffset,
1328 k = i + 1,
1329 hi = j - 1;
1330
1331 while (k < hi) {
1332 var mid = k + hi >>> 1;
1333 if (sums[mid] < valueTarget) k = mid + 1;
1334 else hi = mid;
1335 }
1336
1337 if ((valueTarget - sums[k - 1]) < (sums[k] - valueTarget) && i + 1 < k) --k;
1338
1339 var valueLeft = sums[k] - valueOffset,
1340 valueRight = value - valueLeft;
1341
1342 if ((x1 - x0) > (y1 - y0)) {
1343 var xk = value ? (x0 * valueRight + x1 * valueLeft) / value : x1;
1344 partition(i, k, valueLeft, x0, y0, xk, y1);
1345 partition(k, j, valueRight, xk, y0, x1, y1);
1346 } else {
1347 var yk = value ? (y0 * valueRight + y1 * valueLeft) / value : y1;
1348 partition(i, k, valueLeft, x0, y0, x1, yk);
1349 partition(k, j, valueRight, x0, yk, x1, y1);
1350 }
1351 }
1352}
1353
1354function sliceDice(parent, x0, y0, x1, y1) {
1355 (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1);
1356}
1357
1358var resquarify = (function custom(ratio) {
1359
1360 function resquarify(parent, x0, y0, x1, y1) {
1361 if ((rows = parent._squarify) && (rows.ratio === ratio)) {
1362 var rows,
1363 row,
1364 nodes,
1365 i,
1366 j = -1,
1367 n,
1368 m = rows.length,
1369 value = parent.value;
1370
1371 while (++j < m) {
1372 row = rows[j], nodes = row.children;
1373 for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value;
1374 if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += (y1 - y0) * row.value / value : y1);
1375 else treemapSlice(row, x0, y0, value ? x0 += (x1 - x0) * row.value / value : x1, y1);
1376 value -= row.value;
1377 }
1378 } else {
1379 parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1);
1380 rows.ratio = ratio;
1381 }
1382 }
1383
1384 resquarify.ratio = function(x) {
1385 return custom((x = +x) > 1 ? x : 1);
1386 };
1387
1388 return resquarify;
1389})(phi);
1390
1391exports.Node = Node$1;
1392exports.cluster = cluster;
1393exports.hierarchy = hierarchy;
1394exports.pack = index$1;
1395exports.packEnclose = enclose;
1396exports.packSiblings = siblings;
1397exports.partition = partition;
1398exports.stratify = stratify;
1399exports.tree = tree;
1400exports.treemap = index;
1401exports.treemapBinary = binary;
1402exports.treemapDice = treemapDice;
1403exports.treemapResquarify = resquarify;
1404exports.treemapSlice = treemapSlice;
1405exports.treemapSliceDice = sliceDice;
1406exports.treemapSquarify = squarify;
1407
1408Object.defineProperty(exports, '__esModule', { value: true });
1409
1410}));
Note: See TracBrowser for help on using the repository browser.