【问题标题】:How to forbid cyclic edge connections between vertexes on mxgraph (acyclic graph)如何在mxgraph(非循环图)上禁止顶点之间的循环边连接
【发布时间】:2023-03-27 08:37:02
【问题描述】:

我使用mxGraph 创建了一个自定义编辑器。在我的编辑器中,用户应该能够创建一个acyclic graph。当用户will try to make a cycle in the graph 时,应出现一个弹出窗口,通知用户图形中的cycles are not permitted 并应进行回滚。

mxGraph 对象具有属性multigraph (boolean),它指定图形是否应允许同一对顶点之间存在多个连接,并且与我想要的上述行为类似。

我在 mxGraph 对象的代码中搜索了任何类似的属性,声明该图应该是非循环的,但到目前为止还没有找到任何东西。我也许可以实现我自己的自定义逻辑来使图形无环,但我应该每次连接一对顶点时遍历目标顶点的所属树以检查是否会创建一个循环,这将非常昂贵/耗时,因为该图可能包含数千个顶点和边,因此我正在寻找一种简单的方法/开箱即用的方法(如果存在)来实现它。

示例 - 无环图(OK)

示例 - 循环图(不正常 - 不应允许)

任何帮助将不胜感激,在此先感谢。

【问题讨论】:

    标签: javascript graph directed-acyclic-graphs mxgraph


    【解决方案1】:

    我们遇到了同样的问题并尝试解决,但这可能不是最好的解决方案。我们的解决方案如下:

    1. 我们使用了DFS算法:https://en.wikipedia.org/wiki/Depth-first_search
    2. 我们没有验证整个 DAG 图,而是将验证函数绑定到 mxCell 连接事件。这提高了效率,还允许用户获得实时响应。

    以下是示例代码:

    // validation function.Need to set id for each cell.
    this.graph.connectionHandler.validateConnection = (source, target) => {
        const childrenNodes = [];
        this.deepGetChildren(target, childrenNodes)
        //check the children ids 
        if (childrenNodes.indexOf(source.id) > -1) {
            return false;
        }
        return true;
    }
    /**
    * Recursive function
    * get all child nodes of cell by cell
    */
    deepGetChildren(cell, ids) {
        //if the cell is the end node, or the cell have no edge,just put
        if (cell.type === 'end' || cell.edges === undefined) {
            if (ids.indexOf(cell.id) === -1) {
                ids.push(cell.id)
            }
        } else {
            if (cell.edges !== null && cell.edges.length > 0) {
                for (const item of cell.edges) {
                    //Only need to calculate the output connection
                    if (item.target !== null&&item.target.id !== cell.id&&ids.indexOf(item.target.id) === -1) {
                           this.deepGetChildrens(item.target, ids)
                    }
            } else {
                if (ids.indexOf(item.target.id) === -1) {
                    ids.push(item.target.id)
                }
            }
        }
    }
    

    【讨论】:

    • 您好,感谢您的回复,正如我们在通过后端解决方案进行管理之前已经讨论过的那样,但将来我可能会使用您的自定义,以防我需要额外的层检查,所以 +1现在,当我尝试或社区中的其他任何人发现它有帮助时,我会接受答案:)
    • 谢谢,希望对其他人有所帮助。 :)
    猜你喜欢
    • 2012-05-20
    • 2015-02-07
    • 2020-05-08
    • 1970-01-01
    • 2014-03-16
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    相关资源
    最近更新 更多