2010-05-25 19 views
11

Ich versuche, eine Baumstruktur mit graphviz zu erstellen. Ich bin offen dafür, entweder den GraphViz-Code von Hand zu schreiben oder den Ruby-GraphViz-Edelstein für Ruby zu verwenden. Kann das folgende Bild einen Einblick in den notwendigen Code geben? Ignoriere, dass die Linien nicht gerade sind ... sie sollten sein, wenn graphviz den Graphen erstellt. Ich bin offen für Punkte/Punkte, wenn Linien sich auch schneiden.komplizierte graphviz Baumstruktur

Ich habe mit Ruby-Graphviz und der Familienstammbaum-Klasse gespielt ... das bringt mir einen Teil des Weges, aber ich brauche wirklich alle Linien, die gerade sind und sich im rechten Winkel schneiden und die Out-of-the- Box-Code scheint das nicht zu tun.

Der Code sollte allgemein genug sein für die „C“ Box zu ermöglichen, Kinder zu haben, wie gut und für dort auch mehr Kinder unter „A“ zu sein.

Die Farben sind irrelevant ... die Beispiele jede Färbung ausschließen.

http://docs.google.com/drawings/pub?id=1lUTfgKP_LN0x7C3ItbsFjfLBuDTL84AtmoaW7YFn32Y&w=1036&h=713

Antwort

4

Soweit ich weiß, dass dies erfordert ein wenig Arbeit herumführen; Ich werde es nur in Graphviz DOT Sprache machen. Ich gebe dir zuerst die Lösung und dann einige Erklärungen, wie du sie erweitern kannst.

Dies ist die resultierende Zahl:

outfile.png

Dies ist der Graphviz Code die Figur Herstellung:

graph atree { 
    Item1 [shape=none,label="Item 1",pos="2.2,1.1!"]; 
    Item2 [shape=none,label="Item 2",pos="2.2,0.1!"]; 
    Item3 [shape=none,label="Item 3",pos="2.9,-0.3!"]; 
    A [shape=box,color=lightblue,style=filled,pos="2,3!"]; 
    B [shape=box,color=lightblue,style=filled,pos="1,2.1!"]; 
    C [shape=box,color=lightblue,style=filled,pos="3,2.1!"]; 
    D [shape=box,color=lightblue,style=filled,pos="1.5,1.5!"]; 
    E [shape=box,color=lightblue,style=filled,pos="1.5,0.5!"]; 
    D0 [style=invisible,fixedsize=true,width=0,height=0,pos="2,2.5!",label=""]; 
    D1 [style=invisible,fixedsize=true,width=0,height=0,pos="1,2.5!",label=""]; 
    D2 [style=invisible,fixedsize=true,width=0,height=0,pos="3,2.5!",label=""]; 
    D3 [style=invisible,fixedsize=true,width=0,height=0,pos="1,1.5!",label=""]; 
    D4 [style=invisible,fixedsize=true,width=0,height=0,pos="1,0.5!",label=""]; 
    D5 [style=invisible,fixedsize=true,width=0,height=0,pos="1.5,1.1!",label=""]; 
    D6 [style=invisible,fixedsize=true,width=0,height=0,pos="1.5,0.1!",label=""]; 
    D7 [style=invisible,fixedsize=true,width=0,height=0,pos="2.2,-0.3!",label=""]; 
    A -- D0 -- D1 -- B -- D3 -- D4 -- E [color=blue]; 
    E -- D6 -- Item2 -- D7 -- Item3 [color=blue]; 
    D0 -- D2 -- C [color=blue]; 
    D3 -- D -- D5 -- Item1 [color=blue]; 
} 

Wenn Sie es in einer Datei mit dem Namen setzen inputfile.dot Sie das resultierende Bild bekommen Datei mit dem Befehl neato -Tpng inputfile.dot > outfile.png.

Jetzt ein paar Kommentare, wie es funktioniert: Der Code, der den Baum mit A, B, C, D, E, Item1, Item2, Item3 erstellt, ist unkompliziert (die Attribute legen nur die Farben und Boxstile fest). Der Trick, um die Linien gerade und orthogonal zu erhalten, besteht aus 1) Hinzufügen von unsichtbaren Knoten mit der Größe Null zu dem Graphen und 2) Positionieren aller Objekte in absoluten Koordinaten auf der Leinwand. Der Hilfsknoten D1, D2, D3, D4, D5, D6, D7 für Schritt 1) ​​und die pos="x,y!" Optionen benötigt werden, werden für den Schritt 2) benötigt wird. Beachten Sie, dass Sie das ! Zeichen am Ende des pos Befehls benötigen, da sonst die Positionen nicht als endgültig angesehen werden würden und das Layout noch umziehen würde.

