2017-10-05 97 views
0

我需要繪製graphviz/dot圖,其中節點之間存在常見的邊緣類型,並試圖找到一種方法來爲每種類型的邊界定義標籤,然後在圖中多次使用該標籤。如何在Graphviz/dot/neato中創建命名邊「類型」?

例如想象傳統的吊扇FSM例如它的最初狀態OFF和每次有人拉它基於風扇的轉速變化到一個新的狀態線:

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

每個邊緣命名爲「拉」,我可以通過定義一個對點:

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

,但我不希望保留每次都指定同一個文本標籤,因爲

  1. 我的標籤就會變得很長,所以這是容易出錯,並且
  2. 我邊有其他屬性除了像標籤顏色,並
  3. 我有一個選擇的多個不同類型的邊緣,所以我想拍確保圖中不同上下文中使用的邊緣類型「A」始終具有所有相同的屬性。

我的預期點有一個語法,它可以讓我定義我的邊緣類型的名稱,像:

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

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

但當然什麼的確實是創建一個名爲「拉」節點未標記的邊緣。

我一直在網上搜索幾個小時,沒有成功。任何人都知道如何定義邊緣類型以在多個位置使用?

更新:@vaettchen had suggested定義了一個邊類型,然後列出該邊類型的所有轉換,然後定義下一個邊類型,然後定義它的轉換。雖然這在技術上解決我的問題,它會介紹一些其他的,因爲今天我的圖表可以關注一下:

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; 
    } 
} 
+0

親愛的驅動由downvoter - 護理解釋爲什麼?這個問題有樣本輸入,輸出,試圖解決方案和需求聲明,所以我不知道我能做些什麼來改進它。 –

+1

對於下面的'm4'解決方案,我已經做了一些工作並將它添加到[github](https://github.com/vaettchen/m4gv)。我希望你仍然可以使用它... – vaettchen

+0

再次感謝,我會看看。談到github,我希望能找到一種方法在README.md中包含.dot規範,並在有人在github上查看時自動呈現圖形。因此,如果我在.dot中有一個系統的文本模型,我不必手動更新它的圖像。我發現一個網站(https://github.com/TLmaK0/gravizo)我可以鏈接到一個對我的.dot文件的引用,並且實際上工作,但是我正在使用的github網站是專有的,所以外部網站可以'實際上看到我的內部.dot文件。你有沒有遇到類似的東西? –

回答

1

不是一個真正的答案,但「精神食糧」因爲我不認爲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; 
} 

這將產生

enter image description here

我也試圖與

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

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

產生

enter image description here

實現你diagramm

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

+0

感謝您的建議。我可以在技術上做你建議定義邊緣特徵的建議,然後列出所有類型的轉換,但是現在我在大多數節點之間有雙向邊緣(例如Off-> On和On-> Off)加上我有子圖的邊緣類型A出現在多個子圖中,所以我會在每個子圖中明確列出節點時添加一些更多的工作,將內部邊界定義從子圖中拉出來,並且我會失去對/從並列的每對節點的邊緣。 –

+1

是的,我認爲這比粉絲更復雜 - 你知道'gvpr'嗎?這對我來說太過分了,但您可能會找到方法將它用於您的服務。 – vaettchen

+0

'gvpr'很有意思,謝謝你的建議。我一直在考慮編寫一個awk程序來預處理邊界類型定義增加的點狀文件,如果點本身不支持,但也許gvpr將是一個更強大的方法。我需要做更多的閱讀...... –

1

我想我得到了您的解決方案,使用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]; 
    } 
} 

,併產生了將其轉換預計圖表:

enter image description here

你可以用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!"]; 
} 

enter image description here

+0

有趣,謝謝。在你的'define'行中,你使用反引號和撇號的混合(例如'\'edge_x'' =反引號邊撇號) - 是否真的是需要使用的語法還是錯字?我沒有'm4'可用於測試... –

+0

這實際上是所需的語法。代碼是從生成圖形的實際測試中複製和粘貼的。 – vaettchen