@antv/layout 2.0.0-alpha.2 → 2.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1207 -1247
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +1 -1
- package/dist/worker.js +1 -1
- package/dist/worker.js.map +1 -1
- package/lib/algorithm/antv-dagre/index.js +10 -8
- package/lib/algorithm/antv-dagre/index.js.map +1 -1
- package/lib/algorithm/antv-dagre/types.d.ts +25 -3
- package/lib/algorithm/base-layout.d.ts +1 -0
- package/lib/algorithm/base-layout.js +5 -3
- package/lib/algorithm/base-layout.js.map +1 -1
- package/lib/algorithm/circular/index.js +2 -2
- package/lib/algorithm/circular/index.js.map +1 -1
- package/lib/algorithm/combo-combined/index.js +4 -4
- package/lib/algorithm/combo-combined/index.js.map +1 -1
- package/lib/algorithm/d3-force/index.d.ts +2 -2
- package/lib/algorithm/d3-force/index.js +60 -104
- package/lib/algorithm/d3-force/index.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/util/object.d.ts +1 -2
- package/lib/util/object.js +1 -4
- package/lib/util/object.js.map +1 -1
- package/lib/util/order.d.ts +1 -1
- package/lib/util/order.js +4 -1
- package/lib/util/order.js.map +1 -1
- package/lib/worker.js +768 -807
- package/lib/worker.js.map +1 -1
- package/package.json +1 -1
- package/src/algorithm/antv-dagre/index.ts +11 -12
- package/src/algorithm/antv-dagre/types.ts +25 -3
- package/src/algorithm/base-layout.ts +13 -8
- package/src/algorithm/circular/index.ts +2 -2
- package/src/algorithm/combo-combined/index.ts +5 -5
- package/src/algorithm/d3-force/index.ts +69 -122
- package/src/util/object.ts +0 -4
- package/src/util/order.ts +4 -0
package/dist/index.js
CHANGED
|
@@ -357,1195 +357,1260 @@
|
|
|
357
357
|
return result;
|
|
358
358
|
});
|
|
359
359
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
}
|
|
377
|
-
node(id) {
|
|
378
|
-
return this.nodeMap.get(id);
|
|
379
|
-
}
|
|
380
|
-
nodeAt(index) {
|
|
381
|
-
if (!this.indexNodeCache) {
|
|
382
|
-
this.buildNodeIndexCache();
|
|
383
|
-
}
|
|
384
|
-
const nodeId = this.indexNodeCache.get(index);
|
|
385
|
-
return nodeId ? this.nodeMap.get(nodeId) : undefined;
|
|
386
|
-
}
|
|
387
|
-
nodeIndexOf(id) {
|
|
388
|
-
var _a;
|
|
389
|
-
if (!this.nodeIndexCache) {
|
|
390
|
-
this.buildNodeIndexCache();
|
|
391
|
-
}
|
|
392
|
-
return (_a = this.nodeIndexCache.get(id)) !== null && _a !== void 0 ? _a : -1;
|
|
393
|
-
}
|
|
394
|
-
firstNode() {
|
|
395
|
-
return this.nodeMap.values().next().value;
|
|
396
|
-
}
|
|
397
|
-
forEachNode(callback) {
|
|
398
|
-
let i = 0;
|
|
399
|
-
this.nodeMap.forEach((node) => callback(node, i++));
|
|
400
|
-
}
|
|
401
|
-
originalNode(id) {
|
|
402
|
-
const node = this.nodeMap.get(id);
|
|
403
|
-
return node === null || node === void 0 ? void 0 : node._original;
|
|
404
|
-
}
|
|
405
|
-
nodeCount() {
|
|
406
|
-
return this.nodeMap.size;
|
|
407
|
-
}
|
|
408
|
-
edges() {
|
|
409
|
-
return Array.from(this.edgeMap.values());
|
|
410
|
-
}
|
|
411
|
-
edge(id) {
|
|
412
|
-
return this.edgeMap.get(id);
|
|
413
|
-
}
|
|
414
|
-
firstEdge() {
|
|
415
|
-
return this.edgeMap.values().next().value;
|
|
416
|
-
}
|
|
417
|
-
forEachEdge(callback) {
|
|
418
|
-
let i = 0;
|
|
419
|
-
this.edgeMap.forEach((edge) => callback(edge, i++));
|
|
420
|
-
}
|
|
421
|
-
originalEdge(id) {
|
|
422
|
-
const edge = this.edgeMap.get(id);
|
|
423
|
-
return edge === null || edge === void 0 ? void 0 : edge._original;
|
|
424
|
-
}
|
|
425
|
-
edgeCount() {
|
|
426
|
-
return this.edgeMap.size;
|
|
427
|
-
}
|
|
428
|
-
getEdgeId(edge) {
|
|
429
|
-
if (edge.id)
|
|
430
|
-
return edge.id;
|
|
431
|
-
const baseId = `${edge.source}-${edge.target}`;
|
|
432
|
-
const count = this.edgeIdCounter.get(baseId) || 0;
|
|
433
|
-
const id = count === 0 ? baseId : `${baseId}-${count}`;
|
|
434
|
-
this.edgeIdCounter.set(baseId, count + 1);
|
|
435
|
-
return id;
|
|
436
|
-
}
|
|
437
|
-
degree(nodeId, direction = 'both') {
|
|
438
|
-
if (!this.degreeCache) {
|
|
439
|
-
this.buildDegreeCache();
|
|
440
|
-
}
|
|
441
|
-
const degree = this.degreeCache.get(nodeId);
|
|
442
|
-
if (!degree)
|
|
443
|
-
return 0;
|
|
444
|
-
return degree[direction];
|
|
445
|
-
}
|
|
446
|
-
neighbors(nodeId, direction = 'both') {
|
|
447
|
-
if (!this.outAdjacencyCache || !this.inAdjacencyCache) {
|
|
448
|
-
this.buildAdjacencyCache();
|
|
449
|
-
}
|
|
450
|
-
if (direction === 'out') {
|
|
451
|
-
return Array.from(this.outAdjacencyCache.get(nodeId) || []);
|
|
452
|
-
}
|
|
453
|
-
if (direction === 'in') {
|
|
454
|
-
return Array.from(this.inAdjacencyCache.get(nodeId) || []);
|
|
455
|
-
}
|
|
456
|
-
if (this.bothAdjacencyCache) {
|
|
457
|
-
return Array.from(this.bothAdjacencyCache.get(nodeId) || []);
|
|
458
|
-
}
|
|
459
|
-
const inSet = this.inAdjacencyCache.get(nodeId);
|
|
460
|
-
const outSet = this.outAdjacencyCache.get(nodeId);
|
|
461
|
-
if (!inSet && !outSet)
|
|
462
|
-
return [];
|
|
463
|
-
if (!inSet)
|
|
464
|
-
return Array.from(outSet);
|
|
465
|
-
if (!outSet)
|
|
466
|
-
return Array.from(inSet);
|
|
467
|
-
const merged = new Set();
|
|
468
|
-
inSet.forEach((id) => merged.add(id));
|
|
469
|
-
outSet.forEach((id) => merged.add(id));
|
|
470
|
-
return Array.from(merged);
|
|
471
|
-
}
|
|
472
|
-
successors(nodeId) {
|
|
473
|
-
return this.neighbors(nodeId, 'out');
|
|
474
|
-
}
|
|
475
|
-
predecessors(nodeId) {
|
|
476
|
-
return this.neighbors(nodeId, 'in');
|
|
477
|
-
}
|
|
478
|
-
setNodeOrder(nodes) {
|
|
479
|
-
const next = new Map();
|
|
480
|
-
for (const node of nodes)
|
|
481
|
-
next.set(node.id, node);
|
|
482
|
-
this.nodeMap = next;
|
|
483
|
-
this.nodeIndexCache = undefined;
|
|
484
|
-
this.indexNodeCache = undefined;
|
|
485
|
-
}
|
|
486
|
-
clearCache() {
|
|
487
|
-
this.degreeCache = undefined;
|
|
488
|
-
this.inAdjacencyCache = undefined;
|
|
489
|
-
this.outAdjacencyCache = undefined;
|
|
490
|
-
this.bothAdjacencyCache = undefined;
|
|
491
|
-
this.nodeIndexCache = undefined;
|
|
492
|
-
this.indexNodeCache = undefined;
|
|
493
|
-
}
|
|
494
|
-
buildDegreeCache() {
|
|
495
|
-
this.degreeCache = new Map();
|
|
496
|
-
for (const edge of this.edges()) {
|
|
497
|
-
const { source, target } = edge;
|
|
498
|
-
if (edge.source === edge.target)
|
|
499
|
-
continue;
|
|
500
|
-
if (!this.degreeCache.has(source)) {
|
|
501
|
-
this.degreeCache.set(source, { in: 0, out: 0, both: 0 });
|
|
502
|
-
}
|
|
503
|
-
const sourceDeg = this.degreeCache.get(edge.source);
|
|
504
|
-
if (sourceDeg) {
|
|
505
|
-
sourceDeg.out++;
|
|
506
|
-
sourceDeg.both++;
|
|
507
|
-
}
|
|
508
|
-
if (!this.degreeCache.has(target)) {
|
|
509
|
-
this.degreeCache.set(target, { in: 0, out: 0, both: 0 });
|
|
510
|
-
}
|
|
511
|
-
const targetDeg = this.degreeCache.get(edge.target);
|
|
512
|
-
if (targetDeg) {
|
|
513
|
-
targetDeg.in++;
|
|
514
|
-
targetDeg.both++;
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
buildAdjacencyCache() {
|
|
519
|
-
this.inAdjacencyCache = new Map();
|
|
520
|
-
this.outAdjacencyCache = new Map();
|
|
521
|
-
for (const edge of this.edges()) {
|
|
522
|
-
if (!this.nodeMap.has(edge.source) || !this.nodeMap.has(edge.target))
|
|
523
|
-
continue;
|
|
524
|
-
if (!this.outAdjacencyCache.has(edge.source)) {
|
|
525
|
-
this.outAdjacencyCache.set(edge.source, new Set());
|
|
526
|
-
}
|
|
527
|
-
this.outAdjacencyCache.get(edge.source).add(edge.target);
|
|
528
|
-
if (!this.inAdjacencyCache.has(edge.target)) {
|
|
529
|
-
this.inAdjacencyCache.set(edge.target, new Set());
|
|
530
|
-
}
|
|
531
|
-
this.inAdjacencyCache.get(edge.target).add(edge.source);
|
|
360
|
+
const isArray = Array.isArray;
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Return the layout result for a graph with zero or one node.
|
|
364
|
+
* @param graph original graph
|
|
365
|
+
* @param center the layout center
|
|
366
|
+
* @returns layout result
|
|
367
|
+
*/
|
|
368
|
+
function applySingleNodeLayout(model, center, dimensions = 2) {
|
|
369
|
+
const n = model.nodeCount();
|
|
370
|
+
if (n === 1) {
|
|
371
|
+
const first = model.firstNode();
|
|
372
|
+
first.x = center[0];
|
|
373
|
+
first.y = center[1];
|
|
374
|
+
if (dimensions === 3) {
|
|
375
|
+
first.z = center[2] || 0;
|
|
532
376
|
}
|
|
533
377
|
}
|
|
534
|
-
buildNodeIndexCache() {
|
|
535
|
-
this.nodeIndexCache = new Map();
|
|
536
|
-
this.indexNodeCache = new Map();
|
|
537
|
-
let index = 0;
|
|
538
|
-
this.nodeMap.forEach((_node, nodeId) => {
|
|
539
|
-
this.nodeIndexCache.set(nodeId, index);
|
|
540
|
-
this.indexNodeCache.set(index, nodeId);
|
|
541
|
-
index++;
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
destroy() {
|
|
545
|
-
this.clearCache();
|
|
546
|
-
this.nodeMap.clear();
|
|
547
|
-
this.edgeMap.clear();
|
|
548
|
-
this.edgeIdCounter.clear();
|
|
549
|
-
}
|
|
550
378
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
const edgeFields = ['id', 'source', 'target', 'points'];
|
|
565
|
-
function extractNodeData(nodes, node) {
|
|
566
|
-
if (!nodes) {
|
|
567
|
-
throw new Error('Data.nodes is required');
|
|
568
|
-
}
|
|
569
|
-
const result = new Map();
|
|
570
|
-
for (const datum of nodes) {
|
|
571
|
-
const nodeData = { _original: datum };
|
|
572
|
-
for (const field of nodeFields) {
|
|
573
|
-
const value = datum[field];
|
|
574
|
-
if (isNil(value))
|
|
575
|
-
continue;
|
|
576
|
-
nodeData[field] = value;
|
|
577
|
-
}
|
|
578
|
-
if (node) {
|
|
579
|
-
const customFields = node(datum);
|
|
580
|
-
for (const key in customFields) {
|
|
581
|
-
const value = customFields[key];
|
|
582
|
-
if (isNil(value))
|
|
583
|
-
continue;
|
|
584
|
-
nodeData[key] = value;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
if (isNil(nodeData.id)) {
|
|
588
|
-
throw new Error(`Node is missing id field`);
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Floyd-Warshall algorithm to find shortest paths (but with no negative cycles).
|
|
382
|
+
*/
|
|
383
|
+
const floydWarshall = (adjMatrix) => {
|
|
384
|
+
// initialize
|
|
385
|
+
const n = adjMatrix.length;
|
|
386
|
+
const dist = Array.from({ length: n }, () => new Array(n));
|
|
387
|
+
for (let i = 0; i < n; i++) {
|
|
388
|
+
const row = adjMatrix[i];
|
|
389
|
+
const drow = dist[i];
|
|
390
|
+
for (let j = 0; j < n; j++) {
|
|
391
|
+
drow[j] = i === j ? 0 : row[j] > 0 ? row[j] : Infinity;
|
|
589
392
|
}
|
|
590
|
-
result.set(nodeData.id, nodeData);
|
|
591
393
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
const value = datum[field];
|
|
600
|
-
if (isNil(value))
|
|
394
|
+
// floyd
|
|
395
|
+
for (let k = 0; k < n; k++) {
|
|
396
|
+
const dk = dist[k];
|
|
397
|
+
for (let i = 0; i < n; i++) {
|
|
398
|
+
const di = dist[i];
|
|
399
|
+
const dik = di[k];
|
|
400
|
+
if (dik === Infinity)
|
|
601
401
|
continue;
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
const customFields = edge(datum);
|
|
606
|
-
for (const key in customFields) {
|
|
607
|
-
const value = customFields[key];
|
|
608
|
-
if (isNil(value))
|
|
402
|
+
for (let j = 0; j < n; j++) {
|
|
403
|
+
const dkj = dk[j];
|
|
404
|
+
if (dkj === Infinity)
|
|
609
405
|
continue;
|
|
610
|
-
|
|
406
|
+
const next = dik + dkj;
|
|
407
|
+
if (next < di[j]) {
|
|
408
|
+
di[j] = next;
|
|
409
|
+
}
|
|
611
410
|
}
|
|
612
411
|
}
|
|
613
|
-
if (isNil(edgeData.source) || isNil(edgeData.target)) {
|
|
614
|
-
throw new Error(`Edge is missing source or target field`);
|
|
615
|
-
}
|
|
616
|
-
if (isNil(edgeData.id)) {
|
|
617
|
-
edgeData.id = getEdgeId === null || getEdgeId === void 0 ? void 0 : getEdgeId(datum);
|
|
618
|
-
}
|
|
619
|
-
result.set(edgeData.id, edgeData);
|
|
620
412
|
}
|
|
621
|
-
return
|
|
622
|
-
}
|
|
623
|
-
|
|
413
|
+
return dist;
|
|
414
|
+
};
|
|
415
|
+
/**
|
|
416
|
+
* Get the adjacency matrix of the graph model.
|
|
417
|
+
*/
|
|
418
|
+
const getAdjMatrix = (model, directed) => {
|
|
419
|
+
const n = model.nodeCount();
|
|
420
|
+
const matrix = Array.from({ length: n }, () => new Array(n));
|
|
421
|
+
// map node with index in data.nodes
|
|
422
|
+
const nodeMap = {};
|
|
423
|
+
let i = 0;
|
|
624
424
|
model.forEachNode((node) => {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
425
|
+
nodeMap[node.id] = i++;
|
|
426
|
+
});
|
|
427
|
+
model.forEachEdge((e) => {
|
|
428
|
+
const sIndex = nodeMap[e.source];
|
|
429
|
+
const tIndex = nodeMap[e.target];
|
|
430
|
+
if (sIndex === undefined || tIndex === undefined)
|
|
431
|
+
return;
|
|
432
|
+
matrix[sIndex][tIndex] = 1;
|
|
433
|
+
if (!directed) {
|
|
434
|
+
matrix[tIndex][sIndex] = 1;
|
|
633
435
|
}
|
|
634
436
|
});
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
class RuntimeContext {
|
|
638
|
-
constructor(data, options = {}) {
|
|
639
|
-
this.graph = new GraphLib(data, options);
|
|
640
|
-
}
|
|
641
|
-
export() {
|
|
642
|
-
return this.graph.data();
|
|
643
|
-
}
|
|
644
|
-
replace(result) {
|
|
645
|
-
this.graph.replace(result);
|
|
646
|
-
}
|
|
647
|
-
forEachNode(callback) {
|
|
648
|
-
this.graph.forEachNode(callback);
|
|
649
|
-
}
|
|
650
|
-
forEachEdge(callback) {
|
|
651
|
-
this.graph.forEachEdge((edge, i) => {
|
|
652
|
-
edge.sourceNode = this.graph.node(edge.source);
|
|
653
|
-
edge.targetNode = this.graph.node(edge.target);
|
|
654
|
-
callback(edge, i);
|
|
655
|
-
});
|
|
656
|
-
}
|
|
657
|
-
destroy() {
|
|
658
|
-
this.graph.destroy();
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
|
|
437
|
+
return matrix;
|
|
438
|
+
};
|
|
662
439
|
/**
|
|
663
|
-
*
|
|
664
|
-
* Copyright 2019 Google LLC
|
|
665
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
440
|
+
* Get the adjacency list of the graph model.
|
|
666
441
|
*/
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
442
|
+
const getAdjList = (model, directed) => {
|
|
443
|
+
const n = model.nodeCount();
|
|
444
|
+
const adjList = Array.from({ length: n }, () => []);
|
|
445
|
+
// map node with index
|
|
446
|
+
const nodeMap = {};
|
|
447
|
+
let idx = 0;
|
|
448
|
+
model.forEachNode((node) => {
|
|
449
|
+
nodeMap[node.id] = idx++;
|
|
450
|
+
});
|
|
451
|
+
model.forEachEdge((e) => {
|
|
452
|
+
const s = nodeMap[e.source];
|
|
453
|
+
const t = nodeMap[e.target];
|
|
454
|
+
if (s == null || t == null)
|
|
455
|
+
return;
|
|
456
|
+
adjList[s].push(t);
|
|
457
|
+
if (!directed)
|
|
458
|
+
adjList[t].push(s);
|
|
459
|
+
});
|
|
460
|
+
return adjList;
|
|
461
|
+
};
|
|
673
462
|
/**
|
|
674
|
-
*
|
|
463
|
+
* scale matrix
|
|
464
|
+
* @param matrix [ [], [], [] ]
|
|
465
|
+
* @param ratio
|
|
675
466
|
*/
|
|
676
|
-
const
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
467
|
+
const scaleMatrix = (matrix, ratio) => {
|
|
468
|
+
const n = matrix.length;
|
|
469
|
+
const result = new Array(n);
|
|
470
|
+
for (let i = 0; i < n; i++) {
|
|
471
|
+
const row = matrix[i];
|
|
472
|
+
const m = row.length;
|
|
473
|
+
const newRow = new Array(m);
|
|
474
|
+
for (let j = 0; j < m; j++) {
|
|
475
|
+
newRow[j] = row[j] * ratio;
|
|
476
|
+
}
|
|
477
|
+
result[i] = newRow;
|
|
478
|
+
}
|
|
479
|
+
return result;
|
|
687
480
|
};
|
|
688
481
|
/**
|
|
689
|
-
*
|
|
482
|
+
* calculate the bounding box for the nodes according to their x, y, and size
|
|
483
|
+
* @param nodes nodes in the layout
|
|
484
|
+
* @returns
|
|
690
485
|
*/
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
stack: value.stack,
|
|
702
|
-
},
|
|
703
|
-
};
|
|
486
|
+
const getLayoutBBox = (nodes) => {
|
|
487
|
+
let minX = Infinity;
|
|
488
|
+
let minY = Infinity;
|
|
489
|
+
let maxX = -Infinity;
|
|
490
|
+
let maxY = -Infinity;
|
|
491
|
+
nodes.forEach((node) => {
|
|
492
|
+
let size = node.data.size;
|
|
493
|
+
if (isArray(size)) {
|
|
494
|
+
if (size.length === 1)
|
|
495
|
+
size = [size[0], size[0]];
|
|
704
496
|
}
|
|
705
|
-
else {
|
|
706
|
-
|
|
497
|
+
else if (size === undefined || isNaN(size)) {
|
|
498
|
+
size = [30, 30];
|
|
707
499
|
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
deserialize(serialized) {
|
|
711
|
-
if (serialized.isError) {
|
|
712
|
-
throw Object.assign(new Error(serialized.value.message), serialized.value);
|
|
500
|
+
else if (isNumber(size)) {
|
|
501
|
+
size = [size, size];
|
|
713
502
|
}
|
|
714
|
-
|
|
715
|
-
|
|
503
|
+
const halfSize = [size[0] / 2, size[1] / 2];
|
|
504
|
+
const left = node.data.x - halfSize[0];
|
|
505
|
+
const right = node.data.x + halfSize[0];
|
|
506
|
+
const top = node.data.y - halfSize[1];
|
|
507
|
+
const bottom = node.data.y + halfSize[1];
|
|
508
|
+
if (minX > left)
|
|
509
|
+
minX = left;
|
|
510
|
+
if (minY > top)
|
|
511
|
+
minY = top;
|
|
512
|
+
if (maxX < right)
|
|
513
|
+
maxX = right;
|
|
514
|
+
if (maxY < bottom)
|
|
515
|
+
maxY = bottom;
|
|
516
|
+
});
|
|
517
|
+
return { minX, minY, maxX, maxY };
|
|
716
518
|
};
|
|
717
519
|
/**
|
|
718
|
-
*
|
|
520
|
+
* calculate the euclidean distance form p1 to p2
|
|
521
|
+
* @param p1
|
|
522
|
+
* @param p2
|
|
523
|
+
* @returns
|
|
524
|
+
*/
|
|
525
|
+
const getEuclideanDistance = (p1, p2) => Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
|
|
526
|
+
/**
|
|
527
|
+
* Depth first search begin from nodes in graphCore data.
|
|
528
|
+
* @param graphCore graphlib data structure
|
|
529
|
+
* @param nodes begin nodes
|
|
530
|
+
* @param fn will be called while visiting each node
|
|
531
|
+
* @param mode 'TB' - visit from top to bottom; 'BT' - visit from bottom to top;
|
|
532
|
+
* @returns
|
|
533
|
+
*/
|
|
534
|
+
const graphTreeDfs = (graph, nodes, fn, mode = 'TB', treeKey, stopFns = {}) => {
|
|
535
|
+
if (!(nodes === null || nodes === void 0 ? void 0 : nodes.length))
|
|
536
|
+
return;
|
|
537
|
+
const { stopBranchFn, stopAllFn } = stopFns;
|
|
538
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
539
|
+
const node = nodes[i];
|
|
540
|
+
if (!graph.hasNode(node.id))
|
|
541
|
+
continue;
|
|
542
|
+
if (stopBranchFn === null || stopBranchFn === void 0 ? void 0 : stopBranchFn(node))
|
|
543
|
+
continue; // Stop this branch
|
|
544
|
+
if (stopAllFn === null || stopAllFn === void 0 ? void 0 : stopAllFn(node))
|
|
545
|
+
return; // Stop all
|
|
546
|
+
if (mode === 'TB')
|
|
547
|
+
fn(node); // Traverse from top to bottom
|
|
548
|
+
graphTreeDfs(graph, graph.getChildren(node.id, treeKey), fn, mode, treeKey, stopFns);
|
|
549
|
+
if (mode !== 'TB')
|
|
550
|
+
fn(node); // Traverse from bottom to top
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
/**
|
|
554
|
+
* Use Johnson + Dijkstra to compute APSP for sparse graph.
|
|
555
|
+
* Fully compatible with floydWarshall(adjMatrix).
|
|
556
|
+
*/
|
|
557
|
+
function johnson(adjList) {
|
|
558
|
+
const n = adjList.length;
|
|
559
|
+
// Step 1: add a dummy node q connected to all nodes with weight 0
|
|
560
|
+
new Array(n).fill(0);
|
|
561
|
+
// Bellman-Ford to compute potentials h(v)
|
|
562
|
+
// 因为权重全是 1,无负边,可直接跳过 BF,h 全 0 即可
|
|
563
|
+
// Step 2: reweight edges
|
|
564
|
+
// 因为 h(u)=h(v)=0,reweight 后仍然是 1,省略 reweight 过程
|
|
565
|
+
// Step 3: run Dijkstra from each node
|
|
566
|
+
const distAll = Array.from({ length: n }, () => new Array(n).fill(Infinity));
|
|
567
|
+
for (let s = 0; s < n; s++) {
|
|
568
|
+
distAll[s] = dijkstra(adjList, s);
|
|
569
|
+
}
|
|
570
|
+
return distAll;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Dijkstra algorithm to find shortest paths from source to all nodes.
|
|
719
574
|
*/
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
if (
|
|
730
|
-
|
|
575
|
+
function dijkstra(adjList, source) {
|
|
576
|
+
const n = adjList.length;
|
|
577
|
+
const dist = new Array(n).fill(Infinity);
|
|
578
|
+
dist[source] = 0;
|
|
579
|
+
// Minimal binary heap
|
|
580
|
+
const heap = new MinHeap();
|
|
581
|
+
heap.push([0, source]); // [distance, node]
|
|
582
|
+
while (!heap.empty()) {
|
|
583
|
+
const [d, u] = heap.pop();
|
|
584
|
+
if (d !== dist[u])
|
|
585
|
+
continue;
|
|
586
|
+
const neighbors = adjList[u];
|
|
587
|
+
for (let i = 0; i < neighbors.length; i++) {
|
|
588
|
+
const v = neighbors[i];
|
|
589
|
+
const nd = d + 1;
|
|
590
|
+
if (nd < dist[v]) {
|
|
591
|
+
dist[v] = nd;
|
|
592
|
+
heap.push([nd, v]);
|
|
593
|
+
}
|
|
731
594
|
}
|
|
732
595
|
}
|
|
733
|
-
return
|
|
596
|
+
return dist;
|
|
734
597
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
598
|
+
class MinHeap {
|
|
599
|
+
constructor() {
|
|
600
|
+
this.data = [];
|
|
601
|
+
}
|
|
602
|
+
push(item) {
|
|
603
|
+
this.data.push(item);
|
|
604
|
+
this.bubbleUp(this.data.length - 1);
|
|
605
|
+
}
|
|
606
|
+
pop() {
|
|
607
|
+
const top = this.data[0];
|
|
608
|
+
const end = this.data.pop();
|
|
609
|
+
if (this.data.length > 0) {
|
|
610
|
+
this.data[0] = end;
|
|
611
|
+
this.bubbleDown(0);
|
|
743
612
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
{
|
|
758
|
-
parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
|
|
759
|
-
returnValue = true;
|
|
760
|
-
}
|
|
761
|
-
break;
|
|
762
|
-
case "APPLY" /* MessageType.APPLY */:
|
|
763
|
-
{
|
|
764
|
-
returnValue = rawValue.apply(parent, argumentList);
|
|
765
|
-
}
|
|
766
|
-
break;
|
|
767
|
-
case "CONSTRUCT" /* MessageType.CONSTRUCT */:
|
|
768
|
-
{
|
|
769
|
-
const value = new rawValue(...argumentList);
|
|
770
|
-
returnValue = proxy(value);
|
|
771
|
-
}
|
|
772
|
-
break;
|
|
773
|
-
case "ENDPOINT" /* MessageType.ENDPOINT */:
|
|
774
|
-
{
|
|
775
|
-
const { port1, port2 } = new MessageChannel();
|
|
776
|
-
expose(obj, port2);
|
|
777
|
-
returnValue = transfer(port1, [port1]);
|
|
778
|
-
}
|
|
779
|
-
break;
|
|
780
|
-
case "RELEASE" /* MessageType.RELEASE */:
|
|
781
|
-
{
|
|
782
|
-
returnValue = undefined;
|
|
783
|
-
}
|
|
784
|
-
break;
|
|
785
|
-
default:
|
|
786
|
-
return;
|
|
787
|
-
}
|
|
613
|
+
return top;
|
|
614
|
+
}
|
|
615
|
+
empty() {
|
|
616
|
+
return this.data.length === 0;
|
|
617
|
+
}
|
|
618
|
+
bubbleUp(pos) {
|
|
619
|
+
const data = this.data;
|
|
620
|
+
while (pos > 0) {
|
|
621
|
+
const parent = (pos - 1) >> 1;
|
|
622
|
+
if (data[parent][0] <= data[pos][0])
|
|
623
|
+
break;
|
|
624
|
+
[data[parent], data[pos]] = [data[pos], data[parent]];
|
|
625
|
+
pos = parent;
|
|
788
626
|
}
|
|
789
|
-
|
|
790
|
-
|
|
627
|
+
}
|
|
628
|
+
bubbleDown(pos) {
|
|
629
|
+
const data = this.data;
|
|
630
|
+
const length = data.length;
|
|
631
|
+
while (true) {
|
|
632
|
+
const left = pos * 2 + 1;
|
|
633
|
+
const right = pos * 2 + 2;
|
|
634
|
+
let min = pos;
|
|
635
|
+
if (left < length && data[left][0] < data[min][0])
|
|
636
|
+
min = left;
|
|
637
|
+
if (right < length && data[right][0] < data[min][0])
|
|
638
|
+
min = right;
|
|
639
|
+
if (min === pos)
|
|
640
|
+
break;
|
|
641
|
+
[data[pos], data[min]] = [data[min], data[pos]];
|
|
642
|
+
pos = min;
|
|
791
643
|
}
|
|
792
|
-
Promise.resolve(returnValue)
|
|
793
|
-
.catch((value) => {
|
|
794
|
-
return { value, [throwMarker]: 0 };
|
|
795
|
-
})
|
|
796
|
-
.then((returnValue) => {
|
|
797
|
-
const [wireValue, transferables] = toWireValue(returnValue);
|
|
798
|
-
ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
|
|
799
|
-
if (type === "RELEASE" /* MessageType.RELEASE */) {
|
|
800
|
-
// detach and deactive after sending release response above.
|
|
801
|
-
ep.removeEventListener("message", callback);
|
|
802
|
-
closeEndPoint(ep);
|
|
803
|
-
if (finalizer in obj && typeof obj[finalizer] === "function") {
|
|
804
|
-
obj[finalizer]();
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
})
|
|
808
|
-
.catch((error) => {
|
|
809
|
-
// Send Serialization Error To Caller
|
|
810
|
-
const [wireValue, transferables] = toWireValue({
|
|
811
|
-
value: new TypeError("Unserializable return value"),
|
|
812
|
-
[throwMarker]: 0,
|
|
813
|
-
});
|
|
814
|
-
ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
|
|
815
|
-
});
|
|
816
|
-
});
|
|
817
|
-
if (ep.start) {
|
|
818
|
-
ep.start();
|
|
819
644
|
}
|
|
820
645
|
}
|
|
821
|
-
|
|
822
|
-
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Get nested property value
|
|
649
|
+
* For example: getNestedValue(obj, 'a.b.c') will return obj.a.b.c
|
|
650
|
+
*/
|
|
651
|
+
function getNestedValue(obj, path) {
|
|
652
|
+
const keys = String(path).split('.');
|
|
653
|
+
return get$1(obj, keys);
|
|
823
654
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
655
|
+
/**
|
|
656
|
+
* Set nested property value
|
|
657
|
+
* For example: setNestedValue(obj, 'a.b.c', value) will set obj.a.b.c = value
|
|
658
|
+
*/
|
|
659
|
+
function setNestedValue(obj, path, value) {
|
|
660
|
+
const keys = String(path).split('.');
|
|
661
|
+
set$1(obj, keys, value);
|
|
827
662
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
663
|
+
/**
|
|
664
|
+
* Merge objects, but undefined values in source objects will not override existing values
|
|
665
|
+
* @param target - The target object
|
|
666
|
+
* @param sources - Source objects to merge
|
|
667
|
+
* @returns A new merged object
|
|
668
|
+
*
|
|
669
|
+
* @example
|
|
670
|
+
* assignDefined({ a: 1, b: 2 }, { b: undefined, c: 3 })
|
|
671
|
+
* // Returns: { a: 1, b: 2, c: 3 }
|
|
672
|
+
*/
|
|
673
|
+
function assignDefined(target, ...sources) {
|
|
674
|
+
sources.forEach((source) => {
|
|
675
|
+
if (source) {
|
|
676
|
+
Object.keys(source).forEach((key) => {
|
|
677
|
+
const value = source[key];
|
|
678
|
+
if (value !== undefined) {
|
|
679
|
+
target[key] = value;
|
|
680
|
+
}
|
|
681
|
+
});
|
|
844
682
|
}
|
|
845
683
|
});
|
|
846
|
-
return
|
|
684
|
+
return target;
|
|
847
685
|
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* 通用排序核心函数
|
|
689
|
+
*/
|
|
690
|
+
function sort$1(model, compareFn) {
|
|
691
|
+
const nodes = model.nodes();
|
|
692
|
+
nodes.sort(compareFn);
|
|
693
|
+
model.setNodeOrder(nodes);
|
|
694
|
+
return model;
|
|
852
695
|
}
|
|
853
|
-
function
|
|
854
|
-
return
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
696
|
+
function orderByDegree(model, order = 'desc') {
|
|
697
|
+
return sort$1(model, (nodeA, nodeB) => {
|
|
698
|
+
const degreeA = model.degree(nodeA.id);
|
|
699
|
+
const degreeB = model.degree(nodeB.id);
|
|
700
|
+
if (order === 'asc') {
|
|
701
|
+
return degreeA - degreeB; // ascending order
|
|
702
|
+
}
|
|
703
|
+
return degreeB - degreeA; // descending order
|
|
858
704
|
});
|
|
859
705
|
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
706
|
+
/**
|
|
707
|
+
* 按 ID 排序
|
|
708
|
+
*/
|
|
709
|
+
function orderById(model) {
|
|
710
|
+
return sort$1(model, (nodeA, nodeB) => {
|
|
711
|
+
const idA = nodeA.id;
|
|
712
|
+
const idB = nodeB.id;
|
|
713
|
+
if (typeof idA === 'number' && typeof idB === 'number') {
|
|
714
|
+
return idA - idB;
|
|
867
715
|
}
|
|
716
|
+
return String(idA).localeCompare(String(idB));
|
|
868
717
|
});
|
|
869
|
-
function registerProxy(proxy, ep) {
|
|
870
|
-
const newCount = (proxyCounter.get(ep) || 0) + 1;
|
|
871
|
-
proxyCounter.set(ep, newCount);
|
|
872
|
-
if (proxyFinalizers) {
|
|
873
|
-
proxyFinalizers.register(proxy, ep, proxy);
|
|
874
|
-
}
|
|
875
718
|
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
719
|
+
/**
|
|
720
|
+
* 按自定义比较函数排序
|
|
721
|
+
*/
|
|
722
|
+
function orderBySorter(model, sorter) {
|
|
723
|
+
return sort$1(model, (nodeA, nodeB) => {
|
|
724
|
+
const a = model.originalNode(nodeA.id);
|
|
725
|
+
const b = model.originalNode(nodeB.id);
|
|
726
|
+
return sorter(a, b);
|
|
727
|
+
});
|
|
880
728
|
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
729
|
+
/**
|
|
730
|
+
* Order nodes according to graph topology
|
|
731
|
+
*/
|
|
732
|
+
function orderByTopology(model, directed = false) {
|
|
733
|
+
const n = model.nodeCount();
|
|
734
|
+
if (n === 0)
|
|
735
|
+
return model;
|
|
736
|
+
const nodes = model.nodes();
|
|
737
|
+
const orderedNodes = [nodes[0]];
|
|
738
|
+
const pickFlags = {};
|
|
739
|
+
pickFlags[nodes[0].id] = true;
|
|
740
|
+
let k = 0;
|
|
741
|
+
let i = 0;
|
|
742
|
+
model.forEachNode((node) => {
|
|
743
|
+
if (i !== 0) {
|
|
744
|
+
const currentDegree = model.degree(node.id, 'both');
|
|
745
|
+
const nextDegree = i < n - 1 ? model.degree(nodes[i + 1].id, 'both') : 0;
|
|
746
|
+
const currentNodeId = orderedNodes[k].id;
|
|
747
|
+
const isNeighbor = model
|
|
748
|
+
.neighbors(currentNodeId, 'both')
|
|
749
|
+
.includes(node.id);
|
|
750
|
+
if ((i === n - 1 || currentDegree !== nextDegree || isNeighbor) &&
|
|
751
|
+
!pickFlags[node.id]) {
|
|
752
|
+
orderedNodes.push(node);
|
|
753
|
+
pickFlags[node.id] = true;
|
|
754
|
+
k++;
|
|
893
755
|
}
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
756
|
+
else {
|
|
757
|
+
const children = directed
|
|
758
|
+
? model.successors(currentNodeId)
|
|
759
|
+
: model.neighbors(currentNodeId);
|
|
760
|
+
let foundChild = false;
|
|
761
|
+
for (let j = 0; j < children.length; j++) {
|
|
762
|
+
const childId = children[j];
|
|
763
|
+
const child = model.node(childId);
|
|
764
|
+
if (child &&
|
|
765
|
+
model.degree(childId) === model.degree(node.id) &&
|
|
766
|
+
!pickFlags[childId]) {
|
|
767
|
+
orderedNodes.push(child);
|
|
768
|
+
pickFlags[childId] = true;
|
|
769
|
+
foundChild = true;
|
|
770
|
+
break;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
let ii = 0;
|
|
774
|
+
while (!foundChild) {
|
|
775
|
+
if (!pickFlags[nodes[ii].id]) {
|
|
776
|
+
orderedNodes.push(nodes[ii]);
|
|
777
|
+
pickFlags[nodes[ii].id] = true;
|
|
778
|
+
foundChild = true;
|
|
779
|
+
}
|
|
780
|
+
ii++;
|
|
781
|
+
if (ii === n) {
|
|
782
|
+
break;
|
|
783
|
+
}
|
|
897
784
|
}
|
|
898
|
-
const r = requestResponseMessage(ep, pendingListeners, {
|
|
899
|
-
type: "GET" /* MessageType.GET */,
|
|
900
|
-
path: path.map((p) => p.toString()),
|
|
901
|
-
}).then(fromWireValue);
|
|
902
|
-
return r.then.bind(r);
|
|
903
|
-
}
|
|
904
|
-
return createProxy(ep, pendingListeners, [...path, prop]);
|
|
905
|
-
},
|
|
906
|
-
set(_target, prop, rawValue) {
|
|
907
|
-
throwIfProxyReleased(isProxyReleased);
|
|
908
|
-
// FIXME: ES6 Proxy Handler `set` methods are supposed to return a
|
|
909
|
-
// boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯
|
|
910
|
-
const [value, transferables] = toWireValue(rawValue);
|
|
911
|
-
return requestResponseMessage(ep, pendingListeners, {
|
|
912
|
-
type: "SET" /* MessageType.SET */,
|
|
913
|
-
path: [...path, prop].map((p) => p.toString()),
|
|
914
|
-
value,
|
|
915
|
-
}, transferables).then(fromWireValue);
|
|
916
|
-
},
|
|
917
|
-
apply(_target, _thisArg, rawArgumentList) {
|
|
918
|
-
throwIfProxyReleased(isProxyReleased);
|
|
919
|
-
const last = path[path.length - 1];
|
|
920
|
-
if (last === createEndpoint) {
|
|
921
|
-
return requestResponseMessage(ep, pendingListeners, {
|
|
922
|
-
type: "ENDPOINT" /* MessageType.ENDPOINT */,
|
|
923
|
-
}).then(fromWireValue);
|
|
924
|
-
}
|
|
925
|
-
// We just pretend that `bind()` didn’t happen.
|
|
926
|
-
if (last === "bind") {
|
|
927
|
-
return createProxy(ep, pendingListeners, path.slice(0, -1));
|
|
928
785
|
}
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
type: "APPLY" /* MessageType.APPLY */,
|
|
932
|
-
path: path.map((p) => p.toString()),
|
|
933
|
-
argumentList,
|
|
934
|
-
}, transferables).then(fromWireValue);
|
|
935
|
-
},
|
|
936
|
-
construct(_target, rawArgumentList) {
|
|
937
|
-
throwIfProxyReleased(isProxyReleased);
|
|
938
|
-
const [argumentList, transferables] = processArguments(rawArgumentList);
|
|
939
|
-
return requestResponseMessage(ep, pendingListeners, {
|
|
940
|
-
type: "CONSTRUCT" /* MessageType.CONSTRUCT */,
|
|
941
|
-
path: path.map((p) => p.toString()),
|
|
942
|
-
argumentList,
|
|
943
|
-
}, transferables).then(fromWireValue);
|
|
944
|
-
},
|
|
786
|
+
}
|
|
787
|
+
i++;
|
|
945
788
|
});
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
function myFlat(arr) {
|
|
950
|
-
return Array.prototype.concat.apply([], arr);
|
|
789
|
+
// Update model with ordered nodes
|
|
790
|
+
model.setNodeOrder(orderedNodes);
|
|
791
|
+
return model;
|
|
951
792
|
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
793
|
+
|
|
794
|
+
function parsePoint(point) {
|
|
795
|
+
var _a;
|
|
796
|
+
return [point.x, point.y, (_a = point.z) !== null && _a !== void 0 ? _a : 0];
|
|
955
797
|
}
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
return obj;
|
|
798
|
+
function toPointObject(point) {
|
|
799
|
+
var _a;
|
|
800
|
+
return { x: point[0], y: point[1], z: (_a = point[2]) !== null && _a !== void 0 ? _a : 0 };
|
|
960
801
|
}
|
|
961
|
-
|
|
962
|
-
|
|
802
|
+
|
|
803
|
+
function parseSize(size) {
|
|
804
|
+
if (!size)
|
|
805
|
+
return [0, 0, 0];
|
|
806
|
+
if (isNumber(size))
|
|
807
|
+
return [size, size, size];
|
|
808
|
+
else if (Array.isArray(size) && size.length === 0)
|
|
809
|
+
return [0, 0, 0];
|
|
810
|
+
const [x, y = x, z = x] = size;
|
|
811
|
+
return [x, y, z];
|
|
963
812
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Viewport configuration such as width, height and center point.
|
|
816
|
+
*/
|
|
817
|
+
const normalizeViewport = (options) => {
|
|
818
|
+
const { width, height, center } = options;
|
|
819
|
+
const normalizedWidth = width !== null && width !== void 0 ? width : (typeof window !== 'undefined' ? window.innerWidth : 0);
|
|
820
|
+
const normalizedHeight = height !== null && height !== void 0 ? height : (typeof window !== 'undefined' ? window.innerHeight : 0);
|
|
821
|
+
const centerPoint = center !== null && center !== void 0 ? center : [normalizedWidth / 2, normalizedHeight / 2];
|
|
822
|
+
return {
|
|
823
|
+
width: normalizedWidth,
|
|
824
|
+
height: normalizedHeight,
|
|
825
|
+
center: centerPoint,
|
|
826
|
+
};
|
|
827
|
+
};
|
|
828
|
+
|
|
829
|
+
/**
|
|
830
|
+
* Format value with multiple types into a function that returns a number
|
|
831
|
+
* @param value The value to be formatted
|
|
832
|
+
* @param defaultValue The default value when value is invalid
|
|
833
|
+
* @returns A function that returns a number
|
|
834
|
+
*/
|
|
835
|
+
function formatNumberFn(value, defaultValue) {
|
|
836
|
+
// If value is a function, return it directly
|
|
837
|
+
if (isFunction(value)) {
|
|
838
|
+
return value;
|
|
977
839
|
}
|
|
978
|
-
return
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
];
|
|
840
|
+
// If value is a number, return a function that returns this number
|
|
841
|
+
if (isNumber(value)) {
|
|
842
|
+
return () => value;
|
|
843
|
+
}
|
|
844
|
+
// For other cases (undefined or invalid values), return default value function
|
|
845
|
+
return () => defaultValue;
|
|
985
846
|
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
847
|
+
/**
|
|
848
|
+
* Format size config with multiple types into a function that returns a size
|
|
849
|
+
* @param value The value to be formatted
|
|
850
|
+
* @param defaultValue The default value when value is invalid
|
|
851
|
+
* @param resultIsNumber Whether to return a number (max of width/height) or size array
|
|
852
|
+
* @returns A function that returns a size
|
|
853
|
+
*/
|
|
854
|
+
function formatSizeFn(value, defaultValue = 10) {
|
|
855
|
+
// If value is undefined, return default value function
|
|
856
|
+
if (!value) {
|
|
857
|
+
return () => defaultValue;
|
|
858
|
+
}
|
|
859
|
+
// If value is a function, return it directly
|
|
860
|
+
if (isFunction(value)) {
|
|
861
|
+
return value;
|
|
862
|
+
}
|
|
863
|
+
// If value is a number, return a function that returns this number
|
|
864
|
+
if (isNumber(value)) {
|
|
865
|
+
return () => value;
|
|
992
866
|
}
|
|
867
|
+
// If value is an array, return max or the array itself
|
|
868
|
+
if (Array.isArray(value)) {
|
|
869
|
+
return () => value;
|
|
870
|
+
}
|
|
871
|
+
// If value is an object with width and height
|
|
872
|
+
if (isObject$1(value) && value.width && value.height) {
|
|
873
|
+
return () => [value.width, value.height];
|
|
874
|
+
}
|
|
875
|
+
return () => defaultValue;
|
|
993
876
|
}
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
}
|
|
877
|
+
/**
|
|
878
|
+
* Format nodeSize and nodeSpacing into a function that returns the total size
|
|
879
|
+
* @param nodeSize The size of the node
|
|
880
|
+
* @param nodeSpacing The spacing around the node
|
|
881
|
+
* @param defaultNodeSize The default node size when value is invalid
|
|
882
|
+
* @returns A function that returns the total size (node size + spacing)
|
|
883
|
+
*/
|
|
884
|
+
const formatNodeSizeFn = (nodeSize, nodeSpacing, defaultNodeSize = 10) => {
|
|
885
|
+
const nodeSpacingFunc = formatNumberFn(nodeSpacing, 0);
|
|
886
|
+
const nodeSizeFunc = formatSizeFn(nodeSize, defaultNodeSize);
|
|
887
|
+
return (node) => {
|
|
888
|
+
const size = nodeSizeFunc(node);
|
|
889
|
+
const spacing = nodeSpacingFunc(node);
|
|
890
|
+
return Math.max(...parseSize(size)) + spacing;
|
|
891
|
+
};
|
|
892
|
+
};
|
|
1010
893
|
|
|
1011
|
-
class
|
|
1012
|
-
constructor() {
|
|
1013
|
-
this.
|
|
1014
|
-
this.
|
|
894
|
+
class GraphLib {
|
|
895
|
+
constructor(data, options = {}) {
|
|
896
|
+
this.edgeIdCounter = new Map();
|
|
897
|
+
this.nodeMap = extractNodeData(data.nodes, options.node);
|
|
898
|
+
this.edgeMap = extractEdgeData(data.edges || [], options.edge, this.getEdgeId.bind(this));
|
|
1015
899
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
*/
|
|
1019
|
-
execute(layoutId, data, options) {
|
|
1020
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1021
|
-
if (!this.worker) {
|
|
1022
|
-
yield this.initWorker();
|
|
1023
|
-
}
|
|
1024
|
-
if (!this.workerApi) {
|
|
1025
|
-
throw new Error('Worker API not initialized');
|
|
1026
|
-
}
|
|
1027
|
-
return yield this.workerApi.execute(layoutId, data, options);
|
|
1028
|
-
});
|
|
900
|
+
data() {
|
|
901
|
+
return { nodes: this.nodeMap, edges: this.edgeMap };
|
|
1029
902
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
903
|
+
replace(result) {
|
|
904
|
+
this.nodeMap = result.nodes;
|
|
905
|
+
this.edgeMap = result.edges;
|
|
906
|
+
this.clearCache();
|
|
907
|
+
}
|
|
908
|
+
nodes() {
|
|
909
|
+
return Array.from(this.nodeMap.values());
|
|
910
|
+
}
|
|
911
|
+
node(id) {
|
|
912
|
+
return this.nodeMap.get(id);
|
|
913
|
+
}
|
|
914
|
+
nodeAt(index) {
|
|
915
|
+
if (!this.indexNodeCache) {
|
|
916
|
+
this.buildNodeIndexCache();
|
|
1036
917
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
918
|
+
const nodeId = this.indexNodeCache.get(index);
|
|
919
|
+
return nodeId ? this.nodeMap.get(nodeId) : undefined;
|
|
920
|
+
}
|
|
921
|
+
nodeIndexOf(id) {
|
|
922
|
+
var _a;
|
|
923
|
+
if (!this.nodeIndexCache) {
|
|
924
|
+
this.buildNodeIndexCache();
|
|
1041
925
|
}
|
|
926
|
+
return (_a = this.nodeIndexCache.get(id)) !== null && _a !== void 0 ? _a : -1;
|
|
1042
927
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
*/
|
|
1046
|
-
initWorker() {
|
|
1047
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1048
|
-
const workerPath = this.resolveWorkerPath();
|
|
1049
|
-
const isESM = workerPath.includes('/lib/') || workerPath.endsWith('.mjs');
|
|
1050
|
-
const type = isESM ? 'module' : 'classic';
|
|
1051
|
-
this.worker = new Worker(workerPath, { type });
|
|
1052
|
-
this.workerApi = wrap(this.worker);
|
|
1053
|
-
});
|
|
928
|
+
firstNode() {
|
|
929
|
+
return this.nodeMap.values().next().value;
|
|
1054
930
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
931
|
+
forEachNode(callback) {
|
|
932
|
+
let i = 0;
|
|
933
|
+
this.nodeMap.forEach((node) => callback(node, i++));
|
|
934
|
+
}
|
|
935
|
+
originalNode(id) {
|
|
936
|
+
const node = this.nodeMap.get(id);
|
|
937
|
+
return node === null || node === void 0 ? void 0 : node._original;
|
|
938
|
+
}
|
|
939
|
+
nodeCount() {
|
|
940
|
+
return this.nodeMap.size;
|
|
941
|
+
}
|
|
942
|
+
edges() {
|
|
943
|
+
return Array.from(this.edgeMap.values());
|
|
944
|
+
}
|
|
945
|
+
edge(id) {
|
|
946
|
+
return this.edgeMap.get(id);
|
|
947
|
+
}
|
|
948
|
+
firstEdge() {
|
|
949
|
+
return this.edgeMap.values().next().value;
|
|
950
|
+
}
|
|
951
|
+
forEachEdge(callback) {
|
|
952
|
+
let i = 0;
|
|
953
|
+
this.edgeMap.forEach((edge) => callback(edge, i++));
|
|
954
|
+
}
|
|
955
|
+
originalEdge(id) {
|
|
956
|
+
const edge = this.edgeMap.get(id);
|
|
957
|
+
return edge === null || edge === void 0 ? void 0 : edge._original;
|
|
958
|
+
}
|
|
959
|
+
edgeCount() {
|
|
960
|
+
return this.edgeMap.size;
|
|
961
|
+
}
|
|
962
|
+
getEdgeId(edge) {
|
|
963
|
+
if (edge.id)
|
|
964
|
+
return edge.id;
|
|
965
|
+
const baseId = `${edge.source}-${edge.target}`;
|
|
966
|
+
const count = this.edgeIdCounter.get(baseId) || 0;
|
|
967
|
+
const id = count === 0 ? baseId : `${baseId}-${count}`;
|
|
968
|
+
this.edgeIdCounter.set(baseId, count + 1);
|
|
969
|
+
return id;
|
|
970
|
+
}
|
|
971
|
+
degree(nodeId, direction = 'both') {
|
|
972
|
+
if (!this.degreeCache) {
|
|
973
|
+
this.buildDegreeCache();
|
|
1067
974
|
}
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
975
|
+
const degree = this.degreeCache.get(nodeId);
|
|
976
|
+
if (!degree)
|
|
977
|
+
return 0;
|
|
978
|
+
return degree[direction];
|
|
979
|
+
}
|
|
980
|
+
neighbors(nodeId, direction = 'both') {
|
|
981
|
+
if (!this.outAdjacencyCache || !this.inAdjacencyCache) {
|
|
982
|
+
this.buildAdjacencyCache();
|
|
983
|
+
}
|
|
984
|
+
if (direction === 'out') {
|
|
985
|
+
return Array.from(this.outAdjacencyCache.get(nodeId) || []);
|
|
986
|
+
}
|
|
987
|
+
if (direction === 'in') {
|
|
988
|
+
return Array.from(this.inAdjacencyCache.get(nodeId) || []);
|
|
989
|
+
}
|
|
990
|
+
if (this.bothAdjacencyCache) {
|
|
991
|
+
return Array.from(this.bothAdjacencyCache.get(nodeId) || []);
|
|
992
|
+
}
|
|
993
|
+
const inSet = this.inAdjacencyCache.get(nodeId);
|
|
994
|
+
const outSet = this.outAdjacencyCache.get(nodeId);
|
|
995
|
+
if (!inSet && !outSet)
|
|
996
|
+
return [];
|
|
997
|
+
if (!inSet)
|
|
998
|
+
return Array.from(outSet);
|
|
999
|
+
if (!outSet)
|
|
1000
|
+
return Array.from(inSet);
|
|
1001
|
+
const merged = new Set();
|
|
1002
|
+
inSet.forEach((id) => merged.add(id));
|
|
1003
|
+
outSet.forEach((id) => merged.add(id));
|
|
1004
|
+
return Array.from(merged);
|
|
1005
|
+
}
|
|
1006
|
+
successors(nodeId) {
|
|
1007
|
+
return this.neighbors(nodeId, 'out');
|
|
1008
|
+
}
|
|
1009
|
+
predecessors(nodeId) {
|
|
1010
|
+
return this.neighbors(nodeId, 'in');
|
|
1011
|
+
}
|
|
1012
|
+
setNodeOrder(nodes) {
|
|
1013
|
+
const next = new Map();
|
|
1014
|
+
for (const node of nodes)
|
|
1015
|
+
next.set(node.id, node);
|
|
1016
|
+
this.nodeMap = next;
|
|
1017
|
+
this.nodeIndexCache = undefined;
|
|
1018
|
+
this.indexNodeCache = undefined;
|
|
1019
|
+
}
|
|
1020
|
+
clearCache() {
|
|
1021
|
+
this.degreeCache = undefined;
|
|
1022
|
+
this.inAdjacencyCache = undefined;
|
|
1023
|
+
this.outAdjacencyCache = undefined;
|
|
1024
|
+
this.bothAdjacencyCache = undefined;
|
|
1025
|
+
this.nodeIndexCache = undefined;
|
|
1026
|
+
this.indexNodeCache = undefined;
|
|
1027
|
+
}
|
|
1028
|
+
buildDegreeCache() {
|
|
1029
|
+
this.degreeCache = new Map();
|
|
1030
|
+
for (const edge of this.edges()) {
|
|
1031
|
+
const { source, target } = edge;
|
|
1032
|
+
if (edge.source === edge.target)
|
|
1033
|
+
continue;
|
|
1034
|
+
if (!this.degreeCache.has(source)) {
|
|
1035
|
+
this.degreeCache.set(source, { in: 0, out: 0, both: 0 });
|
|
1036
|
+
}
|
|
1037
|
+
const sourceDeg = this.degreeCache.get(edge.source);
|
|
1038
|
+
if (sourceDeg) {
|
|
1039
|
+
sourceDeg.out++;
|
|
1040
|
+
sourceDeg.both++;
|
|
1041
|
+
}
|
|
1042
|
+
if (!this.degreeCache.has(target)) {
|
|
1043
|
+
this.degreeCache.set(target, { in: 0, out: 0, both: 0 });
|
|
1044
|
+
}
|
|
1045
|
+
const targetDeg = this.degreeCache.get(edge.target);
|
|
1046
|
+
if (targetDeg) {
|
|
1047
|
+
targetDeg.in++;
|
|
1048
|
+
targetDeg.both++;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
buildAdjacencyCache() {
|
|
1053
|
+
this.inAdjacencyCache = new Map();
|
|
1054
|
+
this.outAdjacencyCache = new Map();
|
|
1055
|
+
for (const edge of this.edges()) {
|
|
1056
|
+
if (!this.nodeMap.has(edge.source) || !this.nodeMap.has(edge.target))
|
|
1057
|
+
continue;
|
|
1058
|
+
if (!this.outAdjacencyCache.has(edge.source)) {
|
|
1059
|
+
this.outAdjacencyCache.set(edge.source, new Set());
|
|
1060
|
+
}
|
|
1061
|
+
this.outAdjacencyCache.get(edge.source).add(edge.target);
|
|
1062
|
+
if (!this.inAdjacencyCache.has(edge.target)) {
|
|
1063
|
+
this.inAdjacencyCache.set(edge.target, new Set());
|
|
1075
1064
|
}
|
|
1065
|
+
this.inAdjacencyCache.get(edge.target).add(edge.source);
|
|
1076
1066
|
}
|
|
1077
|
-
return './worker.js';
|
|
1078
1067
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
first.y = center[1];
|
|
1095
|
-
if (dimensions === 3) {
|
|
1096
|
-
first.z = center[2] || 0;
|
|
1097
|
-
}
|
|
1068
|
+
buildNodeIndexCache() {
|
|
1069
|
+
this.nodeIndexCache = new Map();
|
|
1070
|
+
this.indexNodeCache = new Map();
|
|
1071
|
+
let index = 0;
|
|
1072
|
+
this.nodeMap.forEach((_node, nodeId) => {
|
|
1073
|
+
this.nodeIndexCache.set(nodeId, index);
|
|
1074
|
+
this.indexNodeCache.set(index, nodeId);
|
|
1075
|
+
index++;
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
destroy() {
|
|
1079
|
+
this.clearCache();
|
|
1080
|
+
this.nodeMap.clear();
|
|
1081
|
+
this.edgeMap.clear();
|
|
1082
|
+
this.edgeIdCounter.clear();
|
|
1098
1083
|
}
|
|
1099
1084
|
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1085
|
+
const nodeFields = [
|
|
1086
|
+
'id',
|
|
1087
|
+
'x',
|
|
1088
|
+
'y',
|
|
1089
|
+
'z',
|
|
1090
|
+
'vx',
|
|
1091
|
+
'vy',
|
|
1092
|
+
'vz',
|
|
1093
|
+
'fx',
|
|
1094
|
+
'fy',
|
|
1095
|
+
'fz',
|
|
1096
|
+
'parentId',
|
|
1097
|
+
];
|
|
1098
|
+
const edgeFields = ['id', 'source', 'target', 'points'];
|
|
1099
|
+
function extractNodeData(nodes, node) {
|
|
1100
|
+
if (!nodes) {
|
|
1101
|
+
throw new Error('Data.nodes is required');
|
|
1114
1102
|
}
|
|
1115
|
-
|
|
1116
|
-
for (
|
|
1117
|
-
const
|
|
1118
|
-
for (
|
|
1119
|
-
const
|
|
1120
|
-
|
|
1121
|
-
if (dik === Infinity)
|
|
1103
|
+
const result = new Map();
|
|
1104
|
+
for (const datum of nodes) {
|
|
1105
|
+
const nodeData = { _original: datum };
|
|
1106
|
+
for (const field of nodeFields) {
|
|
1107
|
+
const value = datum[field];
|
|
1108
|
+
if (isNil(value))
|
|
1122
1109
|
continue;
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1110
|
+
nodeData[field] = value;
|
|
1111
|
+
}
|
|
1112
|
+
if (node) {
|
|
1113
|
+
const customFields = node(datum);
|
|
1114
|
+
for (const key in customFields) {
|
|
1115
|
+
const value = customFields[key];
|
|
1116
|
+
if (isNil(value))
|
|
1126
1117
|
continue;
|
|
1127
|
-
|
|
1128
|
-
if (next < di[j]) {
|
|
1129
|
-
di[j] = next;
|
|
1130
|
-
}
|
|
1118
|
+
nodeData[key] = value;
|
|
1131
1119
|
}
|
|
1132
1120
|
}
|
|
1121
|
+
if (isNil(nodeData.id)) {
|
|
1122
|
+
throw new Error(`Node is missing id field`);
|
|
1123
|
+
}
|
|
1124
|
+
result.set(nodeData.id, nodeData);
|
|
1133
1125
|
}
|
|
1134
|
-
return
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
model.forEachNode((node) => {
|
|
1146
|
-
nodeMap[node.id] = i++;
|
|
1147
|
-
});
|
|
1148
|
-
model.forEachEdge((e) => {
|
|
1149
|
-
const sIndex = nodeMap[e.source];
|
|
1150
|
-
const tIndex = nodeMap[e.target];
|
|
1151
|
-
if (sIndex === undefined || tIndex === undefined)
|
|
1152
|
-
return;
|
|
1153
|
-
matrix[sIndex][tIndex] = 1;
|
|
1154
|
-
if (!directed) {
|
|
1155
|
-
matrix[tIndex][sIndex] = 1;
|
|
1126
|
+
return result;
|
|
1127
|
+
}
|
|
1128
|
+
function extractEdgeData(edges, edge, getEdgeId) {
|
|
1129
|
+
const result = new Map();
|
|
1130
|
+
for (const datum of edges) {
|
|
1131
|
+
const edgeData = { _original: datum };
|
|
1132
|
+
for (const field of edgeFields) {
|
|
1133
|
+
const value = datum[field];
|
|
1134
|
+
if (isNil(value))
|
|
1135
|
+
continue;
|
|
1136
|
+
edgeData[field] = value;
|
|
1156
1137
|
}
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
const adjList = Array.from({ length: n }, () => []);
|
|
1166
|
-
// map node with index
|
|
1167
|
-
const nodeMap = {};
|
|
1168
|
-
let idx = 0;
|
|
1169
|
-
model.forEachNode((node) => {
|
|
1170
|
-
nodeMap[node.id] = idx++;
|
|
1171
|
-
});
|
|
1172
|
-
model.forEachEdge((e) => {
|
|
1173
|
-
const s = nodeMap[e.source];
|
|
1174
|
-
const t = nodeMap[e.target];
|
|
1175
|
-
if (s == null || t == null)
|
|
1176
|
-
return;
|
|
1177
|
-
adjList[s].push(t);
|
|
1178
|
-
if (!directed)
|
|
1179
|
-
adjList[t].push(s);
|
|
1180
|
-
});
|
|
1181
|
-
return adjList;
|
|
1182
|
-
};
|
|
1183
|
-
/**
|
|
1184
|
-
* scale matrix
|
|
1185
|
-
* @param matrix [ [], [], [] ]
|
|
1186
|
-
* @param ratio
|
|
1187
|
-
*/
|
|
1188
|
-
const scaleMatrix = (matrix, ratio) => {
|
|
1189
|
-
const n = matrix.length;
|
|
1190
|
-
const result = new Array(n);
|
|
1191
|
-
for (let i = 0; i < n; i++) {
|
|
1192
|
-
const row = matrix[i];
|
|
1193
|
-
const m = row.length;
|
|
1194
|
-
const newRow = new Array(m);
|
|
1195
|
-
for (let j = 0; j < m; j++) {
|
|
1196
|
-
newRow[j] = row[j] * ratio;
|
|
1138
|
+
if (edge) {
|
|
1139
|
+
const customFields = edge(datum);
|
|
1140
|
+
for (const key in customFields) {
|
|
1141
|
+
const value = customFields[key];
|
|
1142
|
+
if (isNil(value))
|
|
1143
|
+
continue;
|
|
1144
|
+
edgeData[key] = value;
|
|
1145
|
+
}
|
|
1197
1146
|
}
|
|
1198
|
-
|
|
1147
|
+
if (isNil(edgeData.source) || isNil(edgeData.target)) {
|
|
1148
|
+
throw new Error(`Edge is missing source or target field`);
|
|
1149
|
+
}
|
|
1150
|
+
if (isNil(edgeData.id)) {
|
|
1151
|
+
edgeData.id = getEdgeId === null || getEdgeId === void 0 ? void 0 : getEdgeId(datum);
|
|
1152
|
+
}
|
|
1153
|
+
result.set(edgeData.id, edgeData);
|
|
1199
1154
|
}
|
|
1200
1155
|
return result;
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
*/
|
|
1207
|
-
const getLayoutBBox = (nodes) => {
|
|
1208
|
-
let minX = Infinity;
|
|
1209
|
-
let minY = Infinity;
|
|
1210
|
-
let maxX = -Infinity;
|
|
1211
|
-
let maxY = -Infinity;
|
|
1212
|
-
nodes.forEach((node) => {
|
|
1213
|
-
let size = node.data.size;
|
|
1214
|
-
if (isArray(size)) {
|
|
1215
|
-
if (size.length === 1)
|
|
1216
|
-
size = [size[0], size[0]];
|
|
1156
|
+
}
|
|
1157
|
+
function initNodePosition(model, width, height, dimensions = 2) {
|
|
1158
|
+
model.forEachNode((node) => {
|
|
1159
|
+
if (isNil(node.x)) {
|
|
1160
|
+
node.x = Math.random() * width;
|
|
1217
1161
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1162
|
+
if (isNil(node.y)) {
|
|
1163
|
+
node.y = Math.random() * height;
|
|
1220
1164
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1165
|
+
if (dimensions === 3 && isNil(node.z)) {
|
|
1166
|
+
node.z = Math.random() * Math.min(width, height);
|
|
1223
1167
|
}
|
|
1224
|
-
const halfSize = [size[0] / 2, size[1] / 2];
|
|
1225
|
-
const left = node.data.x - halfSize[0];
|
|
1226
|
-
const right = node.data.x + halfSize[0];
|
|
1227
|
-
const top = node.data.y - halfSize[1];
|
|
1228
|
-
const bottom = node.data.y + halfSize[1];
|
|
1229
|
-
if (minX > left)
|
|
1230
|
-
minX = left;
|
|
1231
|
-
if (minY > top)
|
|
1232
|
-
minY = top;
|
|
1233
|
-
if (maxX < right)
|
|
1234
|
-
maxX = right;
|
|
1235
|
-
if (maxY < bottom)
|
|
1236
|
-
maxY = bottom;
|
|
1237
1168
|
});
|
|
1238
|
-
|
|
1239
|
-
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
class RuntimeContext {
|
|
1172
|
+
constructor(data, options = {}) {
|
|
1173
|
+
this.graph = new GraphLib(data, options);
|
|
1174
|
+
}
|
|
1175
|
+
export() {
|
|
1176
|
+
return this.graph.data();
|
|
1177
|
+
}
|
|
1178
|
+
replace(result) {
|
|
1179
|
+
this.graph.replace(result);
|
|
1180
|
+
}
|
|
1181
|
+
forEachNode(callback) {
|
|
1182
|
+
this.graph.forEachNode(callback);
|
|
1183
|
+
}
|
|
1184
|
+
forEachEdge(callback) {
|
|
1185
|
+
this.graph.forEachEdge((edge, i) => {
|
|
1186
|
+
edge.sourceNode = this.graph.node(edge.source);
|
|
1187
|
+
edge.targetNode = this.graph.node(edge.target);
|
|
1188
|
+
callback(edge, i);
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
destroy() {
|
|
1192
|
+
this.graph.destroy();
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1240
1196
|
/**
|
|
1241
|
-
*
|
|
1242
|
-
*
|
|
1243
|
-
*
|
|
1244
|
-
* @returns
|
|
1197
|
+
* @license
|
|
1198
|
+
* Copyright 2019 Google LLC
|
|
1199
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
1245
1200
|
*/
|
|
1246
|
-
const
|
|
1201
|
+
const proxyMarker = Symbol("Comlink.proxy");
|
|
1202
|
+
const createEndpoint = Symbol("Comlink.endpoint");
|
|
1203
|
+
const releaseProxy = Symbol("Comlink.releaseProxy");
|
|
1204
|
+
const finalizer = Symbol("Comlink.finalizer");
|
|
1205
|
+
const throwMarker = Symbol("Comlink.thrown");
|
|
1206
|
+
const isObject = (val) => (typeof val === "object" && val !== null) || typeof val === "function";
|
|
1247
1207
|
/**
|
|
1248
|
-
*
|
|
1249
|
-
* @param graphCore graphlib data structure
|
|
1250
|
-
* @param nodes begin nodes
|
|
1251
|
-
* @param fn will be called while visiting each node
|
|
1252
|
-
* @param mode 'TB' - visit from top to bottom; 'BT' - visit from bottom to top;
|
|
1253
|
-
* @returns
|
|
1208
|
+
* Internal transfer handle to handle objects marked to proxy.
|
|
1254
1209
|
*/
|
|
1255
|
-
const
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
return; // Stop all
|
|
1267
|
-
if (mode === 'TB')
|
|
1268
|
-
fn(node); // Traverse from top to bottom
|
|
1269
|
-
graphTreeDfs(graph, graph.getChildren(node.id, treeKey), fn, mode, treeKey, stopFns);
|
|
1270
|
-
if (mode !== 'TB')
|
|
1271
|
-
fn(node); // Traverse from bottom to top
|
|
1272
|
-
}
|
|
1210
|
+
const proxyTransferHandler = {
|
|
1211
|
+
canHandle: (val) => isObject(val) && val[proxyMarker],
|
|
1212
|
+
serialize(obj) {
|
|
1213
|
+
const { port1, port2 } = new MessageChannel();
|
|
1214
|
+
expose(obj, port1);
|
|
1215
|
+
return [port2, [port2]];
|
|
1216
|
+
},
|
|
1217
|
+
deserialize(port) {
|
|
1218
|
+
port.start();
|
|
1219
|
+
return wrap(port);
|
|
1220
|
+
},
|
|
1273
1221
|
};
|
|
1274
1222
|
/**
|
|
1275
|
-
*
|
|
1276
|
-
* Fully compatible with floydWarshall(adjMatrix).
|
|
1223
|
+
* Internal transfer handler to handle thrown exceptions.
|
|
1277
1224
|
*/
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1225
|
+
const throwTransferHandler = {
|
|
1226
|
+
canHandle: (value) => isObject(value) && throwMarker in value,
|
|
1227
|
+
serialize({ value }) {
|
|
1228
|
+
let serialized;
|
|
1229
|
+
if (value instanceof Error) {
|
|
1230
|
+
serialized = {
|
|
1231
|
+
isError: true,
|
|
1232
|
+
value: {
|
|
1233
|
+
message: value.message,
|
|
1234
|
+
name: value.name,
|
|
1235
|
+
stack: value.stack,
|
|
1236
|
+
},
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
1239
|
+
else {
|
|
1240
|
+
serialized = { isError: false, value };
|
|
1241
|
+
}
|
|
1242
|
+
return [serialized, []];
|
|
1243
|
+
},
|
|
1244
|
+
deserialize(serialized) {
|
|
1245
|
+
if (serialized.isError) {
|
|
1246
|
+
throw Object.assign(new Error(serialized.value.message), serialized.value);
|
|
1247
|
+
}
|
|
1248
|
+
throw serialized.value;
|
|
1249
|
+
},
|
|
1250
|
+
};
|
|
1293
1251
|
/**
|
|
1294
|
-
*
|
|
1252
|
+
* Allows customizing the serialization of certain values.
|
|
1295
1253
|
*/
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
const
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
if (
|
|
1306
|
-
|
|
1307
|
-
const neighbors = adjList[u];
|
|
1308
|
-
for (let i = 0; i < neighbors.length; i++) {
|
|
1309
|
-
const v = neighbors[i];
|
|
1310
|
-
const nd = d + 1;
|
|
1311
|
-
if (nd < dist[v]) {
|
|
1312
|
-
dist[v] = nd;
|
|
1313
|
-
heap.push([nd, v]);
|
|
1314
|
-
}
|
|
1254
|
+
const transferHandlers = new Map([
|
|
1255
|
+
["proxy", proxyTransferHandler],
|
|
1256
|
+
["throw", throwTransferHandler],
|
|
1257
|
+
]);
|
|
1258
|
+
function isAllowedOrigin(allowedOrigins, origin) {
|
|
1259
|
+
for (const allowedOrigin of allowedOrigins) {
|
|
1260
|
+
if (origin === allowedOrigin || allowedOrigin === "*") {
|
|
1261
|
+
return true;
|
|
1262
|
+
}
|
|
1263
|
+
if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {
|
|
1264
|
+
return true;
|
|
1315
1265
|
}
|
|
1316
1266
|
}
|
|
1317
|
-
return
|
|
1267
|
+
return false;
|
|
1318
1268
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
push(item) {
|
|
1324
|
-
this.data.push(item);
|
|
1325
|
-
this.bubbleUp(this.data.length - 1);
|
|
1326
|
-
}
|
|
1327
|
-
pop() {
|
|
1328
|
-
const top = this.data[0];
|
|
1329
|
-
const end = this.data.pop();
|
|
1330
|
-
if (this.data.length > 0) {
|
|
1331
|
-
this.data[0] = end;
|
|
1332
|
-
this.bubbleDown(0);
|
|
1269
|
+
function expose(obj, ep = globalThis, allowedOrigins = ["*"]) {
|
|
1270
|
+
ep.addEventListener("message", function callback(ev) {
|
|
1271
|
+
if (!ev || !ev.data) {
|
|
1272
|
+
return;
|
|
1333
1273
|
}
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
return this.data.length === 0;
|
|
1338
|
-
}
|
|
1339
|
-
bubbleUp(pos) {
|
|
1340
|
-
const data = this.data;
|
|
1341
|
-
while (pos > 0) {
|
|
1342
|
-
const parent = (pos - 1) >> 1;
|
|
1343
|
-
if (data[parent][0] <= data[pos][0])
|
|
1344
|
-
break;
|
|
1345
|
-
[data[parent], data[pos]] = [data[pos], data[parent]];
|
|
1346
|
-
pos = parent;
|
|
1274
|
+
if (!isAllowedOrigin(allowedOrigins, ev.origin)) {
|
|
1275
|
+
console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);
|
|
1276
|
+
return;
|
|
1347
1277
|
}
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
const
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1278
|
+
const { id, type, path } = Object.assign({ path: [] }, ev.data);
|
|
1279
|
+
const argumentList = (ev.data.argumentList || []).map(fromWireValue);
|
|
1280
|
+
let returnValue;
|
|
1281
|
+
try {
|
|
1282
|
+
const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj);
|
|
1283
|
+
const rawValue = path.reduce((obj, prop) => obj[prop], obj);
|
|
1284
|
+
switch (type) {
|
|
1285
|
+
case "GET" /* MessageType.GET */:
|
|
1286
|
+
{
|
|
1287
|
+
returnValue = rawValue;
|
|
1288
|
+
}
|
|
1289
|
+
break;
|
|
1290
|
+
case "SET" /* MessageType.SET */:
|
|
1291
|
+
{
|
|
1292
|
+
parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
|
|
1293
|
+
returnValue = true;
|
|
1294
|
+
}
|
|
1295
|
+
break;
|
|
1296
|
+
case "APPLY" /* MessageType.APPLY */:
|
|
1297
|
+
{
|
|
1298
|
+
returnValue = rawValue.apply(parent, argumentList);
|
|
1299
|
+
}
|
|
1300
|
+
break;
|
|
1301
|
+
case "CONSTRUCT" /* MessageType.CONSTRUCT */:
|
|
1302
|
+
{
|
|
1303
|
+
const value = new rawValue(...argumentList);
|
|
1304
|
+
returnValue = proxy(value);
|
|
1305
|
+
}
|
|
1306
|
+
break;
|
|
1307
|
+
case "ENDPOINT" /* MessageType.ENDPOINT */:
|
|
1308
|
+
{
|
|
1309
|
+
const { port1, port2 } = new MessageChannel();
|
|
1310
|
+
expose(obj, port2);
|
|
1311
|
+
returnValue = transfer(port1, [port1]);
|
|
1312
|
+
}
|
|
1313
|
+
break;
|
|
1314
|
+
case "RELEASE" /* MessageType.RELEASE */:
|
|
1315
|
+
{
|
|
1316
|
+
returnValue = undefined;
|
|
1317
|
+
}
|
|
1318
|
+
break;
|
|
1319
|
+
default:
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
catch (value) {
|
|
1324
|
+
returnValue = { value, [throwMarker]: 0 };
|
|
1364
1325
|
}
|
|
1326
|
+
Promise.resolve(returnValue)
|
|
1327
|
+
.catch((value) => {
|
|
1328
|
+
return { value, [throwMarker]: 0 };
|
|
1329
|
+
})
|
|
1330
|
+
.then((returnValue) => {
|
|
1331
|
+
const [wireValue, transferables] = toWireValue(returnValue);
|
|
1332
|
+
ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
|
|
1333
|
+
if (type === "RELEASE" /* MessageType.RELEASE */) {
|
|
1334
|
+
// detach and deactive after sending release response above.
|
|
1335
|
+
ep.removeEventListener("message", callback);
|
|
1336
|
+
closeEndPoint(ep);
|
|
1337
|
+
if (finalizer in obj && typeof obj[finalizer] === "function") {
|
|
1338
|
+
obj[finalizer]();
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
})
|
|
1342
|
+
.catch((error) => {
|
|
1343
|
+
// Send Serialization Error To Caller
|
|
1344
|
+
const [wireValue, transferables] = toWireValue({
|
|
1345
|
+
value: new TypeError("Unserializable return value"),
|
|
1346
|
+
[throwMarker]: 0,
|
|
1347
|
+
});
|
|
1348
|
+
ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
|
|
1349
|
+
});
|
|
1350
|
+
});
|
|
1351
|
+
if (ep.start) {
|
|
1352
|
+
ep.start();
|
|
1365
1353
|
}
|
|
1366
1354
|
}
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
* Get nested property value
|
|
1370
|
-
* For example: getNestedValue(obj, 'a.b.c') will return obj.a.b.c
|
|
1371
|
-
*/
|
|
1372
|
-
function getNestedValue(obj, path) {
|
|
1373
|
-
const keys = String(path).split('.');
|
|
1374
|
-
return get$1(obj, keys);
|
|
1355
|
+
function isMessagePort(endpoint) {
|
|
1356
|
+
return endpoint.constructor.name === "MessagePort";
|
|
1375
1357
|
}
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
*/
|
|
1380
|
-
function setNestedValue(obj, path, value) {
|
|
1381
|
-
const keys = String(path).split('.');
|
|
1382
|
-
set$1(obj, keys, value);
|
|
1358
|
+
function closeEndPoint(endpoint) {
|
|
1359
|
+
if (isMessagePort(endpoint))
|
|
1360
|
+
endpoint.close();
|
|
1383
1361
|
}
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
target[key] = value;
|
|
1401
|
-
}
|
|
1402
|
-
});
|
|
1362
|
+
function wrap(ep, target) {
|
|
1363
|
+
const pendingListeners = new Map();
|
|
1364
|
+
ep.addEventListener("message", function handleMessage(ev) {
|
|
1365
|
+
const { data } = ev;
|
|
1366
|
+
if (!data || !data.id) {
|
|
1367
|
+
return;
|
|
1368
|
+
}
|
|
1369
|
+
const resolver = pendingListeners.get(data.id);
|
|
1370
|
+
if (!resolver) {
|
|
1371
|
+
return;
|
|
1372
|
+
}
|
|
1373
|
+
try {
|
|
1374
|
+
resolver(data);
|
|
1375
|
+
}
|
|
1376
|
+
finally {
|
|
1377
|
+
pendingListeners.delete(data.id);
|
|
1403
1378
|
}
|
|
1404
1379
|
});
|
|
1405
|
-
return target;
|
|
1406
|
-
}
|
|
1407
|
-
function mergeOptions(base, patch) {
|
|
1408
|
-
return Object.assign({}, base, patch || {});
|
|
1380
|
+
return createProxy(ep, pendingListeners, [], target);
|
|
1409
1381
|
}
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
function sort$1(model, compareFn) {
|
|
1415
|
-
const nodes = model.nodes();
|
|
1416
|
-
nodes.sort(compareFn);
|
|
1417
|
-
model.setNodeOrder(nodes);
|
|
1418
|
-
return model;
|
|
1382
|
+
function throwIfProxyReleased(isReleased) {
|
|
1383
|
+
if (isReleased) {
|
|
1384
|
+
throw new Error("Proxy has been released and is not useable");
|
|
1385
|
+
}
|
|
1419
1386
|
}
|
|
1420
|
-
function
|
|
1421
|
-
return
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1387
|
+
function releaseEndpoint(ep) {
|
|
1388
|
+
return requestResponseMessage(ep, new Map(), {
|
|
1389
|
+
type: "RELEASE" /* MessageType.RELEASE */,
|
|
1390
|
+
}).then(() => {
|
|
1391
|
+
closeEndPoint(ep);
|
|
1425
1392
|
});
|
|
1426
1393
|
}
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
if (typeof idA === 'number' && typeof idB === 'number') {
|
|
1435
|
-
return idA - idB;
|
|
1394
|
+
const proxyCounter = new WeakMap();
|
|
1395
|
+
const proxyFinalizers = "FinalizationRegistry" in globalThis &&
|
|
1396
|
+
new FinalizationRegistry((ep) => {
|
|
1397
|
+
const newCount = (proxyCounter.get(ep) || 0) - 1;
|
|
1398
|
+
proxyCounter.set(ep, newCount);
|
|
1399
|
+
if (newCount === 0) {
|
|
1400
|
+
releaseEndpoint(ep);
|
|
1436
1401
|
}
|
|
1437
|
-
return String(idA).localeCompare(String(idB));
|
|
1438
1402
|
});
|
|
1403
|
+
function registerProxy(proxy, ep) {
|
|
1404
|
+
const newCount = (proxyCounter.get(ep) || 0) + 1;
|
|
1405
|
+
proxyCounter.set(ep, newCount);
|
|
1406
|
+
if (proxyFinalizers) {
|
|
1407
|
+
proxyFinalizers.register(proxy, ep, proxy);
|
|
1408
|
+
}
|
|
1439
1409
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
return sort$1(model, (nodeA, nodeB) => {
|
|
1445
|
-
const a = model.originalNode(nodeA.id);
|
|
1446
|
-
const b = model.originalNode(nodeB.id);
|
|
1447
|
-
return sorter(a, b);
|
|
1448
|
-
});
|
|
1410
|
+
function unregisterProxy(proxy) {
|
|
1411
|
+
if (proxyFinalizers) {
|
|
1412
|
+
proxyFinalizers.unregister(proxy);
|
|
1413
|
+
}
|
|
1449
1414
|
}
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
let i = 0;
|
|
1463
|
-
model.forEachNode((node) => {
|
|
1464
|
-
if (i !== 0) {
|
|
1465
|
-
const currentDegree = model.degree(node.id, 'both');
|
|
1466
|
-
const nextDegree = i < n - 1 ? model.degree(nodes[i + 1].id, 'both') : 0;
|
|
1467
|
-
const currentNodeId = orderedNodes[k].id;
|
|
1468
|
-
const isNeighbor = model
|
|
1469
|
-
.neighbors(currentNodeId, 'both')
|
|
1470
|
-
.includes(node.id);
|
|
1471
|
-
if ((i === n - 1 || currentDegree !== nextDegree || isNeighbor) &&
|
|
1472
|
-
!pickFlags[node.id]) {
|
|
1473
|
-
orderedNodes.push(node);
|
|
1474
|
-
pickFlags[node.id] = true;
|
|
1475
|
-
k++;
|
|
1415
|
+
function createProxy(ep, pendingListeners, path = [], target = function () { }) {
|
|
1416
|
+
let isProxyReleased = false;
|
|
1417
|
+
const proxy = new Proxy(target, {
|
|
1418
|
+
get(_target, prop) {
|
|
1419
|
+
throwIfProxyReleased(isProxyReleased);
|
|
1420
|
+
if (prop === releaseProxy) {
|
|
1421
|
+
return () => {
|
|
1422
|
+
unregisterProxy(proxy);
|
|
1423
|
+
releaseEndpoint(ep);
|
|
1424
|
+
pendingListeners.clear();
|
|
1425
|
+
isProxyReleased = true;
|
|
1426
|
+
};
|
|
1476
1427
|
}
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
: model.neighbors(currentNodeId);
|
|
1481
|
-
let foundChild = false;
|
|
1482
|
-
for (let j = 0; j < children.length; j++) {
|
|
1483
|
-
const childId = children[j];
|
|
1484
|
-
const child = model.node(childId);
|
|
1485
|
-
if (child &&
|
|
1486
|
-
model.degree(childId) === model.degree(node.id) &&
|
|
1487
|
-
!pickFlags[childId]) {
|
|
1488
|
-
orderedNodes.push(child);
|
|
1489
|
-
pickFlags[childId] = true;
|
|
1490
|
-
foundChild = true;
|
|
1491
|
-
break;
|
|
1492
|
-
}
|
|
1493
|
-
}
|
|
1494
|
-
let ii = 0;
|
|
1495
|
-
while (!foundChild) {
|
|
1496
|
-
if (!pickFlags[nodes[ii].id]) {
|
|
1497
|
-
orderedNodes.push(nodes[ii]);
|
|
1498
|
-
pickFlags[nodes[ii].id] = true;
|
|
1499
|
-
foundChild = true;
|
|
1500
|
-
}
|
|
1501
|
-
ii++;
|
|
1502
|
-
if (ii === n) {
|
|
1503
|
-
break;
|
|
1504
|
-
}
|
|
1428
|
+
if (prop === "then") {
|
|
1429
|
+
if (path.length === 0) {
|
|
1430
|
+
return { then: () => proxy };
|
|
1505
1431
|
}
|
|
1432
|
+
const r = requestResponseMessage(ep, pendingListeners, {
|
|
1433
|
+
type: "GET" /* MessageType.GET */,
|
|
1434
|
+
path: path.map((p) => p.toString()),
|
|
1435
|
+
}).then(fromWireValue);
|
|
1436
|
+
return r.then.bind(r);
|
|
1437
|
+
}
|
|
1438
|
+
return createProxy(ep, pendingListeners, [...path, prop]);
|
|
1439
|
+
},
|
|
1440
|
+
set(_target, prop, rawValue) {
|
|
1441
|
+
throwIfProxyReleased(isProxyReleased);
|
|
1442
|
+
// FIXME: ES6 Proxy Handler `set` methods are supposed to return a
|
|
1443
|
+
// boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯
|
|
1444
|
+
const [value, transferables] = toWireValue(rawValue);
|
|
1445
|
+
return requestResponseMessage(ep, pendingListeners, {
|
|
1446
|
+
type: "SET" /* MessageType.SET */,
|
|
1447
|
+
path: [...path, prop].map((p) => p.toString()),
|
|
1448
|
+
value,
|
|
1449
|
+
}, transferables).then(fromWireValue);
|
|
1450
|
+
},
|
|
1451
|
+
apply(_target, _thisArg, rawArgumentList) {
|
|
1452
|
+
throwIfProxyReleased(isProxyReleased);
|
|
1453
|
+
const last = path[path.length - 1];
|
|
1454
|
+
if (last === createEndpoint) {
|
|
1455
|
+
return requestResponseMessage(ep, pendingListeners, {
|
|
1456
|
+
type: "ENDPOINT" /* MessageType.ENDPOINT */,
|
|
1457
|
+
}).then(fromWireValue);
|
|
1458
|
+
}
|
|
1459
|
+
// We just pretend that `bind()` didn’t happen.
|
|
1460
|
+
if (last === "bind") {
|
|
1461
|
+
return createProxy(ep, pendingListeners, path.slice(0, -1));
|
|
1506
1462
|
}
|
|
1463
|
+
const [argumentList, transferables] = processArguments(rawArgumentList);
|
|
1464
|
+
return requestResponseMessage(ep, pendingListeners, {
|
|
1465
|
+
type: "APPLY" /* MessageType.APPLY */,
|
|
1466
|
+
path: path.map((p) => p.toString()),
|
|
1467
|
+
argumentList,
|
|
1468
|
+
}, transferables).then(fromWireValue);
|
|
1469
|
+
},
|
|
1470
|
+
construct(_target, rawArgumentList) {
|
|
1471
|
+
throwIfProxyReleased(isProxyReleased);
|
|
1472
|
+
const [argumentList, transferables] = processArguments(rawArgumentList);
|
|
1473
|
+
return requestResponseMessage(ep, pendingListeners, {
|
|
1474
|
+
type: "CONSTRUCT" /* MessageType.CONSTRUCT */,
|
|
1475
|
+
path: path.map((p) => p.toString()),
|
|
1476
|
+
argumentList,
|
|
1477
|
+
}, transferables).then(fromWireValue);
|
|
1478
|
+
},
|
|
1479
|
+
});
|
|
1480
|
+
registerProxy(proxy, ep);
|
|
1481
|
+
return proxy;
|
|
1482
|
+
}
|
|
1483
|
+
function myFlat(arr) {
|
|
1484
|
+
return Array.prototype.concat.apply([], arr);
|
|
1485
|
+
}
|
|
1486
|
+
function processArguments(argumentList) {
|
|
1487
|
+
const processed = argumentList.map(toWireValue);
|
|
1488
|
+
return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];
|
|
1489
|
+
}
|
|
1490
|
+
const transferCache = new WeakMap();
|
|
1491
|
+
function transfer(obj, transfers) {
|
|
1492
|
+
transferCache.set(obj, transfers);
|
|
1493
|
+
return obj;
|
|
1494
|
+
}
|
|
1495
|
+
function proxy(obj) {
|
|
1496
|
+
return Object.assign(obj, { [proxyMarker]: true });
|
|
1497
|
+
}
|
|
1498
|
+
function toWireValue(value) {
|
|
1499
|
+
for (const [name, handler] of transferHandlers) {
|
|
1500
|
+
if (handler.canHandle(value)) {
|
|
1501
|
+
const [serializedValue, transferables] = handler.serialize(value);
|
|
1502
|
+
return [
|
|
1503
|
+
{
|
|
1504
|
+
type: "HANDLER" /* WireValueType.HANDLER */,
|
|
1505
|
+
name,
|
|
1506
|
+
value: serializedValue,
|
|
1507
|
+
},
|
|
1508
|
+
transferables,
|
|
1509
|
+
];
|
|
1507
1510
|
}
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1511
|
+
}
|
|
1512
|
+
return [
|
|
1513
|
+
{
|
|
1514
|
+
type: "RAW" /* WireValueType.RAW */,
|
|
1515
|
+
value,
|
|
1516
|
+
},
|
|
1517
|
+
transferCache.get(value) || [],
|
|
1518
|
+
];
|
|
1513
1519
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1520
|
+
function fromWireValue(value) {
|
|
1521
|
+
switch (value.type) {
|
|
1522
|
+
case "HANDLER" /* WireValueType.HANDLER */:
|
|
1523
|
+
return transferHandlers.get(value.name).deserialize(value.value);
|
|
1524
|
+
case "RAW" /* WireValueType.RAW */:
|
|
1525
|
+
return value.value;
|
|
1526
|
+
}
|
|
1518
1527
|
}
|
|
1519
|
-
function
|
|
1520
|
-
|
|
1521
|
-
|
|
1528
|
+
function requestResponseMessage(ep, pendingListeners, msg, transfers) {
|
|
1529
|
+
return new Promise((resolve) => {
|
|
1530
|
+
const id = generateUUID();
|
|
1531
|
+
pendingListeners.set(id, resolve);
|
|
1532
|
+
if (ep.start) {
|
|
1533
|
+
ep.start();
|
|
1534
|
+
}
|
|
1535
|
+
ep.postMessage(Object.assign({ id }, msg), transfers);
|
|
1536
|
+
});
|
|
1522
1537
|
}
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
return [size, size, size];
|
|
1529
|
-
else if (Array.isArray(size) && size.length === 0)
|
|
1530
|
-
return [0, 0, 0];
|
|
1531
|
-
const [x, y = x, z = x] = size;
|
|
1532
|
-
return [x, y, z];
|
|
1538
|
+
function generateUUID() {
|
|
1539
|
+
return new Array(4)
|
|
1540
|
+
.fill(0)
|
|
1541
|
+
.map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))
|
|
1542
|
+
.join("-");
|
|
1533
1543
|
}
|
|
1534
1544
|
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1545
|
+
class Supervisor {
|
|
1546
|
+
constructor() {
|
|
1547
|
+
this.worker = null;
|
|
1548
|
+
this.workerApi = null;
|
|
1549
|
+
}
|
|
1550
|
+
/**
|
|
1551
|
+
* Execute layout in worker
|
|
1552
|
+
*/
|
|
1553
|
+
execute(layoutId, data, options) {
|
|
1554
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1555
|
+
if (!this.worker) {
|
|
1556
|
+
yield this.initWorker();
|
|
1557
|
+
}
|
|
1558
|
+
if (!this.workerApi) {
|
|
1559
|
+
throw new Error('Worker API not initialized');
|
|
1560
|
+
}
|
|
1561
|
+
return yield this.workerApi.execute(layoutId, data, options);
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1564
|
+
/**
|
|
1565
|
+
* Destroy worker
|
|
1566
|
+
*/
|
|
1567
|
+
destroy() {
|
|
1568
|
+
if (this.workerApi) {
|
|
1569
|
+
this.workerApi.destroy();
|
|
1570
|
+
}
|
|
1571
|
+
if (this.worker) {
|
|
1572
|
+
this.worker.terminate();
|
|
1573
|
+
this.worker = null;
|
|
1574
|
+
this.workerApi = null;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
/**
|
|
1578
|
+
* Initialize worker
|
|
1579
|
+
*/
|
|
1580
|
+
initWorker() {
|
|
1581
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1582
|
+
const workerPath = this.resolveWorkerPath();
|
|
1583
|
+
const isESM = workerPath.includes('/lib/') || workerPath.endsWith('.mjs');
|
|
1584
|
+
const type = isESM ? 'module' : 'classic';
|
|
1585
|
+
this.worker = new Worker(workerPath, { type });
|
|
1586
|
+
this.workerApi = wrap(this.worker);
|
|
1587
|
+
});
|
|
1588
|
+
}
|
|
1589
|
+
/**
|
|
1590
|
+
* Resolve worker script path which works in both ESM and UMD environments
|
|
1591
|
+
*/
|
|
1592
|
+
resolveWorkerPath() {
|
|
1593
|
+
if (typeof ({ url: (typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)) }) !== 'undefined' && (typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href))) {
|
|
1594
|
+
const currentUrl = new URL((typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)));
|
|
1595
|
+
// e.g. `.../lib/runtime/supervisor.js` -> `.../lib/worker.js`
|
|
1596
|
+
const asRoot = currentUrl.href.replace(/\/runtime\/[^/]+\.js$/, '/worker.js');
|
|
1597
|
+
if (asRoot !== currentUrl.href)
|
|
1598
|
+
return asRoot;
|
|
1599
|
+
// Fallback: keep legacy behavior (same directory)
|
|
1600
|
+
return currentUrl.href.replace(/\/[^/]+\.js$/, '/worker.js');
|
|
1601
|
+
}
|
|
1602
|
+
if (typeof document !== 'undefined') {
|
|
1603
|
+
const scripts = document.getElementsByTagName('script');
|
|
1604
|
+
for (let i = scripts.length - 1; i >= 0; i--) {
|
|
1605
|
+
const src = scripts[i].src;
|
|
1606
|
+
if (src && (src.includes('index.js') || src.includes('index.min.js'))) {
|
|
1607
|
+
return src.replace(/index(\.min)?\.js/, 'worker.js');
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
return './worker.js';
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1549
1614
|
|
|
1550
1615
|
/**
|
|
1551
1616
|
* <zh/> 布局基类
|
|
@@ -1555,14 +1620,17 @@
|
|
|
1555
1620
|
class BaseLayout {
|
|
1556
1621
|
constructor(options) {
|
|
1557
1622
|
this.supervisor = null;
|
|
1558
|
-
this.initialOptions = mergeOptions(this.getDefaultOptions(), options);
|
|
1623
|
+
this.initialOptions = this.mergeOptions(this.getDefaultOptions(), options);
|
|
1559
1624
|
}
|
|
1560
1625
|
get options() {
|
|
1561
1626
|
return this.runtimeOptions || this.initialOptions;
|
|
1562
1627
|
}
|
|
1628
|
+
mergeOptions(base, patch) {
|
|
1629
|
+
return Object.assign({}, base, patch || {});
|
|
1630
|
+
}
|
|
1563
1631
|
execute(data, userOptions) {
|
|
1564
1632
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1565
|
-
this.runtimeOptions = mergeOptions(this.initialOptions, userOptions);
|
|
1633
|
+
this.runtimeOptions = this.mergeOptions(this.initialOptions, userOptions);
|
|
1566
1634
|
const { node, edge, enableWorker } = this.runtimeOptions;
|
|
1567
1635
|
this.context = new RuntimeContext(data, { node, edge });
|
|
1568
1636
|
this.model = this.context.graph;
|
|
@@ -1627,71 +1695,6 @@
|
|
|
1627
1695
|
return !!layout.tick && !!layout.stop;
|
|
1628
1696
|
}
|
|
1629
1697
|
|
|
1630
|
-
/**
|
|
1631
|
-
* Format value with multiple types into a function that returns a number
|
|
1632
|
-
* @param value The value to be formatted
|
|
1633
|
-
* @param defaultValue The default value when value is invalid
|
|
1634
|
-
* @returns A function that returns a number
|
|
1635
|
-
*/
|
|
1636
|
-
function formatNumberFn(value, defaultValue) {
|
|
1637
|
-
// If value is a function, return it directly
|
|
1638
|
-
if (isFunction(value)) {
|
|
1639
|
-
return value;
|
|
1640
|
-
}
|
|
1641
|
-
// If value is a number, return a function that returns this number
|
|
1642
|
-
if (isNumber(value)) {
|
|
1643
|
-
return () => value;
|
|
1644
|
-
}
|
|
1645
|
-
// For other cases (undefined or invalid values), return default value function
|
|
1646
|
-
return () => defaultValue;
|
|
1647
|
-
}
|
|
1648
|
-
/**
|
|
1649
|
-
* Format size config with multiple types into a function that returns a size
|
|
1650
|
-
* @param value The value to be formatted
|
|
1651
|
-
* @param defaultValue The default value when value is invalid
|
|
1652
|
-
* @param resultIsNumber Whether to return a number (max of width/height) or size array
|
|
1653
|
-
* @returns A function that returns a size
|
|
1654
|
-
*/
|
|
1655
|
-
function formatSizeFn(value, defaultValue = 10) {
|
|
1656
|
-
// If value is undefined, return default value function
|
|
1657
|
-
if (!value) {
|
|
1658
|
-
return () => defaultValue;
|
|
1659
|
-
}
|
|
1660
|
-
// If value is a function, return it directly
|
|
1661
|
-
if (isFunction(value)) {
|
|
1662
|
-
return value;
|
|
1663
|
-
}
|
|
1664
|
-
// If value is a number, return a function that returns this number
|
|
1665
|
-
if (isNumber(value)) {
|
|
1666
|
-
return () => value;
|
|
1667
|
-
}
|
|
1668
|
-
// If value is an array, return max or the array itself
|
|
1669
|
-
if (Array.isArray(value)) {
|
|
1670
|
-
return () => value;
|
|
1671
|
-
}
|
|
1672
|
-
// If value is an object with width and height
|
|
1673
|
-
if (isObject$1(value) && value.width && value.height) {
|
|
1674
|
-
return () => [value.width, value.height];
|
|
1675
|
-
}
|
|
1676
|
-
return () => defaultValue;
|
|
1677
|
-
}
|
|
1678
|
-
/**
|
|
1679
|
-
* Format nodeSize and nodeSpacing into a function that returns the total size
|
|
1680
|
-
* @param nodeSize The size of the node
|
|
1681
|
-
* @param nodeSpacing The spacing around the node
|
|
1682
|
-
* @param defaultNodeSize The default node size when value is invalid
|
|
1683
|
-
* @returns A function that returns the total size (node size + spacing)
|
|
1684
|
-
*/
|
|
1685
|
-
const formatNodeSizeFn = (nodeSize, nodeSpacing, defaultNodeSize = 10) => {
|
|
1686
|
-
const nodeSpacingFunc = formatNumberFn(nodeSpacing, 0);
|
|
1687
|
-
const nodeSizeFunc = formatSizeFn(nodeSize, defaultNodeSize);
|
|
1688
|
-
return (node) => {
|
|
1689
|
-
const size = nodeSizeFunc(node);
|
|
1690
|
-
const spacing = nodeSpacingFunc(node);
|
|
1691
|
-
return Math.max(...parseSize(size)) + spacing;
|
|
1692
|
-
};
|
|
1693
|
-
};
|
|
1694
|
-
|
|
1695
1698
|
/**
|
|
1696
1699
|
* <zh/> 内部图数据结构,用于 antv-dagre 布局算法
|
|
1697
1700
|
*
|
|
@@ -5131,9 +5134,9 @@
|
|
|
5131
5134
|
return __awaiter(this, void 0, void 0, function* () {
|
|
5132
5135
|
const { nodeSize, align, rankdir = 'TB', ranksep, nodesep, edgeLabelSpace, ranker = 'tight-tree', nodeOrder, begin, controlPoints, radial, sortByCombo,
|
|
5133
5136
|
// focusNode,
|
|
5134
|
-
preset, } = options;
|
|
5135
|
-
const ranksepfunc = formatNumberFn(
|
|
5136
|
-
const nodesepfunc = formatNumberFn(
|
|
5137
|
+
preset, ranksepFunc, nodesepFunc, } = options;
|
|
5138
|
+
const ranksepfunc = formatNumberFn(ranksepFunc, ranksep !== null && ranksep !== void 0 ? ranksep : 50);
|
|
5139
|
+
const nodesepfunc = formatNumberFn(nodesepFunc, nodesep !== null && nodesep !== void 0 ? nodesep : 50);
|
|
5137
5140
|
let horisep = nodesepfunc;
|
|
5138
5141
|
let vertisep = ranksepfunc;
|
|
5139
5142
|
if (rankdir === 'LR' || rankdir === 'RL') {
|
|
@@ -5148,9 +5151,10 @@
|
|
|
5148
5151
|
const edges = this.model.edges();
|
|
5149
5152
|
nodes.forEach((node) => {
|
|
5150
5153
|
var _a;
|
|
5151
|
-
const
|
|
5152
|
-
const
|
|
5153
|
-
const
|
|
5154
|
+
const raw = node._original;
|
|
5155
|
+
const size = parseSize(nodeSizeFunc(raw));
|
|
5156
|
+
const verti = vertisep(raw);
|
|
5157
|
+
const hori = horisep(raw);
|
|
5154
5158
|
const width = size[0] + 2 * hori;
|
|
5155
5159
|
const height = size[1] + 2 * verti;
|
|
5156
5160
|
const layer = (_a = node.data) === null || _a === void 0 ? void 0 : _a.layer;
|
|
@@ -5216,6 +5220,7 @@
|
|
|
5216
5220
|
acyclicer: 'greedy',
|
|
5217
5221
|
ranker,
|
|
5218
5222
|
rankdir,
|
|
5223
|
+
nodesep,
|
|
5219
5224
|
align,
|
|
5220
5225
|
});
|
|
5221
5226
|
const layoutTopLeft = [0, 0];
|
|
@@ -5474,7 +5479,7 @@
|
|
|
5474
5479
|
}
|
|
5475
5480
|
else if (ordering === 'degree') {
|
|
5476
5481
|
// layout according to the descent order of degrees
|
|
5477
|
-
orderByDegree(this.model);
|
|
5482
|
+
orderByDegree(this.model, 'asc');
|
|
5478
5483
|
}
|
|
5479
5484
|
let { radius, startRadius, endRadius } = this.options;
|
|
5480
5485
|
const nodes = this.model.nodes();
|
|
@@ -7320,25 +7325,17 @@
|
|
|
7320
7325
|
}
|
|
7321
7326
|
|
|
7322
7327
|
const DEFAULTS_LAYOUT_OPTIONS$6 = {
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
+
link: {
|
|
7329
|
+
id: (d) => String(d.id),
|
|
7330
|
+
},
|
|
7331
|
+
manyBody: {
|
|
7332
|
+
strength: -30,
|
|
7333
|
+
},
|
|
7328
7334
|
preventOverlap: false,
|
|
7329
7335
|
nodeSize: 10,
|
|
7330
7336
|
nodeSpacing: 0,
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
nodeStrength: -30,
|
|
7334
|
-
distanceMin: undefined,
|
|
7335
|
-
distanceMax: undefined,
|
|
7336
|
-
theta: undefined,
|
|
7337
|
-
alpha: 1,
|
|
7338
|
-
alphaMin: 0.001,
|
|
7339
|
-
alphaDecay: 1 - Math.pow(0.001, 1 / 300),
|
|
7340
|
-
alphaTarget: 0,
|
|
7341
|
-
velocityDecay: 0.4,
|
|
7337
|
+
x: false,
|
|
7338
|
+
y: false,
|
|
7342
7339
|
clustering: false,
|
|
7343
7340
|
clusterNodeStrength: -1,
|
|
7344
7341
|
clusterEdgeStrength: 0.1,
|
|
@@ -7453,14 +7450,7 @@
|
|
|
7453
7450
|
});
|
|
7454
7451
|
}
|
|
7455
7452
|
parseOptions(options) {
|
|
7456
|
-
var _a, _b;
|
|
7457
7453
|
const _ = options;
|
|
7458
|
-
// process nodeSize
|
|
7459
|
-
if (_.collide && ((_a = _.collide) === null || _a === void 0 ? void 0 : _a.radius) === undefined) {
|
|
7460
|
-
_.collide = _.collide || {};
|
|
7461
|
-
// @ts-ignore
|
|
7462
|
-
_.collide.radius = (_b = _.nodeSize) !== null && _b !== void 0 ? _b : 10;
|
|
7463
|
-
}
|
|
7464
7454
|
// process iterations
|
|
7465
7455
|
if (_.iterations === undefined) {
|
|
7466
7456
|
if (_.link && _.link.iterations === undefined) {
|
|
@@ -7555,20 +7545,17 @@
|
|
|
7555
7545
|
this.setupClusterForce(simulation, options);
|
|
7556
7546
|
}
|
|
7557
7547
|
getCenterOptions(options) {
|
|
7558
|
-
if (
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
});
|
|
7570
|
-
}
|
|
7571
|
-
return undefined;
|
|
7548
|
+
if (options.center === false)
|
|
7549
|
+
return undefined;
|
|
7550
|
+
const viewport = normalizeViewport({
|
|
7551
|
+
width: options.width,
|
|
7552
|
+
height: options.height,
|
|
7553
|
+
});
|
|
7554
|
+
return assignDefined({}, options.center || {}, {
|
|
7555
|
+
x: viewport.width / 2,
|
|
7556
|
+
y: viewport.height / 2,
|
|
7557
|
+
strength: options.centerStrength,
|
|
7558
|
+
});
|
|
7572
7559
|
}
|
|
7573
7560
|
setupCenterForce(simulation, options) {
|
|
7574
7561
|
const center = this.getCenterOptions(options);
|
|
@@ -7592,19 +7579,14 @@
|
|
|
7592
7579
|
}
|
|
7593
7580
|
}
|
|
7594
7581
|
getManyBodyOptions(options) {
|
|
7595
|
-
if (options.manyBody
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
options.
|
|
7599
|
-
options.
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
distanceMax: options.distanceMax,
|
|
7604
|
-
theta: options.theta,
|
|
7605
|
-
});
|
|
7606
|
-
}
|
|
7607
|
-
return undefined;
|
|
7582
|
+
if (options.manyBody === false)
|
|
7583
|
+
return undefined;
|
|
7584
|
+
return assignDefined({}, options.manyBody || {}, {
|
|
7585
|
+
strength: options.nodeStrength,
|
|
7586
|
+
distanceMin: options.distanceMin,
|
|
7587
|
+
distanceMax: options.distanceMax,
|
|
7588
|
+
theta: options.theta,
|
|
7589
|
+
});
|
|
7608
7590
|
}
|
|
7609
7591
|
setupManyBodyForce(simulation, options) {
|
|
7610
7592
|
const manyBody = this.getManyBodyOptions(options);
|
|
@@ -7630,19 +7612,14 @@
|
|
|
7630
7612
|
}
|
|
7631
7613
|
}
|
|
7632
7614
|
getLinkOptions(options) {
|
|
7633
|
-
if (options.link
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
options.
|
|
7637
|
-
options.
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
strength: options.edgeStrength,
|
|
7642
|
-
iterations: options.edgeIterations,
|
|
7643
|
-
});
|
|
7644
|
-
}
|
|
7645
|
-
return undefined;
|
|
7615
|
+
if (options.link === false)
|
|
7616
|
+
return undefined;
|
|
7617
|
+
return assignDefined({}, options.link || {}, {
|
|
7618
|
+
id: options.edgeId,
|
|
7619
|
+
distance: options.linkDistance,
|
|
7620
|
+
strength: options.edgeStrength,
|
|
7621
|
+
iterations: options.edgeIterations,
|
|
7622
|
+
});
|
|
7646
7623
|
}
|
|
7647
7624
|
setupLinkForce(simulation, options) {
|
|
7648
7625
|
const edges = this.model.edges();
|
|
@@ -7669,23 +7646,17 @@
|
|
|
7669
7646
|
}
|
|
7670
7647
|
}
|
|
7671
7648
|
getCollisionOptions(options) {
|
|
7672
|
-
if (
|
|
7649
|
+
if (options.preventOverlap === false &&
|
|
7650
|
+
(options.collide === false || options.collide === undefined))
|
|
7673
7651
|
return undefined;
|
|
7674
|
-
|
|
7675
|
-
options.nodeSize
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
options.
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
return assignDefined({}, options.collide || {}, {
|
|
7683
|
-
radius,
|
|
7684
|
-
strength: options.collideStrength,
|
|
7685
|
-
iterations: options.collideIterations,
|
|
7686
|
-
});
|
|
7687
|
-
}
|
|
7688
|
-
return undefined;
|
|
7652
|
+
const radius = options.nodeSize || options.nodeSpacing
|
|
7653
|
+
? (d) => formatNodeSizeFn(options.nodeSize, options.nodeSpacing)(d._original) / 2
|
|
7654
|
+
: undefined;
|
|
7655
|
+
return assignDefined({}, options.collide || {}, {
|
|
7656
|
+
radius: (options.collide && options.collide.radius) || radius,
|
|
7657
|
+
strength: options.collideStrength,
|
|
7658
|
+
iterations: options.collideIterations,
|
|
7659
|
+
});
|
|
7689
7660
|
}
|
|
7690
7661
|
setupCollisionForce(simulation, options) {
|
|
7691
7662
|
const collide = this.getCollisionOptions(options);
|
|
@@ -7710,18 +7681,13 @@
|
|
|
7710
7681
|
}
|
|
7711
7682
|
getXForceOptions(options) {
|
|
7712
7683
|
var _a;
|
|
7713
|
-
if (options.x
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
options.
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
x: (_a = options.forceXPosition) !== null && _a !== void 0 ? _a : (center && center.x),
|
|
7721
|
-
strength: options.forceXStrength,
|
|
7722
|
-
});
|
|
7723
|
-
}
|
|
7724
|
-
return undefined;
|
|
7684
|
+
if (options.x === false)
|
|
7685
|
+
return undefined;
|
|
7686
|
+
const center = this.getCenterOptions(options);
|
|
7687
|
+
return assignDefined({}, options.x || {}, {
|
|
7688
|
+
x: (_a = options.forceXPosition) !== null && _a !== void 0 ? _a : (center && center.x),
|
|
7689
|
+
strength: options.forceXStrength,
|
|
7690
|
+
});
|
|
7725
7691
|
}
|
|
7726
7692
|
setupXForce(simulation, options) {
|
|
7727
7693
|
const x = this.getXForceOptions(options);
|
|
@@ -7744,18 +7710,13 @@
|
|
|
7744
7710
|
}
|
|
7745
7711
|
getYForceOptions(options) {
|
|
7746
7712
|
var _a;
|
|
7747
|
-
if (options.y
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
options.
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
y: (_a = options.forceYPosition) !== null && _a !== void 0 ? _a : (center && center.y),
|
|
7755
|
-
strength: options.forceYStrength,
|
|
7756
|
-
});
|
|
7757
|
-
}
|
|
7758
|
-
return undefined;
|
|
7713
|
+
if (options.y === false)
|
|
7714
|
+
return undefined;
|
|
7715
|
+
const center = this.getCenterOptions(options);
|
|
7716
|
+
return assignDefined({}, options.y || {}, {
|
|
7717
|
+
y: (_a = options.forceYPosition) !== null && _a !== void 0 ? _a : (center && center.y),
|
|
7718
|
+
strength: options.forceYStrength,
|
|
7719
|
+
});
|
|
7759
7720
|
}
|
|
7760
7721
|
setupYForce(simulation, options) {
|
|
7761
7722
|
const y = this.getYForceOptions(options);
|
|
@@ -32479,9 +32440,9 @@ ${indent}columns: ${matrix.columns}
|
|
|
32479
32440
|
? { type: 'force', preventOverlap: true }
|
|
32480
32441
|
: { type: 'concentric', preventOverlap: true },
|
|
32481
32442
|
nodeSize: 20,
|
|
32482
|
-
nodeSpacing:
|
|
32483
|
-
comboPadding:
|
|
32484
|
-
comboSpacing:
|
|
32443
|
+
nodeSpacing: 0,
|
|
32444
|
+
comboPadding: 10,
|
|
32445
|
+
comboSpacing: 0,
|
|
32485
32446
|
};
|
|
32486
32447
|
const ROOT_ID = 'root';
|
|
32487
32448
|
/**
|
|
@@ -32799,7 +32760,6 @@ ${indent}columns: ${matrix.columns}
|
|
|
32799
32760
|
exports.isArray = isArray;
|
|
32800
32761
|
exports.isLayoutWithIterations = isLayoutWithIterations;
|
|
32801
32762
|
exports.johnson = johnson;
|
|
32802
|
-
exports.mergeOptions = mergeOptions;
|
|
32803
32763
|
exports.normalizeViewport = normalizeViewport;
|
|
32804
32764
|
exports.orderByDegree = orderByDegree;
|
|
32805
32765
|
exports.orderById = orderById;
|