GraphViz - Come collegare i sottografi?


166

Nella DOTlingua di GraphViz, sto cercando di rappresentare un diagramma delle dipendenze. Ho bisogno di essere in grado di avere nodi all'interno di un contenitore e di poter rendere nodi e / o contenitori dipendenti da altri nodi e / o contenitori.

Sto usando subgraphper rappresentare i miei contenitori. Il collegamento dei nodi funziona bene, ma non riesco a capire come collegare i sottografi.

Dato il programma seguente, devo essere in grado di connettermi cluster_1e cluster_2con una freccia, ma qualsiasi cosa abbia provato crea nuovi nodi invece di collegare i cluster:

digraph G {

    graph [fontsize=10 fontname="Verdana"];
    node [shape=record fontsize=10 fontname="Verdana"];

    subgraph cluster_0 {
        node [style=filled];
        "Item 1" "Item 2";
        label = "Container A";
        color=blue;
    }

    subgraph cluster_1 {
        node [style=filled];
        "Item 3" "Item 4";
        label = "Container B";
        color=blue;
    }

    subgraph cluster_2 {
        node [style=filled];
        "Item 5" "Item 6";
        label = "Container C";
        color=blue;
    }

    // Renders fine
    "Item 1" -> "Item 2";
    "Item 2" -> "Item 3";

    // Both of these create new nodes
    cluster_1 -> cluster_2;
    "Container A" -> "Container C";
}

inserisci qui la descrizione dell'immagine


2
Sto riscontrando lo stesso problema, eppure hanno un esempio naturale in cui i sottografi si comportano come nodi, graphviz.org/content/fdpclust .
nlucaroni,

1
@nlucaroni mi chiedo se questo problema sia risolto. questo esempio mi dà un grafico sbagliato: i bordi collegano i centri del sottografo. non sai come farlo funzionare come nell'esempio?
k102,

1
@ k102, lo so. Scopri di nuovo quella pagina; dice che devi usare fdp. L'esempio collegato e quello sopra funzionano entrambi (l'ultima riga nell'esempio qui deve usare i nomi dei sottografi non l'etichetta e potrebbe essere utile includere le lunghezze delle linee per il grafico); è un po 'stretto così com'è).
nlucaroni,

1
@nlucaroni Usando fdpv2.28.0 e copiando / incollando la fonte dall'esempio le linee si collegano al centro del sottografo, non ai bordi. Se si apre il dot in OmniGraffle questi sono collegati, mentre neatoe dotsia creare nodi superflui per il cluster.
Phrogz,

Risposte:


190

Il manuale utente DOT fornisce il seguente esempio di grafico con cluster con bordi tra i cluster:

IMPORTANTE: compound=trueè richiesta la dichiarazione iniziale .

digraph G {
  compound=true;
  subgraph cluster0 {
    a -> b;
    a -> c;
    b -> d;
    c -> d;
  }
  subgraph cluster1 {
    e -> g;
    e -> f;
  }
  b -> f [lhead=cluster1];
  d -> e;
  c -> g [ltail=cluster0,lhead=cluster1];
  c -> e [ltail=cluster0];
  d -> h;
}

... e bordi tra nodi e cluster:

inserisci qui la descrizione dell'immagine


14
Grazie - funziona, ma sembra davvero un brutto hack. Sto sperando che non ho uno scenario in cui ho un contenitore senza nodi.
Winston Smith,

5
Nel caso in cui qualcuno sia interessato, questo può causare problemi di posizionamento se si hanno collegamenti etichettati (bordi). Mentre la testa o la coda del bordo possono essere nascoste sotto un cluster, l'etichetta è ancora posizionata nel punto medio, il che significa che alcune etichette del bordo sembrano fluttuare su un cluster invece di essere posizionate dal bordo stesso.
Winston Smith

58
@WinstonSmith: Vecchia domanda, ma ho avuto un problema simile e l'ho risolto con un nodo fittizio invisibile per cluster, che può essere collegato anche se il cluster è vuoto altrimenti. DUMMY_0 [shape=point style=invis]
DevSolar il

2
Ho scoperto che i miei bordi tra cluster erano compressi solo con punte di freccia, quando si utilizzavano cluster collegati solo verticalmente. L'ho risolto con minlen = 1 sui bordi. c -> g [ltail = cluster0, lhead = cluster1, minlen = 1];
Venerdì

3
Ecco il link al manuale con l'esempio: graphviz.org/Documentation/dotguide.pdf (pagina 30).
Kirill Bulygin,

90

Per facilità di riferimento, la soluzione descritta nella risposta di HighPerformanceMark, applicata direttamente alla domanda originale, è simile alla seguente:

digraph G {

    graph [fontsize=10 fontname="Verdana" compound=true];
    node [shape=record fontsize=10 fontname="Verdana"];

    subgraph cluster_0 {
        node [style=filled];
        "Item 1" "Item 2";
        label = "Container A";
        color=blue;
    }

    subgraph cluster_1 {
        node [style=filled];
        "Item 3" "Item 4";
        label = "Container B";
        color=blue;
    }

    subgraph cluster_2 {
        node [style=filled];
        "Item 5" "Item 6";
        label = "Container C";
        color=blue;
    }

    // Edges between nodes render fine
    "Item 1" -> "Item 2";
    "Item 2" -> "Item 3";

    // Edges that directly connect one cluster to another
    "Item 1" -> "Item 3" [ltail=cluster_0 lhead=cluster_1];
    "Item 1" -> "Item 5" [ltail=cluster_0 lhead=cluster_2];
}

Il compound=truenella graphdichiarazione è di vitale importanza. Questo produce output:

grafico con cluster collegati

Si noti che ho modificato i bordi per fare riferimento ai nodi all'interno del cluster, ho aggiunto gli attributi ltail e lhead a ciascun bordo, specificando il nome del cluster e aggiunto l'attributo a livello di grafico 'compound = true'.

Per quanto riguarda la preoccupazione che si potrebbe desiderare di connettere un cluster senza nodi al suo interno, la mia soluzione è stata quella di aggiungere sempre un nodo a ogni cluster, reso con style = plaintext. Usa questo nodo per etichettare il cluster (invece dell'attributo "label" incorporato del cluster, che dovrebbe essere impostato sulla stringa vuota (in Python label='""'). Ciò significa che non sto più aggiungendo i bordi che collegano direttamente i cluster, ma funziona nella mia situazione particolare.


24
Nota: 'graph [fontsize = 10 fontname = "Verdana" compound = true];' è essenziale - se perdi che il collegamento a ltail / lhead non funziona.
Daniele,

1
@JonathanHartley, Come per il tuo ultimo paragrafo, c'è un modo per centrare quel nodo proprio nel mezzo del cluster?
Pacerier,

anche il nome del cluster non dovrebbe iniziare con una lettera maiuscola
JCLL

7
@ s.Daniel È solo il composto = vero; che è richiesto
Dr. Max Völkel,

Invece di reimpostare lhead e ltail quando si collega "Item 1" -> "Item 3", come posso collegare cluster_0 e cluster_1 con un codice significativo? Meam, rendi cluster_0 -> cluster_1presente mentre esci. Perché potrebbero esserci molti elementi nel collegamento cluster_0 ad altri molti elementi in cluster_1 (molti a molti o uno a molti). Sarebbe bene collegarne solo due.
Mithril,

11

Assicurati di utilizzare il fdplayout per il file. Non credo neatosupporti i cluster.


2
Anch'io ho sperimentalmente scoperto che il neatomotore non supporta i cluster .. Non sono sicuro che si tratti di un bug o no ..
Ross Rogers
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.