können Sie fügen zusätzliche Knoten, die durch erste Positioniereinrichtung einen neuen Knoten (durch den Code für den Knoten unter Verwendung von A ... Item3 als Vorlage), einen unsichtbaren, Hilfsknoten Addieren (mit pos, so daß alle Verbindungen zu und von ihm orthogonal sind), und Fügen Sie dann die Verbindung zum Diagramm über <StartingNode> -- <AuxiliaryNode> -- <NewNode> hinzu.

+0

so sieht es aus wie mein Code den harten Teil in herauszufinden, die absolute Positionierung Zahlen zu tun haben! – thomas

+0

Leider kenne ich keine Möglichkeit, Graphviz zu verwenden, das den Graphen mit orthogonalen (und aufteilenden) Verbindungen zwischen Knoten zeichnet! Wenn Sie dieses Verhalten nicht benötigen, übernimmt Graphviz die meiste Arbeit für Sie. Wenn Sie auf diesem Verhalten bestehen, müssen Sie einige manuelle Arbeit für das Layout tun. – user8472

+0

danke. Ich brauche dieses Verhalten leider. Ich werde diese Logik codieren müssen. – thomas

12

ein wenig zu spät, ich weiß, aber ich wollte nur, ohne dass eine andere Version zeigen, die die genaue Positionen von jedem Knoten, um herauszufinden.

digraph { 
    splines=false; 
    ranksep=0.05; 

    node[shape=box, color=lightblue, style=filled]; 
    A;B;C;D;E; 

    node[shape=none, color=none, style=solid]; 
    i1[label="Item 1"]; 
    i2[label="Item 2"]; 
    i3[label="Item 3"]; 

    node[label="", width=0, height=0]; 
    edge[arrowhead=none, color=blue]; 

    {rank=same; n2; n1; n3;} 
    n2; n1; n3; 
    A -> n1; 
    n2 -> n1 -> n3; 

    {rank=same; B; C;} 
    n2 -> B; 
    n3 -> C; 

    {rank=same; n4; D;} 
    B -> n4 -> D; 

    {rank=same; n6; n5; i1;} 
    D -> n5 -> i1; 
    n4 -> n6; 

    {rank=same; n7; E;} 
    n6 -> n7 -> E; 

    {rank=same; n8; i2;} 
    E -> n8 -> i2; 

    {rank=same; n9; i3;} 
    i2 -> n9 -> i3; 
} 

Gerade Linien erzwungen werden durch:

  • splines=false - nein sagen
  • unsichtbare Knoten (Knoten n1 Splines, n2, ...n9)
  • Platzierung Knoten auf dem gleichen Rang mit rank=same

Es ist noch einige Arbeit der Punktdatei richtig zu machen, aber es schlägt imho Berechnung sich die Position jedes Knotens.

Ausgabe sieht wie folgt aus:

graphviz output

Solange C keine Kindknoten hat, würden Sie etwas mehr Tricks (unsichtbare Knoten) anwenden müssen, um es anzuzeigen den ganzen Weg nach rechts.

Um eine allgemeinere Lösung für verschiedene Graphen zu erhalten, werden wahrscheinlich einige weitere Anpassungen erforderlich sein (Gewicht auf vertikale Kanten anwenden oder Gruppenknoten, die vertikal ausgerichtet sein müssen, oder Teilgraphen verwenden, ...).

+0

Hinweis: Es funktioniert nicht richtig mit den neuesten GraphViz-Versionen. 'splilines = ortho' könnte stattdessen verwendet werden, wenn Sie die externen versteckten Knoten entfernen http://stackoverflow.com/a/36953206/1312346 –

3

Noch eine Version mit splines=ortho, die weniger versteckte Knoten benötigt und ähnliche visuelle Ergebnisse liefert.

digraph example { 
    splines=ortho; 
    ranksep=0.05; 

    node[shape=box, color=lightblue, style=filled]; 
    A;B;C;D;E; 

    node[shape=none, color=none, style=solid]; 
    i1[label="Item 1"]; 
    i2[label="Item 2"]; 
    i3[label="Item 3"]; 

    node[label="", width=0, height=0]; 
    edge[arrowhead=none, color=blue]; 
    n1; n2; n3; n4; n5; 

    {rank=same; B; C;} 
    A -> n1; 
    n1 -> B; 
    n1 -> C; 

    {rank=same; n2; D;} 
    B -> n2; 
    n2 -> D; 

    {rank=same; n3; i1;} 
    D -> n3; 
    n3 -> i1; 

    {rank=same; n4; E;} 
    n2 -> n4; 
    n4 -> E; 

    {rank=same; n5; i2;} 
    E -> n5; 
    n5 -> i2; 

    {rank=same; n6; i3;} 
    i2 -> n6; 
    n6 -> i3; 
} 

dot image drawn via PlantUML.com