34

I have tried using xlp and also followed this graphviz thread (http://www.graphviz.org/content/how-use-xlp-attribute-positioning-external-labels-xlabel), but neither have actually worked.

This is my dot code:

digraph {
    forcelabels=true;
    rankdir=LR;
    graph[ranksep=1,nodesep=.5];
    node[shape=box];
    "start" [xlabel="start",xlp="0,0",shape=doublecircle,label=" "];
    "requested"->"fault";
    "requested"->"progress";
    "start"->"requested";
    "progress"->"fault";
    "progress"->"progress";
    "progress"->"complete";
    "fault" [xlabel="fault",shape=doublecircle,label=" "];
    "complete" [xlabel="complete",shape=doublecircle,label=" "];
}

And this is what it looks like: enter image description here

Ideally start,fault, and complete would just be directly under the nodes, but I can't seem to postion the xlabels correctly.

Kir Chou
  • 2,980
  • 1
  • 36
  • 48
user1634494
  • 609
  • 1
  • 7
  • 23
  • I have the exact same problem, I also want to position labels under the nodes but there seems to be no tutorial or anything on how to do it. – Charl Meyers Mar 02 '16 at 07:37
  • I tried xlabels, but their positioning seems to be broken – Nick Roz Jul 14 '16 at 09:14
  • I've been looking at the data generated by dot - and changing the xlp information doesn't seem to do anything cf. http://www.graphviz.org/content/how-use-xlp-attribute-positioning-external-labels-xlabel Likewise with changing the actual pos values. – d-cubed Nov 22 '16 at 18:00
  • 1
    I realise this comment is late to the party (and things may have changed) but in [the docs](https://graphviz.gitlab.io/_pages/doc/info/attrs.html) it states in the table of attributes: `xlp NE point write only`. Then above that table it states: "_write only_ indicates that the attribute is used for output, and is not used or read by any of the layout programs" which explains why setting it doesn't do anything. – Samuel Harmer Aug 29 '18 at 17:09

3 Answers3

15

If you use neato with the -n2 flag, you should be able to set the position of xlabel. You would need to specify the position of every node, though.

So if you had a file called lb.gv with the following contents:

digraph{
    forcelabels=true;
    rankdir=LR;
    graph[ranksep=1,nodesep=.5,margin=0.3,bgcolor=Transparent];

    node[shape=box];
    start [pos="0,0", xlp="23,54", xlabel=start, shape=doublecircle, label= " "];
    requested [pos="100,0"];
    progress [pos="250,-66"];
    fault [pos="400,70", xlp="424,124", xlabel=fault, shape=doublecircle,label= " "];
    complete [pos="400,-66", xlp="424,-10", xlabel=complete, shape=doublecircle,label= " "];
    requested->fault;
    requested->progress;
    start->requested;
    progress->fault;
    progress:w->progress:_;
    progress->complete;
}

You could run neato -n2 -Tpng lb.gv > test.png

That's what I got:

graphviz

Ivan Chaer
  • 6,980
  • 1
  • 38
  • 48
  • 14
    Note: this *forces* you to place everything explicitly, which is a pain, and half defeats the purpose of graphviz. – Ciro Santilli OurBigBook.com Dec 27 '16 at 10:16
  • @CiroSantilli烏坎事件2016六四事件法轮功 That's a bummer indeed. That's why there is an open feature request ticket for it: http://www.graphviz.org/mantisbt/view.php?id=2410 – Ivan Chaer Dec 27 '16 at 10:53
  • I face the same problem, it seems that the feature to avoid to place everything explicitly is still not available ? – Kumpelka Feb 19 '18 at 15:57
  • 2
    @IvanChaer the feature request is now https://gitlab.com/graphviz/graphviz/issues/299 and https://gitlab.com/graphviz/graphviz/issues/68 – mtd Aug 24 '18 at 13:33
2

Not exactly what you are asking, but you could try something like:

digraph nodes_as_labels {
    rankdir=LR;
    graph[ranksep=1,nodesep=.5];
    node[shape=box];

    "start" [xlp="0,0",shape=doublecircle,label=" "];
    "fault" [shape=doublecircle,label=" "];
    "complete" [shape=doublecircle,label=" "];
    "startlabel" [label="start",penwidth="0"];
    "faultlabel" [label="fault",penwidth="0"];
    "completelabel" [label="complete",penwidth="0"];

    "startlabel" -> "start"[style="invis"];
    "requested"->"fault";
    "requested"->"progress";
    "start"->"requested";
    "progress"->"fault";
    "progress"->"progress";
    "progress"->"complete";
    "fault" -> "faultlabel"[style="invis"];
    "complete" -> "completelabel"[style="invis"];
}

This results in:

gv converted to png

This approach is more relevant when you are using the neato or fdp layout engine, because then you can use the len attribute to set the distance between the nodes that act as label and the nodes you are labeling. This way you can prevent the labels from overlapping edges. Unfortunately, the len attribute does not work for the dot layout engine that the example is using, which is why the labels in the result are far away from the nodes they are labeling.

toongeorges
  • 1,844
  • 17
  • 14
2
  • Use newlines in label string to drop text below node
  • set fixedsize=true to keep node size to default
  • add cluster to keep lowest labels from being truncated
digraph {
    rankdir=LR;
    graph[ranksep=1,nodesep=.5];
    //  add a cluster to provide "margin" for labels below nodes
    subgraph cluster_space {
      graph [peripheries=0]
      node[shape=box];
      // dot ignores xlp
      // add newlines to shift label down
      // fixedsize=true to keep node sized correctly
      "start" [label="\n\n\n\nstart" shape=doublecircle fixedsize=true ];
      "requested"
      "progress"
      "complete" [label="\n\n\n\ncomplete" shape=doublecircle fixedsize=true]
      "fault" [label="\n\n\n\nfault" shape=doublecircle fixedsize=true]

      "requested"->"fault";
      "requested"->"progress";
      "start"->"requested";
      "progress"->"fault";
      "progress"->"progress";
      "progress"->"complete";
    }
}

Giving:
enter image description here

sroush
  • 5,375
  • 2
  • 5
  • 11