2013-05-10 81 views
3

我有一個以DOT語言編碼的圖形集合。我想要構造一個圖表,使得超圖中的每個節點都是這些圖的其中一個。有沒有辦法在GraphViz框架內做到這一點?Graphviz中的圖形圖形

我知道gvpack將允許我將多個圖組合成一個.dot文件。但我不知道它是否會允許我在這些圖表之間聲明邊界。

回答

5

簡短的回答是gvpack沒有聲明子圖之間的邊。事實上,當子圖之間存在共同的節點名稱時,gvpack將它們重命名以避免衝突。但是,這是可以修復的。

例如,給定3個.dot文件1.dot

digraph { 
    A -> B 
    A -> C 
    } 

2.dot

digraph { 
    D -> E 
    E -> F 
    } 

...和3.dot

digraph { 
    D -> G 
    G -> A 
    } 

...運行gvpack -u 1.dot 2.dot 3.dot | dot -Tjpg -ogvp1.jpg提供了以下圖形gvp1.jpg

enter image description here

正如你所看到的,gvpack已經重新貼上標籤,重複的節點名稱。然而,我們可以很容易地扭轉使用gvpack -u 1.dot 2.dot 3.dot | sed 's/_gv[0-9]\+//g' | dot -Tjpg -ogvsub.jpg重新貼標籤,其產生以下圖表gvsub.jpg

enter image description here

這種方法依賴於具有共同的節點名稱的子圖,所以它可能是需要插入額外的節點在子圖.dot文件中實現這一點。

(編輯:上面的溶液顯示出與節點合併,但不與在簇中的子圖的曲線圖下面的解決方案示出了在集羣子圖。)

鑑於.dot文件1.dot(這些是與上面相同的文件,但我已經給每個有向圖的名稱):

digraph g1 { 
    A -> B 
    A -> C 
    } 

2.dot

digraph g2 { 
    D -> E 
    E -> F 
    } 

...和3.dot

digraph g3 { 
    D -> G 
    G -> A 
    } 

...與hdr.dot一起:

digraph GMaster { 
    compound = true; 
    g1 [style=invisible, height = 0, width = 0, label=""]; 
    g2 [style=invisible, height = 0, width = 0, label=""]; 
    g3 [style=invisible, height = 0, width = 0, label=""]; 
    g1 -> g2 [lhead=clusterg2, ltail=clusterg1]; 
    g1 -> g3 [lhead=clusterg3, ltail=clusterg1] 

...和tail.dot

} 

...我們可以運行cat 1.dot 2.dot 3.dot | sed 's/digraph \(\w*\) *{/subgraph cluster\1 { \1/' | cat hdr.dot - tail.dot | dot -Tjpg -oclust1.jpg給文件clust1.jpg

enter image description here

因此,在頭文件,我已經添加了一個invisble節點到每個子圖,具有相同的名稱作爲子圖,用於compound=true來允許羣集之間的邊緣。我已經指定了在簇之間繪製的邊緣,並且我已經爲不可見節點之間的每條邊設置了lheadltail,以確保將正確的簇用作每個邊的頭部和尾部。在使用sed將每個子圖轉換爲集羣的過程中,我還爲每個子圖添加了適當的不可見節點。

顯示節點D,G和A之間的邊緣,因爲這些節點在羣集之間是共同的。而且,它們中的每一個僅顯示在一個羣集中。如果節點對於簇是唯一的,那麼將在簇之間顯示的唯一邊將是不可見節點之間的邊緣。這可以看出,在下面的圖,在那裏我已經在3.dot改名爲節點:

enter image description here

有一個剩餘的缺陷,我還沒有完全得以解決。不可見節點仍佔用一點點空間,因此集羣框看起來不平衡,因爲不可見節點與可見節點並排放置。這也意味着簇之間邊緣的頭部指向簇框的一側而不是中間。目前,除非我們準備查看每個子圖並找到一個已經在該子圖/集羣中的節點作爲該子圖/集羣的代表節點,否則我不知道可以做些什麼。我們爲該羣集繪製邊緣的一個或者從中)。手工製作幾個子圖可以很容易地完成,但是如果有多個子圖,則會很繁瑣。

相反,我上面使用的方法只需要我們知道羣集的名稱,並且可以將它插入到hdr.dot文件中。

我已經構建了hdr.dot文件由專人針對這種情況,但hdr.dot文件的內容可以從其他.dot文件,如果有必要提取與sedawkperlpython。如果有關應該連接哪些羣集的信息可用,該腳本還可以插入邊緣以將羣集鏈接到hdr.dot

+0

感謝Simon的徹底迴應。在我的情況下,儘管我想把每個子圖作爲超圖中的節點,而不是組件。我想指定1-> 2和1-> 3之間存在一條邊,並將子圖劃分爲不同的部分,並用節點之間的適當邊構成節點。 – MRocklin 2013-05-13 13:49:52

+0

啊,我明白了。我認爲加入子圖可以通過類似於我在答案中採用的方法來實現。我會考慮一下。 – Simon 2013-05-13 20:42:15

+0

我編輯了我的答案,以顯示如何通過邊鏈接羣集。 – Simon 2013-05-14 02:29:00