@antv/g2plot
Version: 
An interactive and responsive charting library
93 lines • 3.17 kB
JavaScript
import { isArray } from '@antv/util';
/**
 * 根据 edges 获取对应的 node 结构
 */
export function getNodes(edges, sourceField, targetField) {
    var nodes = [];
    edges.forEach(function (e) {
        var source = e[sourceField];
        var target = e[targetField];
        if (!nodes.includes(source)) {
            nodes.push(source);
        }
        if (!nodes.includes(target)) {
            nodes.push(target);
        }
    });
    return nodes;
}
/**
 * 根据 edges 获取对应的 dfs 邻接矩阵
 */
export function getMatrix(edges, nodes, sourceField, targetField) {
    var graphMatrix = {};
    nodes.forEach(function (pre) {
        graphMatrix[pre] = {};
        nodes.forEach(function (next) {
            graphMatrix[pre][next] = 0;
        });
    });
    edges.forEach(function (edge) {
        graphMatrix[edge[sourceField]][edge[targetField]] = 1;
    });
    return graphMatrix;
}
/**
 * 使用 DFS 思路切断桑基图数据中的环(会丢失数据),保证顺序
 * @param data
 * @param sourceField
 * @param targetField
 */
export function cutoffCircle(edges, sourceField, targetField) {
    if (!isArray(edges))
        return [];
    // 待删除的环状结构
    var removedData = [];
    // 获取所有的节点
    var nodes = getNodes(edges, sourceField, targetField);
    // 获取节点与边的邻接矩阵
    var graphMatrix = getMatrix(edges, nodes, sourceField, targetField);
    // visited:标记节点访问状态, 0:未访问,1:访问中, -1:已访问
    var visited = {};
    // 初始化visited
    nodes.forEach(function (node) {
        visited[node] = 0;
    });
    // 图的深度遍历函数
    function DFS(dfsNode) {
        // 节点状态置为正在访问
        visited[dfsNode] = 1;
        nodes.forEach(function (node) {
            if (graphMatrix[dfsNode][node] != 0) {
                // 当前节点在访问中,再次被访问,证明有环,移动到 removeData
                if (visited[node] == 1) {
                    // 拼接为字符串,方便最后过滤
                    removedData.push(dfsNode + "_" + node);
                }
                else if (visited[node] == -1) {
                    // 当前结点及后边的结点都被访问过,直接跳至下一个结点
                    return;
                }
                else {
                    DFS(node); // 否则递归访问
                }
            }
        });
        //遍历过所有相连的结点后,把本节点标记为-1
        visited[dfsNode] = -1;
    }
    // 对每个节点执行 dfs 操作
    nodes.forEach(function (node) {
        //该结点后边的结点都被访问过了,跳过它
        if (visited[node] == -1) {
            return;
        }
        DFS(node);
    });
    if (removedData.length !== 0) {
        console.warn("sankey data contains circle, " + removedData.length + " records removed.", removedData);
    }
    // 过滤 remove 路径
    return edges.filter(function (edge) { return removedData.findIndex(function (i) { return i === edge[sourceField] + "_" + edge[targetField]; }) < 0; });
}
//# sourceMappingURL=circle.js.map