Center a node above a group of other nodes

I’m trying to create a “title” type node and center it above all the other nodes. So far I’ve been unable to do so. Everything I try seems to not center it where I want it, or it messes with the edges of the other nodes. I’ll put my current implementation and what it looks like below:

digraph {
	rankdir=LR ranksep=.25
	100 [label=CBADAABDRRBN fontsize=30 shape=box]
	0 [label="(" color=green style=filled]
	1 [label="(" color=green style=filled]
	2 [label=A color=green style=filled]
	3 [label="*" color=green style=filled]
	4 [label=B color=green style=filled]
	5 [label="|"]
	6 [label=A color=green style=filled]
	7 [label=C]
	8 [label=")"]
	9 [label=D]
	10 [label=")"]
	11 [label=""]
	0 -> 1 [style=invis weight=10]
	1 -> 2 [style=invis weight=10]
	2 -> 3 [style=invis weight=10]
	3 -> 4 [style=invis weight=10]
	4 -> 5 [style=invis weight=10]
	5 -> 6 [style=invis weight=10]
	6 -> 7 [style=invis weight=10]
	7 -> 8 [style=invis weight=10]
	8 -> 9 [style=invis weight=10]
	9 -> 10 [style=invis weight=10]
	10 -> 11 [style=invis weight=10]
	2:e -> 3:w [color=black weight=10]
	4:e -> 5:w [color=black weight=10]
	6:e -> 7:w [color=black weight=10]
	7:e -> 8:w [color=black weight=10]
	9:e -> 10:w [color=black weight=10]
	0:e -> 1:w [arrowsize=1.33 color=red style=bold weight=10]
	1:e -> 2:w [arrowsize=1.33 color=red style=bold weight=10]
	3:e -> 4:w [arrowsize=1.33 color=red style=bold weight=10]
	8:e -> 9:w [color=red weight=10]
	10:e -> 11:w [color=red weight=10]
	2:ne -> 3:nw [arrowsize=1.33 color=red style=bold]
	3:sw -> 2:se [arrowsize=1.33 color=red style=bold]
	1 -> 6 [arrowsize=1.33 color=red style=bold]
	5 -> 8 [color=red]
}

Is this what you want?

  1. Make the label a graph attribute (not a node attribute) (label | Graphviz)
  2. Use the labelloc attribute to position it at the top
digraph {
rankdir=LR ranksep=.25
graph [label=CBADAABDRRBN fontsize=30 labelloc=t]
0 [label="(" color=green style=filled]
1 [label="(" color=green style=filled]
2 [label=A color=green style=filled]
3 [label="*" color=green style=filled]
4 [label=B color=green style=filled]
5 [label="|"]
6 [label=A color=green style=filled]
7 [label=C]
8 [label=")"]
9 [label=D]
10 [label=")"]
11 [label=""]
0 -> 1 [style=invis weight=10]
1 -> 2 [style=invis weight=10]
2 -> 3 [style=invis weight=10]
3 -> 4 [style=invis weight=10]
4 -> 5 [style=invis weight=10]
5 -> 6 [style=invis weight=10]
6 -> 7 [style=invis weight=10]
7 -> 8 [style=invis weight=10]
8 -> 9 [style=invis weight=10]
9 -> 10 [style=invis weight=10]
10 -> 11 [style=invis weight=10]
2:e -> 3:w [color=black weight=10]
4:e -> 5:w [color=black weight=10]
6:e -> 7:w [color=black weight=10]
7:e -> 8:w [color=black weight=10]
9:e -> 10:w [color=black weight=10]
0:e -> 1:w [arrowsize=1.33 color=red style=bold weight=10]
1:e -> 2:w [arrowsize=1.33 color=red style=bold weight=10]
3:e -> 4:w [arrowsize=1.33 color=red style=bold weight=10]
8:e -> 9:w [color=red weight=10]
10:e -> 11:w [color=red weight=10]
2:ne -> 3:nw [arrowsize=1.33 color=red style=bold]
3:sw -> 2:se [arrowsize=1.33 color=red style=bold]
1 -> 6 [arrowsize=1.33 color=red style=bold]
5 -> 8 [color=red]
}

