簡體   English   中英

如何在 Graphviz/dot/neato 中創建命名邊“類型”?

[英]How can I create named edge "types" in Graphviz/dot/neato?

我需要用 graphviz/dot 繪制一個圖表,其中節點之間有共同的邊類型,我試圖找到一種方法來為每種類型的邊定義標簽,然后在圖表中多次使用該標簽。

例如,想象一下傳統的吊扇 FSM 示例,它最初處於關閉狀態,每次有人拉動電源線時,它都會根據風扇的速度更改為新狀態:

     Pull         Pull        Pull
OFF ------> HIGH ------> MED ------> LOW
 ^                                    |
 |                Pull                |
 +------------------------------------+

每條邊都被命名為“Pull”,我可以使用以下方法在 dot 中定義它:

digraph fan {
    OFF  -> HIGH [label="Pull"];
    HIGH -> MED  [label="Pull"];
    MED  -> LOW  [label="Pull"];
    LOW  -> OFF  [label="Pull"];
}

但我不想每次都指定相同的文本標簽,因為

  1. 我的標簽可能會很長,所以很容易出錯,而且
  2. 除了標簽,我的邊緣還有其他屬性,比如顏色,以及
  3. 我選擇了多種不同類型的邊,因此我想確保在圖中不同上下文中使用的邊類型“A”始終具有所有相同的屬性。

我希望 dot 有一種語法可以讓我為我的邊緣類型定義名稱,例如:

digraph fan {
    edge_a [label="Pull"];

    OFF  -> HIGH edge_a;
    HIGH -> MED  edge_a;
    MED  -> LOW  edge_a;
    LOW  -> OFF  edge_a;
}

但當然,真正做的是創建一個名為“Pull”的節點和未標記的邊。

我已經在網上搜索了幾個小時沒有成功。 任何人都知道如何預先定義要在多個位置使用的邊緣類型?

更新: @vaettchen 建議定義一個邊類型,然后列出該邊類型的所有過渡,然后定義下一個邊類型,然后是它的過渡。 雖然這在技術上可以解決我的問題,但它會引入其他一些問題,因為我今天的圖表可能如下所示:

digraph {
    subgraph cluster_1 {
        a -> b [label="type x", color=red, style=solid];
        b -> a [label="type y", color=green, style=dashed];

        b -> c [label="type x", color=red, style=solid];
        c -> b [label="type y", color=green, style=dashed];

        c -> d [label="type z", color=blue, style=dotted];
    }

    subgraph cluster_2 {
        d -> e [label="type x", color=red, style=solid];
        e -> d [label="type y", color=green, style=dashed];

        e -> f [label="type x", color=red, style=solid];
        f -> e [label="type y", color=green, style=dashed];

        f -> c [label="type z", color=blue, style=dotted];
    }
}

並按邊類型重新排列,我會在使雙向邊彼此相鄰(a->b 和 b->a)的代碼中失去直接的視覺清晰度,我必須明確列出每個中的節點子圖,我必須將子圖內部邊定義拉到主圖中:

digraph {
    edge [label="type x", color=red, style=solid];
    a -> b;
    b -> c;
    d -> e;
    e -> f;

    edge [label="type y", color=green, style=dashed];
    b -> a;
    c -> b;
    e -> d;
    f -> e;

    edge [label="type z", color=blue, style=dotted];
    c -> d;
    f -> c;

    subgraph cluster_1 {
        a; b; c;
    }

    subgraph cluster_2 {
        d; e; f;
    }
}

因此,雖然它可以解決我問過的問題並且我很欣賞這個建議,但我不確定是否值得權衡,因為你最終得到了一個 C 程序,你必須在函數之外定義所有變量和按類型而不是邏輯關聯來組織它們。

需要明確的是,鑒於上面的示例,如果存在這樣的“edge_type”定義關鍵字,我真正希望的內容將如下所示:

digraph {
    edge_type edge_x [label="type x", color=red, style=solid];
    edge_type edge_y [label="type y", color=green, style=dashed];
    edge_type edge_z [label="type z", color=blue, style=dotted];

    subgraph cluster_1 {
        a -> b edge_x;
        b -> a edge_y;

        b -> c edge_x;
        c -> b edge_y;

        c -> d edge_z;
    }

    subgraph cluster_2 {
        d -> e edge_x;
        e -> d edge_y;

        e -> f edge_x;
        f -> e edge_y;

        f -> c edge_z;
    }
}

