Есть ли возможность автоматического удаления «лишних» ребер в точечной диаграмме? - PullRequest
0 голосов
/ 09 июля 2019

Я создаю точечный график зависимостей для моих проектов Debian (см. Рисунок).Зависимости включают избыточные ребра.Я хотел бы иметь более простой график без этих избыточных ребер.Я мог бы рассчитать их самостоятельно, но это не так просто, так как я генерирую файл .dot в моих расширениях CMakeLists.txt и .cmake.

Так что мне интересно, будет ли опция в точке илиГрафвиз для удаления ребер, которые не требуются.Так, например, верхний snapwebsites проект зависит от csspp и advgetopt.Поскольку пакет cspp уже зависит от advgetopt, нет необходимости в границе между snapwebsites и advgetopt.

В орграфе это будет означать:

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

"csspp" -> "advgetopt";

Итак, есть ли такая опция?

enter image description here

Ответы [ 2 ]

2 голосов
/ 09 июля 2019

Насколько я знаю, такой встроенной опции не существует (и я могу ошибаться ...).

Обычно самый простой способ - включить в скрипт graphviz только те ребра, которые нужны в первую очередь.,Если это невозможно, вы можете обработать свой график с помощью gvpr (язык сканирования и обработки графического шаблона) перед выводом его вывода в точку для макета.

Это, конечно, означает, что выпришлось бы реализовывать обнаружение и подавление ненужных ребер с помощью gvpr, сценария, который вы затем могли бы использовать повторно при необходимости.

0 голосов
/ 18 июля 2019

Основываясь на ответе @ marapet, я создал сценарий и подумал, что, возможно, другие получат пользу от его копии. Это также в Snap! C ++ as 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

...