Giving:

Hi Steve, thanks for the response! And apologies, I think I jumped the gun a bit in making this post. I think I need to work at the node level and not at the graph level because I want to put multiple nodes at this top level. I’ll show what I mean below:

I’d like to have the Current Letter node and the node it’s pointing at centered above the other nodes. Additionally, if possible I want to stop them from elongating the edges of the other nodes.

Again sorry about the misunderstanding, my question was poorly-formed.

digraph {
	rankdir=LR ranksep=.25
	text [label="{<f0> |<f1>A|<f2>A|<f3>B|<f4>D}" fontsize=30 shape=record]
	pointer [label="Current Letter" fontsize=30]
	pointer -> text:f0:n
	0 [label="(" color=green style=filled]
	1 [label="(" color=green style=filled]
	2 [label=A color=green style=filled]
	3 [label="*" color=green style=filled]
	4 [label=B color=green style=filled]
	5 [label="|"]
	6 [label=A color=green style=filled]
	7 [label=C]
	8 [label=")"]
	9 [label=D]
	10 [label=")"]
	11 [label=""]
	0 -> 1 [style=invis weight=10]
	1 -> 2 [style=invis weight=10]
	2 -> 3 [style=invis weight=10]
	3 -> 4 [style=invis weight=10]
	4 -> 5 [style=invis weight=10]
	5 -> 6 [style=invis weight=10]
	6 -> 7 [style=invis weight=10]
	7 -> 8 [style=invis weight=10]
	8 -> 9 [style=invis weight=10]
	9 -> 10 [style=invis weight=10]
	10 -> 11 [style=invis weight=10]
	2:e -> 3:w [color=black weight=10]
	4:e -> 5:w [color=black weight=10]
	6:e -> 7:w [color=black weight=10]
	7:e -> 8:w [color=black weight=10]
	9:e -> 10:w [color=black weight=10]
	0:e -> 1:w [arrowsize=1.33 color=red style=bold weight=10]
	1:e -> 2:w [arrowsize=1.33 color=red style=bold weight=10]
	3:e -> 4:w [arrowsize=1.33 color=red style=bold weight=10]
	8:e -> 9:w [color=red weight=10]
	10:e -> 11:w [color=red weight=10]
	2:ne -> 3:nw [arrowsize=1.33 color=red style=bold]
	3:sw -> 2:se [arrowsize=1.33 color=red style=bold]
	1 -> 6 [arrowsize=1.33 color=red style=bold]
	5 -> 8 [color=red]
}

My monthly PSA: the forum supports code blocks with Graphviz syntax highlighting:

```dot
digraph {
  like -> so[with="a label"];
}
```

which produces:

digraph {
  like -> so[with="a label"];
}
1 Like

Thanks, edited to include that!

The uneven placement of nodes is a side-effect of rankdir=LR. That is easy to fix.
Here are two “close” solutions:
Here we had to go to HTML because same-rank edges to-from records are broken.

