代码之家  ›  专栏  ›  技术社区  ›  Alexis Wilke

是否有自动删除点图中“多余”边的选项?

  •  0
  • Alexis Wilke  · 技术社区  · 5 年前

    我为我的debian项目创建了一个依赖关系点图(见图)。依赖项包括冗余边。我想要一个没有多余边的简单图。我可以自己计算,但这并不容易,因为我在cmakelists.txt和.cmake扩展名中生成了.dot文件。

    所以我想知道在dot或graphviz中是否有删除不需要的边的选项。例如,上面的 snapwebsites 项目取决于 csspp advgetopt . 自从 cspp 包已依赖于 建议选择 ,不需要在 快照网站 建议选择 .

    在有向图中,这意味着:

    "snapwebsites" -> "advgetopt";     <-- "auto-remove" this one
    "snapwebsites" -> "csspp";
    
    "csspp" -> "advgetopt";
    

    那么,有这样的选择吗?

    enter image description here

    0 回复  |  直到 5 年前
        1
  •  2
  •   marapet    5 年前

    据我所知,没有这种内置的选项(我可能错了)。

    最简单的方法通常是只在graphviz脚本中包含最初需要的边。如果这不可能,您可以使用 gvpr (Graphviz模式扫描和处理语言)在输出到布局的点之前。

    当然,这意味着您必须使用gvpr实现对不需要的边的检测和抑制,然后可以在需要时重用该脚本。

        2
  •  0
  •   Alexis Wilke    5 年前

    基于@marapet的回答,我创建了一个脚本,我想也许其他人会从中受益。也很快!C++作为 clean-dependencies.gvpr .

    # Run with:
    #
    #    /usr/bin/gvpr -o clean-dependencies.dot -f clean-dependencies.gvpr dependencies.dot
    #
    # Clean up the dependencies.svg from double dependencies
    # In other words if A depends on B and C, and B also depends on C, we
    # can remove the link between A amd C, it's not necessary in our file.
    
    BEG_G {
        edge_t direct_edges[int];
        node_t children[int];
    
        node_t n = fstnode($G);
        while(n != NULL) {
    
            // 1. extract the current node direct children
            //
            int direct_pos = 0;
            edge_t e = fstout_sg($G, n);
            while(e != NULL) {
                direct_edges[direct_pos] = e;
                children[direct_pos] = opp(e, n);
                direct_pos = direct_pos + 1;
                e = nxtout_sg($G, e);
            }
    
            // 2. find all of the grand children
            //    and see whether some are duplicates, if so delete the
            //    original (direct) edge
            //
            int child_pos = direct_pos;
            int c = 0;
            for(c = 0; c < child_pos; ++c) {
                e = fstout_sg($G, children[c]);
                while(e != NULL) {
                    node_t o = opp(e, children[c]);
                    int idx;
                    for(idx = 0; idx < direct_pos; ++idx) {
                        if(children[idx] == o) {
                            if(direct_edges[idx] != NULL) {
                                delete($G, direct_edges[idx]);
                                direct_edges[idx] = NULL;
                            }
                            break;
                        }
                    }
                    e = nxtout_sg($G, e);
                }
            }
    
            n = nxtnode_sg($G, n);
        }
    }
    
    END_G {
        $O = $G;
    }
    

    我想提的是:gvpr函数似乎不接受数组作为输入。此外,我第一次尝试使用递归方法,局部变量被进一步的调用破坏(即,在递归调用返回时,变量的值是来自子调用的值……所以变量是函数的“本地”变量,但仍然只有一个实例,没有堆栈!)

    希望以后的版本能解决这些问题。

    $ gvpr -V
    gvpr version 2.38.0 (20140413.2041)
    

    在cmake中修复我的图表已经比尝试同样的方法容易得多了。

    enter image description here

    推荐文章