circle.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.cutoffCircle = exports.getMatrix = exports.getNodes = void 0;
  4. var util_1 = require("@antv/util");
  5. /**
  6. * 根据 edges 获取对应的 node 结构
  7. */
  8. function getNodes(edges, sourceField, targetField) {
  9. var nodes = [];
  10. edges.forEach(function (e) {
  11. var source = e[sourceField];
  12. var target = e[targetField];
  13. if (!nodes.includes(source)) {
  14. nodes.push(source);
  15. }
  16. if (!nodes.includes(target)) {
  17. nodes.push(target);
  18. }
  19. });
  20. return nodes;
  21. }
  22. exports.getNodes = getNodes;
  23. /**
  24. * 根据 edges 获取对应的 dfs 邻接矩阵
  25. */
  26. function getMatrix(edges, nodes, sourceField, targetField) {
  27. var graphMatrix = {};
  28. nodes.forEach(function (pre) {
  29. graphMatrix[pre] = {};
  30. nodes.forEach(function (next) {
  31. graphMatrix[pre][next] = 0;
  32. });
  33. });
  34. edges.forEach(function (edge) {
  35. graphMatrix[edge[sourceField]][edge[targetField]] = 1;
  36. });
  37. return graphMatrix;
  38. }
  39. exports.getMatrix = getMatrix;
  40. /**
  41. * 使用 DFS 思路切断桑基图数据中的环(会丢失数据),保证顺序
  42. * @param data
  43. * @param sourceField
  44. * @param targetField
  45. */
  46. function cutoffCircle(edges, sourceField, targetField) {
  47. if (!(0, util_1.isArray)(edges))
  48. return [];
  49. // 待删除的环状结构
  50. var removedData = [];
  51. // 获取所有的节点
  52. var nodes = getNodes(edges, sourceField, targetField);
  53. // 获取节点与边的邻接矩阵
  54. var graphMatrix = getMatrix(edges, nodes, sourceField, targetField);
  55. // visited:标记节点访问状态, 0:未访问,1:访问中, -1:已访问
  56. var visited = {};
  57. // 初始化visited
  58. nodes.forEach(function (node) {
  59. visited[node] = 0;
  60. });
  61. // 图的深度遍历函数
  62. function DFS(dfsNode) {
  63. // 节点状态置为正在访问
  64. visited[dfsNode] = 1;
  65. nodes.forEach(function (node) {
  66. if (graphMatrix[dfsNode][node] != 0) {
  67. // 当前节点在访问中,再次被访问,证明有环,移动到 removeData
  68. if (visited[node] == 1) {
  69. // 拼接为字符串,方便最后过滤
  70. removedData.push("".concat(dfsNode, "_").concat(node));
  71. }
  72. else if (visited[node] == -1) {
  73. // 当前结点及后边的结点都被访问过,直接跳至下一个结点
  74. return;
  75. }
  76. else {
  77. DFS(node); // 否则递归访问
  78. }
  79. }
  80. });
  81. //遍历过所有相连的结点后,把本节点标记为-1
  82. visited[dfsNode] = -1;
  83. }
  84. // 对每个节点执行 dfs 操作
  85. nodes.forEach(function (node) {
  86. //该结点后边的结点都被访问过了,跳过它
  87. if (visited[node] == -1) {
  88. return;
  89. }
  90. DFS(node);
  91. });
  92. if (removedData.length !== 0) {
  93. console.warn("sankey data contains circle, ".concat(removedData.length, " records removed."), removedData);
  94. }
  95. // 过滤 remove 路径
  96. return edges.filter(function (edge) { return removedData.findIndex(function (i) { return i === "".concat(edge[sourceField], "_").concat(edge[targetField]); }) < 0; });
  97. }
  98. exports.cutoffCircle = cutoffCircle;
  99. //# sourceMappingURL=circle.js.map