// fix irregular node positions by changing rankdir to TB
//  rankdir=LR ranksep=.25
{
  rank=source // position pseudo-title on top
  // change text to HTML-style record
  text [ fontsize=30 shape=plain label=<
  <table border="0" cellborder="1" cellspacing="0">
  <tr>
  <td port="p1"> </td>
  <td port="p2">A</td>
  <td port="p3">A</td>
  <td port="p4">B</td>
  <td port="p5">D</td>
  </tr></table>>]

  pointer [label="Current Letter" fontsize=30]
  pointer -> text:p3:n
  // left-right positiong via invisible "dummy" nodes
  // tacky, but it works
  node [style=invis]
  dummy1->dummy2->pointer [style=invis]
}
{
  rank=sink // position rest of graph on bottom
0 [label="(" color=green style=filled]
1 [label="(" color=green style=filled]
2 [label=A color=green style=filled]
3 [label="*" color=green style=filled]
4 [label=B color=green style=filled]
5 [label="|"]
6 [label=A color=green style=filled]
7 [label=C]
8 [label=")"]
9 [label=D]
10 [label=")"]
11 [label=""]
}
0 -> 1 [style=invis weight=10]
1 -> 2 [style=invis weight=10]
2 -> 3 [style=invis weight=10]
3 -> 4 [style=invis weight=10]
4 -> 5 [style=invis weight=10]
5 -> 6 [style=invis weight=10]
6 -> 7 [style=invis weight=10]
7 -> 8 [style=invis weight=10]
8 -> 9 [style=invis weight=10]
9 -> 10 [style=invis weight=10]
10 -> 11 [style=invis weight=10]
2:e -> 3:w [color=black weight=10]
4:e -> 5:w [color=black weight=10]
6:e -> 7:w [color=black weight=10]
7:e -> 8:w [color=black weight=10]
9:e -> 10:w [color=black weight=10]
0:e -> 1:w [arrowsize=1.33 color=red style=bold weight=10]
1:e -> 2:w [arrowsize=1.33 color=red style=bold weight=10]
3:e -> 4:w [arrowsize=1.33 color=red style=bold weight=10]
8:e -> 9:w [color=red weight=10]
10:e -> 11:w [color=red weight=10]
2:ne -> 3:nw [arrowsize=1.33 color=red style=bold]
3:sw -> 2:se [arrowsize=1.33 color=red style=bold]
1 -> 6 [arrowsize=1.33 color=red style=bold]
5 -> 8 [color=red]
}

Giving :

And this - replaces the arrow edge with a colored indicator. Easier to automate, guaranteed to center the label.:

digraph {
  //rankdir=LR
  ranksep=.25
  
  graph [labelloc=t fontsize=22 shape=plain label=<
  <table border="0" cellborder="1" cellspacing="0">
  <tr>
  <td colspan="5"><FONT POINT-SIZE="16">Current Letter</FONT></td>
  </tr>
  <tr>
  <td port="p1"> &nbsp;</td>
  <td port="p2">A</td>
  <td port="p3" bgcolor="orange">A</td>
  <td port="p4">B</td>
  <td port="p5">D</td>
  </tr></table>>]


{rank=sink
0 [label="(" color=green style=filled]
1 [label="(" color=green style=filled]
2 [label=A color=green style=filled]
3 [label="*" color=green style=filled]
4 [label=B color=green style=filled]
5 [label="|"]
6 [label=A color=green style=filled]
7 [label=C]
8 [label=")"]
9 [label=D]
10 [label=")"]
11 [label=""]
}
0 -> 1 [style=invis weight=10]
1 -> 2 [style=invis weight=10]
2 -> 3 [style=invis weight=10]
3 -> 4 [style=invis weight=10]
4 -> 5 [style=invis weight=10]
5 -> 6 [style=invis weight=10]
6 -> 7 [style=invis weight=10]
7 -> 8 [style=invis weight=10]
8 -> 9 [style=invis weight=10]
9 -> 10 [style=invis weight=10]
10 -> 11 [style=invis weight=10]
2:e -> 3:w [color=black weight=10]
4:e -> 5:w [color=black weight=10]
6:e -> 7:w [color=black weight=10]
7:e -> 8:w [color=black weight=10]
9:e -> 10:w [color=black weight=10]
0:e -> 1:w [arrowsize=1.33 color=red style=bold weight=10]
1:e -> 2:w [arrowsize=1.33 color=red style=bold weight=10]
3:e -> 4:w [arrowsize=1.33 color=red style=bold weight=10]
8:e -> 9:w [color=red weight=10]
10:e -> 11:w [color=red weight=10]
2:ne -> 3:nw [arrowsize=1.33 color=red style=bold]
3:sw -> 2:se [arrowsize=1.33 color=red style=bold]
1 -> 6 [arrowsize=1.33 color=red style=bold]
5 -> 8 [color=red]
}

Giving:

1 Like

Perfect, this is exactly what I wanted but I didn’t believe it was possible to actually implement in GraphViz. Thanks so much!

Out of curiosity, which did you like?

The second version that used highlighting. If you want to see the animated version, I just made it public here: GitHub - aydinschwa/Regex-Engine: Educational, animated regular expression engine

Again, thanks so much for your help. I couldn’t have done it without you!

Excellent! By the way, here is another take on Graphviz-based videos: Stupid Dot Tricks #2 - Making a video

1 Like