Graphviz Legend/Key with Nodes
Asked Answered
D

2

8

I am trying to create a legend/key in Graphviz that contains, not just text, but nodes and edges. While I've read this post, the HTML table does not seem to work with what I am trying to do.

Right now, the code I am using is:

digraph G {
fontname="Helvetica";
labelloc=t;
rankdir=LR;
label="Course Graph";

node[style=filled, fontname="Helvetica", colorscheme=greens3, color=1];

subgraph cluster_key {
    rank=min;

    label="Key";
    rankdir=LR;

    kc1[label="Course", peripheries=2, color=2];
    k1[shape=plaintext, style=solid, label="Required Course"]
    prereq[label="Course 1"];
    kc2[label="Course 2"];
    prereq->kc2;
    k2[shape=plaintext, style=solid, label="Course 1 is a prerequisite for Course 2"]
    coreq1[label="Course 1"];
    coreq2[label="Course 2"];
    coreq1->coreq2[dir=both];
    k3[shape=plaintext, style=solid, label="Course 1 and Course 2 are corequisite"]

    or[style="dashed", color="black", shape="diamond", label="OR"];
    or1[label="Course 1"];
    or1 -> or[style="dashed", dir="none"];
    or2[label="Course 2"];
    or2 -> or[style="dashed", dir="none"];
    kc3[label="Course 3"]
    or->kc3;
    k4[shape=plaintext, style=solid, label="You must take either Course 1 OR\nCourse 2 before taking Course 3"]
    { rank=min;k1 k2 k3 k4 }
}

c3[color=3, peripheries=2];
c4[color=3, peripheries=2];

c1->c2[dir=both];
c2->c3;

c4_reqs[style="dashed", color="black", shape="diamond", label="OR"];
c4_reqs->c4;
c2->c4_reqs[style="dashed", dir="none"];
c5->c4_reqs[style="dashed", dir="none"];

}

The result of this code is:

The result of this code is

but I would like something more like this - preferably sized smaller:

ebut I would like something more like

Dutchman answered 21/10, 2013 at 19:1 Comment(0)
T
10

You weren't far off. With some minor adjustments I got the following result:

enter image description here

The most important change I made was use rank=source instead of rank=min to get the nodes lined up correctly.

To fix the text alignment I used \r to align the text to the right (\l does the same but to the left) and give all of the plaintext nodes the same width.

The entire code looks like this (I added some comments where I made the changes):

digraph G {
    fontname="Helvetica";
    labelloc=t;
    rankdir=LR;
    label="Course Graph";

    node[style=filled, fontname="Helvetica", colorscheme=greens3, color=1];

    subgraph cluster_key {
        //rank=min; /* this doesn't really do anything for you */

        label="Key";
        //rankdir=LR; /* this is also not needed*/

        kc1[label="Course", peripheries=2, color=2];
        k1[shape=plaintext, style=solid, label="Required Course\r", width=3.5] // Add fixed width so all nodes line up

        prereq[label="Course 1"];
        kc2[label="Course 2"];
        prereq->kc2;
        k2[shape=plaintext, style=solid, label="Course 1 is a prerequisite for Course 2\r", width=3.5]  // Add fixed width

        coreq1[label="Course 1"];
        coreq2[label="Course 2"];
        coreq1->coreq2[dir=both];
        k3[shape=plaintext, style=solid, label="Course 1 and Course 2 are corequisite\r", width=3.5]    // Add fixed width

        or[style="dashed", color="black", shape="diamond", label="OR"];
        or1[label="Course 1"];
        or1 -> or[style="dashed", dir="none"];
        or2[label="Course 2"];
        or2 -> or[style="dashed", dir="none"];
        kc3[label="Course 3"]
        or->kc3;
        k4[shape=plaintext, style=solid, label="You must take either Course 1 OR\rCourse 2 before taking Course 3\r", width=3.5] // Add fixed width

        { rank=source;k1 k2 k3 k4 } // Use "source in stead of min
    }

    c3[color=3, peripheries=2];
    c4[color=3, peripheries=2];

    c1->c2[dir=both];
    c2->c3;

    c4_reqs[style="dashed", color="black", shape="diamond", label="OR"];
    c4_reqs->c4;
    c2->c4_reqs[style="dashed", dir="none"];
    c5->c4_reqs[style="dashed", dir="none"];

}

On a side note, the code could be cleaned up a bit by placing all of the plaintext nodes together, so attributes wouldn't have to be declared more often. This would have the added benefit of the nodes and rank attribute not being split into different parts in the code:

    { 
        rank=source
        node [shape=plaintext, style=solid, width=3.5]

        k1 [label="Required Course\r"]
        k2 [label="Course 1 is a prerequisite for Course 2\r"]
        k3 [label="Course 1 and Course 2 are corequisite\r"]
        k4 [label="You must take either Course 1 OR\rCourse 2 before taking Course 3\r"]
    }
Theravada answered 23/10, 2013 at 20:7 Comment(0)
C
0

Here is a smaller and arguably simpler way to build this legend/key:

  1. put the entire legend inside an html table and make that a cluster label
  2. use labelloc and labeljust to position the label/legend/table
  3. turn each of the left-side figures into stand-alone images and then include them with the IMG attribute

This:

 digraph G {
    graph [fontname="Helvetica"  labelloc=t labeljust=c  rankdir=LR]
    graph [label="Course Graph"]
    subgraph clusterAll{
      graph [peripheries=0  labelloc=b labeljust=r  rankdir=LR]
      node[shape=none]
      graph[label=<
        <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
          <TR><TD ALIGN="LEFT" >Required Course</TD>
              <TD ALIGN="LEFT"><IMG SRC="courseKey1a.png"/></TD></TR>
          <TR><TD ALIGN="LEFT" >Course 1 is a prerequisite for Course 2</TD>
              <TD  ALIGN="LEFT"><IMG SRC="courseKey1b.png"/></TD></TR>
          <TR><TD  ALIGN="LEFT">Course 1 and Course 2 are corequisite</TD>
              <TD  ALIGN="LEFT"><IMG SRC="courseKey1c.png"/></TD></TR>
          <TR><TD  ALIGN="LEFT">You must take either Course 1<BR  ALIGN="LEFT"/>OR<BR  ALIGN="LEFT"/>Course 2 before taking Course 3</TD>
              <TD  ALIGN="LEFT"><IMG SRC="courseKey1d.png"/></TD></TR>
        </TABLE>
     >];

    node[shape=oval style=filled, fontname="Helvetica", colorscheme=greens3, color=1];

    c3[color=3, peripheries=2];
    c4[color=3, peripheries=2];

    c1->c2[dir=both];
    c2->c3;

    c4_reqs[style="dashed", color="black", shape="diamond", label="OR"];
    c4_reqs->c4;
    c2->c4_reqs[style="dashed", dir="none"];
    c5->c4_reqs[style="dashed", dir="none"];

    lots -> more -> of -> this -> that -> and -> the -> other
  }
}

Produced this: enter image description here

Counterblow answered 7/7, 2020 at 21:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.