GraphViz - Wie verbinde ich Untergraphen?

166

In der DOTSprache für GraphVizversuche ich, ein Abhängigkeitsdiagramm darzustellen. Ich muss in der Lage sein, Knoten in einem Container zu haben und Knoten und / oder Container von anderen Knoten und / oder Containern abhängig zu machen.

Ich verwende subgraph, um meine Container darzustellen. Die Knotenverknüpfung funktioniert einwandfrei, aber ich kann nicht herausfinden, wie Subgraphen verbunden werden.

In Anbetracht der unten angegebene Programm muss ich in der Lage sein , zu verbinden cluster_1und cluster_2mit einem Pfeil, aber alles , was ich versucht habe , schafft neue Knoten stattdessen die Cluster verbinden:

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";
}

Geben Sie hier die Bildbeschreibung ein

Winston Smith
quelle
2
Ich habe das gleiche Problem, aber sie haben ein natürliches Beispiel, bei dem sich Untergraphen wie Knoten verhalten : graphviz.org/content/fdpclust .
Nlucaroni
1
@nlucaroni Ich frage mich, ob dieses Problem gelöst ist. Dieses Beispiel gibt mir einen falschen Graphen: Kanten verbinden die Zentren des Untergraphen. Weißt du nicht, wie es funktioniert, wie im Beispiel?
K102
1
@ k102, ich weiß. Schauen Sie sich diese Seite noch einmal an. es sagt, dass Sie verwenden müssen fdp. Das verknüpfte Beispiel und das obige funktionieren beide (die letzte Zeile im Beispiel hier muss die Namen der Untergraphen verwenden, nicht die Beschriftung, und es kann hilfreich sein, Zeilenlängen für das Diagramm einzuschließen). es ist ein wenig eng wie es ist).
Nlucaroni
1
@nlucaroni Wenn Sie fdpv2.28.0 verwenden und die Quelle aus dem Beispiel kopieren / einfügen, werden die Linien mit der Mitte des Untergraphen und nicht mit den Kanten verbunden. Wenn Sie den Punkt in OmniGraffle öffnen, sind sie ordnungsgemäß verbunden, neatound dotbeide erstellen überflüssige Knoten für den Cluster.
Phrogz

Antworten:

190

Das DOT-Benutzerhandbuch enthält das folgende Beispiel eines Diagramms mit Clustern mit Kanten zwischen Clustern:

WICHTIG: Die erste compound=trueAnweisung ist erforderlich.

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

... und Kanten zwischen Knoten und Clustern:

Geben Sie hier die Bildbeschreibung ein

Hochleistungsmarke
quelle
14
Danke - das funktioniert, aber es fühlt sich wirklich wie ein hässlicher Hack an. Ich hoffe, ich habe kein Szenario, in dem ich einen Container ohne Knoten habe.
Winston Smith
5
Falls jemand daran interessiert ist, kann dies zu Positionierungsproblemen führen, wenn Sie Links (Kanten) beschriftet haben. Während der Kopf oder das Ende der Kante unter einem Cluster verborgen sein kann, befindet sich die Beschriftung immer noch im Mittelpunkt, was bedeutet, dass einige Kantenbeschriftungen über einem Cluster zu schweben scheinen, anstatt von der Kante selbst positioniert zu werden.
Winston Smith
58
@WinstonSmith: Alte Frage, aber ich hatte ein ähnliches Problem und löste es mit einem unsichtbaren Dummy-Knoten pro Cluster, mit dem verknüpft werden kann, auch wenn der Cluster ansonsten leer ist. DUMMY_0 [shape=point style=invis]
DevSolar
2
Ich habe festgestellt, dass meine Kanten zwischen Clustern auf Pfeilspitzen reduziert sind, wenn Cluster verwendet werden, die nur vertikal verbunden sind. Ich habe das mit minlen = 1 an den Rändern behoben . c -> g [ltail = cluster0, lhead = cluster1, minlen = 1];
Freenerd
2
Hier ist der Link zum Handbuch mit dem Beispiel: graphviz.org/Documentation/dotguide.pdf (Seite 30).
Kirill Bulygin
90

Zur Vereinfachung der Bezugnahme sieht die in der Antwort von HighPerformanceMark beschriebene Lösung, die direkt auf die ursprüngliche Frage angewendet wird, folgendermaßen aus:

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];
}

Das compound=truein der graphErklärung ist von entscheidender Bedeutung. Das erzeugt Ausgabe:

Grafik mit verbundenen Clustern

Beachten Sie, dass ich die Kanten in Referenzknoten innerhalb des Clusters geändert, die Attribute ltail und lhead zu jeder Kante hinzugefügt, den Clusternamen angegeben und das Attribut "Verbindung = wahr" auf Diagrammebene hinzugefügt habe.

In Bezug auf die Sorge, dass ein Cluster ohne Knoten verbunden werden soll, bestand meine Lösung darin , jedem Cluster immer einen Knoten hinzuzufügen, der mit style = plaintext gerendert wird. Verwenden Sie diesen Knoten, um den Cluster zu beschriften (anstelle des integrierten "label" -Attributs des Clusters, das auf die leere Zeichenfolge gesetzt werden sollte (in Python label='""'). Dies bedeutet, dass ich keine Kanten mehr hinzufüge, die Cluster direkt verbinden, sondern es funktioniert in meiner besonderen Situation.

Jonathan Hartley
quelle
24
Hinweis: 'graph [fontsize = 10 fontname = "Verdana" -Verbindung = true];' ist wichtig - wenn Sie vermissen, dass die Verknüpfung mit ltail / lhead nicht funktioniert.
Daniel
1
@JonathanHartley, Gibt es gemäß Ihrem letzten Absatz eine Möglichkeit, diesen Knoten genau in der Mitte des Clusters zu zentrieren?
Pacerier
Auch der Name des Clusters sollte nicht mit einem Großbuchstaben beginnen
JCLL
7
@ an Daniel Es ist nur die Verbindung = wahr; was erforderlich ist
Dr. Max Völkel
Wie verknüpfe ich cluster_0 und cluster_1 mit aussagekräftigem Code, anstatt lhead und ltail zurückzusetzen, wenn "Item 1" -> "Item 3" verknüpft wird? Ich meam, mach cluster_0 -> cluster_1präsent, während du ausgibst. Weil es in cluster_0 möglicherweise viele Elemente gibt, die mit anderen vielen Elementen in cluster_1 verknüpft sind (viele zu viele oder eins zu viele). Es wäre gut, nur zwei zu verknüpfen.
Mithril
11

Stellen Sie sicher, dass Sie das fdpLayout für die Datei verwenden. Ich denke nicht, dass neatoCluster unterstützt werden.

mihajlv
quelle
2
Ich habe auch experimentell festgestellt, dass die neatoEngine keine Cluster unterstützt. Ich bin nicht sicher, ob dies ein Fehler ist oder nicht.
Ross Rogers