我想我得到了你的解決方案,使用m4 (感謝Simon )。 使用和調整您的示例,我創建了一個名為gv.m4的文件:

digraph {
    define(`edge_x',`[label="type x", color=red, style=solid]')
    define(`edge_y',`[label="type y", color=green, style=dashed]')
    define(`edge_z',`[label="type z", color=blue, style=dotted]')

    subgraph cluster_1 {
        a -> b edge_x;
        b -> a edge_y;

        b -> c edge_x;
        c -> b edge_y;

        c -> d edge_z;
    }

    subgraph cluster_2 {
        d -> e edge_x;
        e -> d edge_y;

        e -> f edge_x;
        f -> e edge_y;

        f -> c edge_z;
    }
}

並使用簡單命令轉換它

m4 gv.m4 > gv.dot

現在包含您定義的邊

digraph {

    subgraph cluster_1 {
        a -> b [label="type x", color=red, style=solid];
        b -> a [label="type y", color=green, style=dashed];

        b -> c [label="type x", color=red, style=solid];
        c -> b [label="type y", color=green, style=dashed];

        c -> d [label="type z", color=blue, style=dotted];
    }

    subgraph cluster_2 {
        d -> e [label="type x", color=red, style=solid];
        e -> d [label="type y", color=green, style=dashed];

        e -> f [label="type x", color=red, style=solid];
        f -> e [label="type y", color=green, style=dashed];

        f -> c [label="type z", color=blue, style=dotted];
    }
}

並產生預期的圖形:

在此輸入圖像描述

你可以用m4做更多的事情 - 在graphViz中缺少的東西,比如維護和(甚至有條件地)包括子文件。 例如,如果將兩個子圖放入兩個單獨的文件gv1.txtgv2.txt ,這將很好地工作:

digraph incl
{
    define(`edge_x',`[label="type x", color=red, style=solid]')
    define(`edge_y',`[label="type y", color=green, style=dashed]')
    define(`edge_z',`[label="type z", color=blue, style=dotted]')
    include(gv1.txt)
    include(gv2.txt)
     e -> d[ color = yellow, label = "this is new!"];
}

在此輸入圖像描述

不是一個答案,而是“思考的食物”,因為我不認為graphviz存在命名標簽:您可以為以下邊緣定義默認標簽。 如果您的工作流程允許在一個位置定義邊緣,那么這很有效。 例:

digraph rs
{
    node[ shape = box, style = rounded]

    edge[ label = "pull" ];
    { A B } -> C;
    G -> H;
    C -> D[ label = "stop" ];
    edge[ label = "push"];
    D -> { E F };
    edge[ color = red, fontcolor = red ];
    { E F } -> G;
}

產量

在此輸入圖像描述

我也嘗試用你的實現

digraph fan 
{
    splines = ortho;
    node [ shape=box ]

    edge [ xlabel = "Pull", minlen = 4 ];
    { rank = same; OFF  -> HIGH -> LOW; }
    LOW:s -> OFF:s;
}

哪個產生

在此輸入圖像描述

所以它看起來不錯,但所有的調整很難擴展。

我努力在我的機器上下載 m4,因此選擇通過 python API 使用 graphviz,您可以在其中將樣式定義為字典並根據需要應用於節點/邊。

import graphviz

dot = graphviz.Digraph(comment='Test File')


nodeAttr_statement = dot.node_attr = {"shape": 'box', "style": 'filled', "fillcolor":"red"}
nodeAttr_question = dot.node_attr = {"shape": 'diamond', "style": 'filled', "fillcolor":"blue"}

dot.edge_attr

edge_Attr_sample = dot.edge_attr = {"arrowhead":'vee',"color":"yellow"}
edge_Attr_sample2 = dot.edge_attr = {"arrowhead": 'diamond', "color": "green"}


dot.node("A", "A", nodeAttr_statement)
dot.node("B", "B", nodeAttr_question )



dot.edge("A", "B", _attributes=edge_Attr_sample)
dot.edge("B", "A", _attributes=edge_Attr_sample2)
dot.format = 'pdf'
dot.render('test', view=True)

輸出

// Test File
digraph {
    node [fillcolor=blue shape=diamond style=filled]
    edge [arrowhead=diamond color=green]
    A [label=A fillcolor=red shape=box style=filled]
    B [label=B fillcolor=blue shape=diamond style=filled]
    A -> B [arrowhead=vee color=yellow]
    B -> A [arrowhead=diamond color=green]
}

從 python 腳本輸出圖像

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM