1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | var __extends = (this && this.__extends) || (function () {
|
7 | var extendStatics = function (d, b) {
|
8 | extendStatics = Object.setPrototypeOf ||
|
9 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
10 | function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
11 | return extendStatics(d, b);
|
12 | };
|
13 | return function (d, b) {
|
14 | extendStatics(d, b);
|
15 | function __() { this.constructor = d; }
|
16 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
17 | };
|
18 | })();
|
19 | Object.defineProperty(exports, "__esModule", { value: true });
|
20 | exports.ComboForceLayout = void 0;
|
21 | var base_1 = require("./base");
|
22 | var util_1 = require("../util");
|
23 |
|
24 |
|
25 |
|
26 | var ComboForceLayout = (function (_super) {
|
27 | __extends(ComboForceLayout, _super);
|
28 | function ComboForceLayout(options) {
|
29 | var _this = _super.call(this) || this;
|
30 |
|
31 | _this.center = [0, 0];
|
32 |
|
33 | _this.maxIteration = 100;
|
34 |
|
35 | _this.gravity = 10;
|
36 |
|
37 | _this.comboGravity = 10;
|
38 |
|
39 | _this.linkDistance = 10;
|
40 |
|
41 | _this.alpha = 1;
|
42 | _this.alphaMin = 0.001;
|
43 | _this.alphaDecay = 1 - Math.pow(_this.alphaMin, (1 / 300));
|
44 | _this.alphaTarget = 0;
|
45 |
|
46 | _this.velocityDecay = 0.6;
|
47 |
|
48 | _this.edgeStrength = 0.6;
|
49 |
|
50 | _this.nodeStrength = 30;
|
51 |
|
52 | _this.preventOverlap = false;
|
53 |
|
54 | _this.preventNodeOverlap = false;
|
55 |
|
56 | _this.preventComboOverlap = false;
|
57 |
|
58 | _this.collideStrength = undefined;
|
59 |
|
60 | _this.nodeCollideStrength = 0.5;
|
61 |
|
62 | _this.comboCollideStrength = 0.5;
|
63 |
|
64 | _this.comboSpacing = 20;
|
65 |
|
66 | _this.comboPadding = 10;
|
67 |
|
68 | _this.optimizeRangeFactor = 1;
|
69 |
|
70 | _this.onTick = function () { };
|
71 |
|
72 | _this.onLayoutEnd = function () { };
|
73 |
|
74 | _this.depthAttractiveForceScale = 1;
|
75 |
|
76 | _this.depthRepulsiveForceScale = 2;
|
77 |
|
78 | _this.nodes = [];
|
79 | _this.edges = [];
|
80 | _this.combos = [];
|
81 | _this.comboTrees = [];
|
82 | _this.width = 300;
|
83 | _this.height = 300;
|
84 | _this.bias = [];
|
85 | _this.nodeMap = {};
|
86 | _this.oriComboMap = {};
|
87 | _this.indexMap = {};
|
88 | _this.comboMap = {};
|
89 | _this.previousLayouted = false;
|
90 | _this.updateCfg(options);
|
91 | return _this;
|
92 | }
|
93 | ComboForceLayout.prototype.getDefaultCfg = function () {
|
94 | return {
|
95 | maxIteration: 100,
|
96 | center: [0, 0],
|
97 | gravity: 10,
|
98 | speed: 1,
|
99 | comboGravity: 30,
|
100 | preventOverlap: false,
|
101 | preventComboOverlap: true,
|
102 | preventNodeOverlap: true,
|
103 | nodeSpacing: undefined,
|
104 | collideStrength: undefined,
|
105 | nodeCollideStrength: 0.5,
|
106 | comboCollideStrength: 0.5,
|
107 | comboSpacing: 20,
|
108 | comboPadding: 10,
|
109 | edgeStrength: 0.6,
|
110 | nodeStrength: 30,
|
111 | linkDistance: 10,
|
112 | };
|
113 | };
|
114 | |
115 |
|
116 |
|
117 | ComboForceLayout.prototype.execute = function () {
|
118 | var self = this;
|
119 | var nodes = self.nodes;
|
120 | var center = self.center;
|
121 | self.comboTree = {
|
122 | id: 'comboTreeRoot',
|
123 | depth: -1,
|
124 | children: self.comboTrees,
|
125 | };
|
126 | if (!nodes || nodes.length === 0) {
|
127 | return;
|
128 | }
|
129 | if (nodes.length === 1) {
|
130 | nodes[0].x = center[0];
|
131 | nodes[0].y = center[1];
|
132 | return;
|
133 | }
|
134 | self.initVals();
|
135 |
|
136 | self.run();
|
137 | self.onLayoutEnd();
|
138 | };
|
139 | ComboForceLayout.prototype.run = function () {
|
140 | var self = this;
|
141 | var nodes = self.nodes;
|
142 | var maxIteration = self.previousLayouted ? self.maxIteration / 5 : self.maxIteration;
|
143 | if (!self.width && typeof window !== 'undefined') {
|
144 | self.width = window.innerWidth;
|
145 | }
|
146 | if (!self.height && typeof window !== 'undefined') {
|
147 | self.height = window.innerHeight;
|
148 | }
|
149 | var center = self.center;
|
150 | var velocityDecay = self.velocityDecay;
|
151 |
|
152 | var comboMap = self.comboMap;
|
153 | if (!self.previousLayouted)
|
154 | self.initPos(comboMap);
|
155 | var _loop_1 = function (i) {
|
156 | var displacements = [];
|
157 | nodes.forEach(function (_, j) {
|
158 | displacements[j] = { x: 0, y: 0 };
|
159 | });
|
160 | self.applyCalculate(displacements);
|
161 |
|
162 | self.applyComboCenterForce(displacements);
|
163 |
|
164 | nodes.forEach(function (n, j) {
|
165 | if (!util_1.isNumber(n.x) || !util_1.isNumber(n.y))
|
166 | return;
|
167 | n.x += displacements[j].x * velocityDecay;
|
168 | n.y += displacements[j].y * velocityDecay;
|
169 | });
|
170 | self.alpha += (self.alphaTarget - self.alpha) * self.alphaDecay;
|
171 | self.onTick();
|
172 | };
|
173 |
|
174 | for (var i = 0; i < maxIteration; i++) {
|
175 | _loop_1(i);
|
176 | }
|
177 |
|
178 | var meanCenter = [0, 0];
|
179 | nodes.forEach(function (n) {
|
180 | if (!util_1.isNumber(n.x) || !util_1.isNumber(n.y))
|
181 | return;
|
182 | meanCenter[0] += n.x;
|
183 | meanCenter[1] += n.y;
|
184 | });
|
185 | meanCenter[0] /= nodes.length;
|
186 | meanCenter[1] /= nodes.length;
|
187 | var centerOffset = [center[0] - meanCenter[0], center[1] - meanCenter[1]];
|
188 | nodes.forEach(function (n, j) {
|
189 | if (!util_1.isNumber(n.x) || !util_1.isNumber(n.y))
|
190 | return;
|
191 | n.x += centerOffset[0];
|
192 | n.y += centerOffset[1];
|
193 | });
|
194 |
|
195 | self.combos.forEach(function (combo) {
|
196 | var mapped = comboMap[combo.id];
|
197 | if (mapped && mapped.empty) {
|
198 | combo.x = mapped.cx || combo.x;
|
199 | combo.y = mapped.cy || combo.y;
|
200 | }
|
201 | });
|
202 | self.previousLayouted = true;
|
203 | };
|
204 | ComboForceLayout.prototype.initVals = function () {
|
205 | var self = this;
|
206 | var edges = self.edges;
|
207 | var nodes = self.nodes;
|
208 | var combos = self.combos;
|
209 | var count = {};
|
210 | var nodeMap = {};
|
211 | var indexMap = {};
|
212 | nodes.forEach(function (node, i) {
|
213 | nodeMap[node.id] = node;
|
214 | indexMap[node.id] = i;
|
215 | });
|
216 | self.nodeMap = nodeMap;
|
217 | self.indexMap = indexMap;
|
218 | var oriComboMap = {};
|
219 | combos.forEach(function (combo) {
|
220 | oriComboMap[combo.id] = combo;
|
221 | });
|
222 | self.oriComboMap = oriComboMap;
|
223 | self.comboMap = self.getComboMap();
|
224 | var preventOverlap = self.preventOverlap;
|
225 | self.preventComboOverlap = self.preventComboOverlap || preventOverlap;
|
226 | self.preventNodeOverlap = self.preventNodeOverlap || preventOverlap;
|
227 | var collideStrength = self.collideStrength;
|
228 | if (collideStrength) {
|
229 | self.comboCollideStrength = collideStrength;
|
230 | self.nodeCollideStrength = collideStrength;
|
231 | }
|
232 | self.comboCollideStrength = self.comboCollideStrength ? self.comboCollideStrength : 0;
|
233 | self.nodeCollideStrength = self.nodeCollideStrength ? self.nodeCollideStrength : 0;
|
234 |
|
235 | for (var i = 0; i < edges.length; ++i) {
|
236 | if (count[edges[i].source])
|
237 | count[edges[i].source]++;
|
238 | else
|
239 | count[edges[i].source] = 1;
|
240 | if (count[edges[i].target])
|
241 | count[edges[i].target]++;
|
242 | else
|
243 | count[edges[i].target] = 1;
|
244 | }
|
245 | var bias = [];
|
246 | for (var i = 0; i < edges.length; ++i) {
|
247 | bias[i] = count[edges[i].source] / (count[edges[i].source] + count[edges[i].target]);
|
248 | }
|
249 | this.bias = bias;
|
250 | var nodeSize = self.nodeSize;
|
251 | var nodeSpacing = self.nodeSpacing;
|
252 | var nodeSizeFunc;
|
253 | var nodeSpacingFunc;
|
254 |
|
255 | if (util_1.isNumber(nodeSpacing)) {
|
256 | nodeSpacingFunc = function () { return nodeSpacing; };
|
257 | }
|
258 | else if (util_1.isFunction(nodeSpacing)) {
|
259 | nodeSpacingFunc = nodeSpacing;
|
260 | }
|
261 | else {
|
262 | nodeSpacingFunc = function () { return 0; };
|
263 | }
|
264 | this.nodeSpacing = nodeSpacingFunc;
|
265 |
|
266 | if (!nodeSize) {
|
267 | nodeSizeFunc = function (d) {
|
268 | if (d.size) {
|
269 | if (util_1.isArray(d.size)) {
|
270 | var res = d.size[0] > d.size[1] ? d.size[0] : d.size[1];
|
271 | return res / 2;
|
272 | }
|
273 | return d.size / 2;
|
274 | }
|
275 | return 10;
|
276 | };
|
277 | }
|
278 | else if (util_1.isFunction(nodeSize)) {
|
279 | nodeSizeFunc = function (d) {
|
280 | return nodeSize(d);
|
281 | };
|
282 | }
|
283 | else if (util_1.isArray(nodeSize)) {
|
284 | var larger = nodeSize[0] > nodeSize[1] ? nodeSize[0] : nodeSize[1];
|
285 | var radius_1 = larger / 2;
|
286 | nodeSizeFunc = function (d) { return radius_1; };
|
287 | }
|
288 | else {
|
289 |
|
290 | var radius_2 = nodeSize / 2;
|
291 | nodeSizeFunc = function (d) { return radius_2; };
|
292 | }
|
293 | this.nodeSize = nodeSizeFunc;
|
294 |
|
295 | var comboSpacing = self.comboSpacing;
|
296 | var comboSpacingFunc;
|
297 | if (util_1.isNumber(comboSpacing)) {
|
298 | comboSpacingFunc = function () { return comboSpacing; };
|
299 | }
|
300 | else if (util_1.isFunction(comboSpacing)) {
|
301 | comboSpacingFunc = comboSpacing;
|
302 | }
|
303 | else {
|
304 |
|
305 | comboSpacingFunc = function () { return 0; };
|
306 | }
|
307 | this.comboSpacing = comboSpacingFunc;
|
308 |
|
309 | var comboPadding = self.comboPadding;
|
310 | var comboPaddingFunc;
|
311 | if (util_1.isNumber(comboPadding)) {
|
312 | comboPaddingFunc = function () { return comboPadding; };
|
313 | }
|
314 | else if (util_1.isArray(comboPadding)) {
|
315 | comboPaddingFunc = function () { return Math.max.apply(null, comboPadding); };
|
316 | }
|
317 | else if (util_1.isFunction(comboPadding)) {
|
318 | comboPaddingFunc = comboPadding;
|
319 | }
|
320 | else {
|
321 |
|
322 | comboPaddingFunc = function () { return 0; };
|
323 | }
|
324 | this.comboPadding = comboPaddingFunc;
|
325 |
|
326 | var linkDistance = this.linkDistance;
|
327 | var linkDistanceFunc;
|
328 | if (!linkDistance) {
|
329 | linkDistance = 10;
|
330 | }
|
331 | if (util_1.isNumber(linkDistance)) {
|
332 | linkDistanceFunc = function (d) {
|
333 | return linkDistance;
|
334 | };
|
335 | }
|
336 | else {
|
337 | linkDistanceFunc = linkDistance;
|
338 | }
|
339 | this.linkDistance = linkDistanceFunc;
|
340 |
|
341 | var edgeStrength = this.edgeStrength;
|
342 | var edgeStrengthFunc;
|
343 | if (!edgeStrength) {
|
344 | edgeStrength = 1;
|
345 | }
|
346 | if (util_1.isNumber(edgeStrength)) {
|
347 | edgeStrengthFunc = function (d) {
|
348 | return edgeStrength;
|
349 | };
|
350 | }
|
351 | else {
|
352 | edgeStrengthFunc = edgeStrength;
|
353 | }
|
354 | this.edgeStrength = edgeStrengthFunc;
|
355 |
|
356 | var nodeStrength = this.nodeStrength;
|
357 | var nodeStrengthFunc;
|
358 | if (!nodeStrength) {
|
359 | nodeStrength = 30;
|
360 | }
|
361 | if (util_1.isNumber(nodeStrength)) {
|
362 | nodeStrengthFunc = function (d) {
|
363 | return nodeStrength;
|
364 | };
|
365 | }
|
366 | else {
|
367 | nodeStrengthFunc = nodeStrength;
|
368 | }
|
369 | this.nodeStrength = nodeStrengthFunc;
|
370 | };
|
371 | ComboForceLayout.prototype.initPos = function (comboMap) {
|
372 | var self = this;
|
373 | var nodes = self.nodes;
|
374 | nodes.forEach(function (node, i) {
|
375 | var comboId = node.comboId;
|
376 | var combo = comboMap[comboId];
|
377 | if (comboId && combo) {
|
378 | node.x = combo.cx + 100 / (i + 1);
|
379 | node.y = combo.cy + 100 / (i + 1);
|
380 | }
|
381 | else {
|
382 | node.x = 100 / (i + 1);
|
383 | node.y = 100 / (i + 1);
|
384 | }
|
385 | });
|
386 | };
|
387 | ComboForceLayout.prototype.getComboMap = function () {
|
388 | var self = this;
|
389 | var nodeMap = self.nodeMap;
|
390 | var indexMap = self.indexMap;
|
391 | var comboTrees = self.comboTrees;
|
392 | var oriComboMap = self.oriComboMap;
|
393 | var comboMap = {};
|
394 | (comboTrees || []).forEach(function (ctree) {
|
395 | var treeChildren = [];
|
396 | util_1.traverseTreeUp(ctree, function (treeNode) {
|
397 | if (treeNode.itemType === 'node')
|
398 | return true;
|
399 | if (!oriComboMap[treeNode.id])
|
400 | return true;
|
401 | if (comboMap[treeNode.id] === undefined) {
|
402 | var combo = {
|
403 | id: treeNode.id,
|
404 | name: treeNode.id,
|
405 | cx: 0,
|
406 | cy: 0,
|
407 | count: 0,
|
408 | depth: self.oriComboMap[treeNode.id].depth,
|
409 | children: [],
|
410 | };
|
411 | comboMap[treeNode.id] = combo;
|
412 | }
|
413 | var children = treeNode.children;
|
414 | if (children) {
|
415 | children.forEach(function (child) {
|
416 | if (!comboMap[child.id] && !nodeMap[child.id])
|
417 | return true;
|
418 | treeChildren.push(child);
|
419 | });
|
420 | }
|
421 | var c = comboMap[treeNode.id];
|
422 | c.cx = 0;
|
423 | c.cy = 0;
|
424 |
|
425 | if (treeChildren.length === 0) {
|
426 | c.empty = true;
|
427 | var oriCombo = oriComboMap[treeNode.id];
|
428 | var idx = Object.keys(nodeMap).length;
|
429 | var virtualNodeId = treeNode.id + "-visual-child-" + idx;
|
430 | var vnode = {
|
431 | id: virtualNodeId,
|
432 | x: oriCombo.x,
|
433 | y: oriCombo.y,
|
434 | depth: c.depth + 1,
|
435 | itemType: 'node',
|
436 | };
|
437 | self.nodes.push(vnode);
|
438 | nodeMap[virtualNodeId] = vnode;
|
439 | indexMap[virtualNodeId] = idx;
|
440 | c.cx = oriCombo.x;
|
441 | c.cy = oriCombo.y;
|
442 | treeChildren.push(vnode);
|
443 | }
|
444 | treeChildren.forEach(function (child) {
|
445 | c.count++;
|
446 | if (child.itemType !== 'node') {
|
447 | var childCombo = comboMap[child.id];
|
448 | if (util_1.isNumber(childCombo.cx))
|
449 | c.cx += childCombo.cx;
|
450 | if (util_1.isNumber(childCombo.cy))
|
451 | c.cy += childCombo.cy;
|
452 | return;
|
453 | }
|
454 | var node = nodeMap[child.id];
|
455 |
|
456 | if (!node)
|
457 | return;
|
458 | if (util_1.isNumber(node.x)) {
|
459 | c.cx += node.x;
|
460 | }
|
461 | if (util_1.isNumber(node.y)) {
|
462 | c.cy += node.y;
|
463 | }
|
464 | });
|
465 | c.cx /= c.count;
|
466 | c.cy /= c.count;
|
467 | c.children = treeChildren;
|
468 | return true;
|
469 | });
|
470 | });
|
471 | return comboMap;
|
472 | };
|
473 | ComboForceLayout.prototype.applyComboCenterForce = function (displacements) {
|
474 | var self = this;
|
475 | var gravity = self.gravity;
|
476 | var comboGravity = self.comboGravity || gravity;
|
477 | var alpha = this.alpha;
|
478 | var comboTrees = self.comboTrees;
|
479 | var indexMap = self.indexMap;
|
480 | var nodeMap = self.nodeMap;
|
481 | var comboMap = self.comboMap;
|
482 | (comboTrees || []).forEach(function (ctree) {
|
483 | util_1.traverseTreeUp(ctree, function (treeNode) {
|
484 | if (treeNode.itemType === 'node')
|
485 | return true;
|
486 | var combo = comboMap[treeNode.id];
|
487 |
|
488 | if (!combo)
|
489 | return true;
|
490 | var c = comboMap[treeNode.id];
|
491 |
|
492 | var gravityScale = (c.depth + 1) / 10 * 0.5;
|
493 |
|
494 |
|
495 | var comboX = c.cx;
|
496 | var comboY = c.cy;
|
497 | c.cx = 0;
|
498 | c.cy = 0;
|
499 | c.children.forEach(function (child) {
|
500 | if (child.itemType !== 'node') {
|
501 | var childCombo = comboMap[child.id];
|
502 | if (childCombo && util_1.isNumber(childCombo.cx))
|
503 | c.cx += childCombo.cx;
|
504 | if (childCombo && util_1.isNumber(childCombo.cy))
|
505 | c.cy += childCombo.cy;
|
506 | return;
|
507 | }
|
508 | var node = nodeMap[child.id];
|
509 | var vecX = node.x - comboX || 0.005;
|
510 | var vecY = node.y - comboY || 0.005;
|
511 | var l = Math.sqrt(vecX * vecX + vecY * vecY);
|
512 | var childIdx = indexMap[node.id];
|
513 | var params = ((comboGravity * alpha) / l) * gravityScale;
|
514 | displacements[childIdx].x -= vecX * params;
|
515 | displacements[childIdx].y -= vecY * params;
|
516 | if (util_1.isNumber(node.x))
|
517 | c.cx += node.x;
|
518 | if (util_1.isNumber(node.y))
|
519 | c.cy += node.y;
|
520 | });
|
521 | c.cx /= c.count;
|
522 | c.cy /= c.count;
|
523 | return true;
|
524 | });
|
525 | });
|
526 | };
|
527 | ComboForceLayout.prototype.applyCalculate = function (displacements) {
|
528 | var self = this;
|
529 | var comboMap = self.comboMap;
|
530 | var nodes = self.nodes;
|
531 |
|
532 | var vecMap = {};
|
533 | nodes.forEach(function (v, i) {
|
534 | nodes.forEach(function (u, j) {
|
535 | if (i < j)
|
536 | return;
|
537 | var vx = v.x - u.x || 0.005;
|
538 | var vy = v.y - u.y || 0.005;
|
539 | var vl2 = vx * vx + vy * vy;
|
540 | var vl = Math.sqrt(vl2);
|
541 | if (vl2 < 1)
|
542 | vl2 = vl;
|
543 | vecMap[v.id + "-" + u.id] = { vx: vx, vy: vy, vl2: vl2, vl: vl };
|
544 | vecMap[u.id + "-" + v.id] = { vl2: vl2, vl: vl, vx: -vx, vy: -vy };
|
545 | });
|
546 | });
|
547 |
|
548 | self.updateComboSizes(comboMap);
|
549 | self.calRepulsive(displacements, vecMap);
|
550 | self.calAttractive(displacements, vecMap);
|
551 | var preventComboOverlap = self.preventComboOverlap;
|
552 | if (preventComboOverlap)
|
553 | self.comboNonOverlapping(displacements, comboMap);
|
554 | };
|
555 | |
556 |
|
557 |
|
558 |
|
559 | ComboForceLayout.prototype.updateComboSizes = function (comboMap) {
|
560 | var self = this;
|
561 | var comboTrees = self.comboTrees;
|
562 | var nodeMap = self.nodeMap;
|
563 | var nodeSize = self.nodeSize;
|
564 | var comboSpacing = self.comboSpacing;
|
565 | var comboPadding = self.comboPadding;
|
566 | (comboTrees || []).forEach(function (ctree) {
|
567 | var treeChildren = [];
|
568 | util_1.traverseTreeUp(ctree, function (treeNode) {
|
569 | if (treeNode.itemType === 'node')
|
570 | return true;
|
571 | var c = comboMap[treeNode.id];
|
572 |
|
573 | if (!c)
|
574 | return false;
|
575 | var children = treeNode.children;
|
576 | if (children) {
|
577 | children.forEach(function (child) {
|
578 |
|
579 | if (!comboMap[child.id] && !nodeMap[child.id])
|
580 | return;
|
581 | treeChildren.push(child);
|
582 | });
|
583 | }
|
584 | c.minX = Infinity;
|
585 | c.minY = Infinity;
|
586 | c.maxX = -Infinity;
|
587 | c.maxY = -Infinity;
|
588 | treeChildren.forEach(function (child) {
|
589 | if (child.itemType !== 'node')
|
590 | return true;
|
591 | var node = nodeMap[child.id];
|
592 | if (!node)
|
593 | return true;
|
594 | var r = nodeSize(node);
|
595 | var nodeMinX = node.x - r;
|
596 | var nodeMinY = node.y - r;
|
597 | var nodeMaxX = node.x + r;
|
598 | var nodeMaxY = node.y + r;
|
599 | if (c.minX > nodeMinX)
|
600 | c.minX = nodeMinX;
|
601 | if (c.minY > nodeMinY)
|
602 | c.minY = nodeMinY;
|
603 | if (c.maxX < nodeMaxX)
|
604 | c.maxX = nodeMaxX;
|
605 | if (c.maxY < nodeMaxY)
|
606 | c.maxY = nodeMaxY;
|
607 | });
|
608 | var minSize = self.oriComboMap[treeNode.id].size || 10;
|
609 | if (util_1.isArray(minSize))
|
610 | minSize = minSize[0];
|
611 | var maxLength = Math.max(c.maxX - c.minX, c.maxY - c.minY, minSize);
|
612 | c.r = maxLength / 2 + comboSpacing(c) / 2 + comboPadding(c);
|
613 | return true;
|
614 | });
|
615 | });
|
616 | };
|
617 | |
618 |
|
619 |
|
620 | ComboForceLayout.prototype.comboNonOverlapping = function (displacements, comboMap) {
|
621 | var self = this;
|
622 | var comboTree = self.comboTree;
|
623 | var comboCollideStrength = self.comboCollideStrength;
|
624 | var indexMap = self.indexMap;
|
625 | var nodeMap = self.nodeMap;
|
626 | util_1.traverseTreeUp(comboTree, function (treeNode) {
|
627 | if (!comboMap[treeNode.id] && !nodeMap[treeNode.id] && treeNode.id !== 'comboTreeRoot') {
|
628 | return false;
|
629 | }
|
630 | var children = treeNode.children;
|
631 |
|
632 | if (children && children.length > 1) {
|
633 | children.forEach(function (v, i) {
|
634 | if (v.itemType === 'node')
|
635 | return false;
|
636 | var cv = comboMap[v.id];
|
637 | if (!cv)
|
638 | return;
|
639 | children.forEach(function (u, j) {
|
640 | if (i <= j)
|
641 | return false;
|
642 | if (u.itemType === 'node')
|
643 | return false;
|
644 | var cu = comboMap[u.id];
|
645 | if (!cu)
|
646 | return false;
|
647 | var vx = cv.cx - cu.cx || 0.005;
|
648 | var vy = cv.cy - cu.cy || 0.005;
|
649 | var l = vx * vx + vy * vy;
|
650 | var rv = cv.r;
|
651 | var ru = cu.r;
|
652 | var r = rv + ru;
|
653 | var ru2 = ru * ru;
|
654 | var rv2 = rv * rv;
|
655 |
|
656 | if (l < r * r) {
|
657 | var vnodes = v.children;
|
658 | if (!vnodes || vnodes.length === 0)
|
659 | return false;
|
660 | var unodes_1 = u.children;
|
661 | if (!unodes_1 || unodes_1.length === 0)
|
662 | return false;
|
663 | var sqrtl = Math.sqrt(l);
|
664 | var ll = ((r - sqrtl) / sqrtl) * comboCollideStrength;
|
665 | var xl_1 = vx * ll;
|
666 | var yl_1 = vy * ll;
|
667 | var rratio_1 = ru2 / (rv2 + ru2);
|
668 | var irratio_1 = 1 - rratio_1;
|
669 |
|
670 | vnodes.forEach(function (vn) {
|
671 | if (vn.itemType !== 'node')
|
672 | return false;
|
673 | if (!nodeMap[vn.id])
|
674 | return;
|
675 | var vindex = indexMap[vn.id];
|
676 | unodes_1.forEach(function (un) {
|
677 | if (un.itemType !== 'node')
|
678 | return false;
|
679 | if (!nodeMap[un.id])
|
680 | return false;
|
681 | var uindex = indexMap[un.id];
|
682 | displacements[vindex].x += xl_1 * rratio_1;
|
683 | displacements[vindex].y += yl_1 * rratio_1;
|
684 | displacements[uindex].x -= xl_1 * irratio_1;
|
685 | displacements[uindex].y -= yl_1 * irratio_1;
|
686 | });
|
687 | });
|
688 | }
|
689 | });
|
690 | });
|
691 | }
|
692 | return true;
|
693 | });
|
694 | };
|
695 | |
696 |
|
697 |
|
698 |
|
699 |
|
700 | ComboForceLayout.prototype.calRepulsive = function (displacements, vecMap) {
|
701 | var self = this;
|
702 | var nodes = self.nodes;
|
703 | var max = self.width * self.optimizeRangeFactor;
|
704 | var nodeStrength = self.nodeStrength;
|
705 | var alpha = self.alpha;
|
706 | var nodeCollideStrength = self.nodeCollideStrength;
|
707 | var preventNodeOverlap = self.preventNodeOverlap;
|
708 | var nodeSizeFunc = self.nodeSize;
|
709 | var nodeSpacingFunc = self.nodeSpacing;
|
710 | var scale = self.depthRepulsiveForceScale;
|
711 | var center = self.center;
|
712 | nodes.forEach(function (v, i) {
|
713 | if (!v.x || !v.y)
|
714 | return;
|
715 |
|
716 | if (center) {
|
717 | var gravity = self.gravity;
|
718 | var vecX = v.x - center[0] || 0.005;
|
719 | var vecY = v.y - center[1] || 0.005;
|
720 | var l = Math.sqrt(vecX * vecX + vecY * vecY);
|
721 | displacements[i].x -= (vecX * gravity * alpha) / l;
|
722 | displacements[i].y -= (vecY * gravity * alpha) / l;
|
723 | }
|
724 | nodes.forEach(function (u, j) {
|
725 | if (i === j) {
|
726 | return;
|
727 | }
|
728 | if (!u.x || !u.y)
|
729 | return;
|
730 | var _a = vecMap[v.id + "-" + u.id], vl2 = _a.vl2, vl = _a.vl;
|
731 | if (vl > max)
|
732 | return;
|
733 | var _b = vecMap[v.id + "-" + u.id], vx = _b.vx, vy = _b.vy;
|
734 | var depthDiff = (Math.log(Math.abs(u.depth - v.depth) / 10) + 1 || 1);
|
735 | depthDiff = depthDiff < 1 ? 1 : depthDiff;
|
736 | if (u.comboId !== v.comboId)
|
737 | depthDiff += 1;
|
738 | var depthParam = depthDiff ? Math.pow(scale, depthDiff) : 1;
|
739 | var params = ((nodeStrength(u) * alpha) / vl2) * depthParam;
|
740 | displacements[i].x += vx * params;
|
741 | displacements[i].y += vy * params;
|
742 |
|
743 | if (i < j && preventNodeOverlap) {
|
744 | var ri = nodeSizeFunc(v) + nodeSpacingFunc(v);
|
745 | var rj = nodeSizeFunc(u) + nodeSpacingFunc(u);
|
746 | var r = ri + rj;
|
747 | if (vl2 < r * r) {
|
748 | var ll = ((r - vl) / vl) * nodeCollideStrength;
|
749 | var rj2 = rj * rj;
|
750 | var rratio = rj2 / (ri * ri + rj2);
|
751 | var xl = vx * ll;
|
752 | var yl = vy * ll;
|
753 | displacements[i].x += xl * rratio;
|
754 | displacements[i].y += yl * rratio;
|
755 | rratio = 1 - rratio;
|
756 | displacements[j].x -= xl * rratio;
|
757 | displacements[j].y -= yl * rratio;
|
758 | }
|
759 | }
|
760 | });
|
761 | });
|
762 | };
|
763 | |
764 |
|
765 |
|
766 |
|
767 |
|
768 | ComboForceLayout.prototype.calAttractive = function (displacements, vecMap) {
|
769 | var self = this;
|
770 | var edges = self.edges;
|
771 | var linkDistance = self.linkDistance;
|
772 | var alpha = self.alpha;
|
773 | var edgeStrength = self.edgeStrength;
|
774 | var bias = self.bias;
|
775 | var scale = self.depthAttractiveForceScale;
|
776 | edges.forEach(function (e, i) {
|
777 | if (!e.source || !e.target || e.source === e.target)
|
778 | return;
|
779 | var uIndex = self.indexMap[e.source];
|
780 | var vIndex = self.indexMap[e.target];
|
781 | var u = self.nodeMap[e.source];
|
782 | var v = self.nodeMap[e.target];
|
783 | if (!u || !v)
|
784 | return;
|
785 | var depthDiff = Math.log(Math.abs(u.depth - v.depth) / 10);
|
786 | if (u.comboId === v.comboId) {
|
787 | depthDiff = depthDiff / 2;
|
788 | }
|
789 | var depthParam = depthDiff ? Math.pow(scale, depthDiff) : 1;
|
790 | if (u.comboId !== v.comboId && depthParam === 1) {
|
791 | depthParam = scale / 2;
|
792 | }
|
793 | else if (u.comboId === v.comboId) {
|
794 | depthParam = 2;
|
795 | }
|
796 | if (!util_1.isNumber(v.x) || !util_1.isNumber(u.x) || !util_1.isNumber(v.y) || !util_1.isNumber(u.y))
|
797 | return;
|
798 | var _a = vecMap[e.target + "-" + e.source], vl = _a.vl, vx = _a.vx, vy = _a.vy;
|
799 | var l = ((vl - linkDistance(e)) / vl) * alpha * edgeStrength(e) * depthParam;
|
800 | var vecX = vx * l;
|
801 | var vecY = vy * l;
|
802 | var b = bias[i];
|
803 | displacements[vIndex].x -= vecX * b;
|
804 | displacements[vIndex].y -= vecY * b;
|
805 | displacements[uIndex].x += vecX * (1 - b);
|
806 | displacements[uIndex].y += vecY * (1 - b);
|
807 | });
|
808 | };
|
809 | ComboForceLayout.prototype.getType = function () {
|
810 | return 'comboForce';
|
811 | };
|
812 | return ComboForceLayout;
|
813 | }(base_1.Base));
|
814 | exports.ComboForceLayout = ComboForceLayout;
|
815 |
|
\ | No newline at end of file |