UNPKG

4.53 kBJavaScriptView Raw
1"use strict";
2/**
3 * @fileOverview MDS layout
4 * @author shiwu.wyy@antfin.com
5 */
6var __extends = (this && this.__extends) || (function () {
7 var extendStatics = function (d, b) {
8 extendStatics = Object.setPrototypeOf ||
9 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
10 function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
11 return extendStatics(d, b);
12 };
13 return function (d, b) {
14 extendStatics(d, b);
15 function __() { this.constructor = d; }
16 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
17 };
18})();
19Object.defineProperty(exports, "__esModule", { value: true });
20exports.MDSLayout = void 0;
21var ml_matrix_1 = require("ml-matrix");
22var util_1 = require("../util");
23var base_1 = require("./base");
24/**
25 * mds 布局
26 */
27var MDSLayout = /** @class */ (function (_super) {
28 __extends(MDSLayout, _super);
29 function MDSLayout(options) {
30 var _this = _super.call(this) || this;
31 /** 布局中心 */
32 _this.center = [0, 0];
33 /** 边长度 */
34 _this.linkDistance = 50;
35 _this.nodes = [];
36 _this.edges = [];
37 _this.updateCfg(options);
38 return _this;
39 }
40 MDSLayout.prototype.getDefaultCfg = function () {
41 return {
42 center: [0, 0],
43 linkDistance: 50,
44 };
45 };
46 /**
47 * 执行布局
48 */
49 MDSLayout.prototype.execute = function () {
50 var self = this;
51 var nodes = self.nodes, _a = self.edges, edges = _a === void 0 ? [] : _a;
52 var center = self.center;
53 if (!nodes || nodes.length === 0) {
54 return;
55 }
56 if (nodes.length === 1) {
57 nodes[0].x = center[0];
58 nodes[0].y = center[1];
59 return;
60 }
61 var linkDistance = self.linkDistance;
62 // the graph-theoretic distance (shortest path distance) matrix
63 var adjMatrix = util_1.getAdjMatrix({ nodes: nodes, edges: edges }, false);
64 var distances = util_1.floydWarshall(adjMatrix);
65 self.handleInfinity(distances);
66 // scale the ideal edge length acoording to linkDistance
67 var scaledD = util_1.scaleMatrix(distances, linkDistance);
68 self.scaledDistances = scaledD;
69 // get positions by MDS
70 var positions = self.runMDS();
71 self.positions = positions;
72 positions.forEach(function (p, i) {
73 nodes[i].x = p[0] + center[0];
74 nodes[i].y = p[1] + center[1];
75 });
76 return {
77 nodes: nodes,
78 edges: edges,
79 };
80 };
81 /**
82 * mds 算法
83 * @return {array} positions 计算后的节点位置数组
84 */
85 MDSLayout.prototype.runMDS = function () {
86 var self = this;
87 var dimension = 2;
88 var distances = self.scaledDistances;
89 // square distances
90 var M = ml_matrix_1.Matrix.mul(ml_matrix_1.Matrix.pow(distances, 2), -0.5);
91 // double centre the rows/columns
92 var rowMeans = M.mean('row');
93 var colMeans = M.mean('column');
94 var totalMean = M.mean();
95 M.add(totalMean).subRowVector(rowMeans).subColumnVector(colMeans);
96 // take the SVD of the double centred matrix, and return the
97 // points from it
98 var ret = new ml_matrix_1.SingularValueDecomposition(M);
99 var eigenValues = ml_matrix_1.Matrix.sqrt(ret.diagonalMatrix).diagonal();
100 return ret.leftSingularVectors.toJSON().map(function (row) {
101 return ml_matrix_1.Matrix.mul([row], [eigenValues]).toJSON()[0].splice(0, dimension);
102 });
103 };
104 MDSLayout.prototype.handleInfinity = function (distances) {
105 var maxDistance = -999999;
106 distances.forEach(function (row) {
107 row.forEach(function (value) {
108 if (value === Infinity) {
109 return;
110 }
111 if (maxDistance < value) {
112 maxDistance = value;
113 }
114 });
115 });
116 distances.forEach(function (row, i) {
117 row.forEach(function (value, j) {
118 if (value === Infinity) {
119 distances[i][j] = maxDistance;
120 }
121 });
122 });
123 };
124 MDSLayout.prototype.getType = function () {
125 return 'mds';
126 };
127 return MDSLayout;
128}(base_1.Base));
129exports.MDSLayout = MDSLayout;
130//# sourceMappingURL=mds.js.map
\No newline at end of file