Graphviz: how to rotate a node (or a subgraph)? - rotation

I am trying to have a node (or a subgraph, enclosing a node - whichever is possible/easier) rotated, like shown in this image:
(Note that it doesn't matter to me if the "B" label is rotated - only that the 'verti-*' texts in the record [or rather, the whole record node] are rotated as shown)
However, the closest I can to that, is the following dot code:
digraph graphname {
node [fontname=Monospace, fontsize=14];
subgraph clusterMasterBox {
node [shape=record];
l1 [label = "{ horiz-1 \r| \
horiz-2 \r| \
horiz-3 \r| \
horiz-4 \r} \
"];
subgraph clusterSubRotateBox {
rotate=90;
node [shape=record,rotate=90];
l2 [label = "{ verti-1 \r| \
verti-2 \r| \
verti-3 \r| \
verti-4 \r} \
"];
label="B";
}
label="A"
}
}
The only reason I have the subgraph clusterSubRotateBox there (and the only reason why it is nested inside the clusterMasterBox), is because I hoped I could assign rotation to it, but apparently I cannot - as the above code generates this image:
So my question is - is there a way to rotate a record node; if not on its own, then maybe as a part of subgraph (or a different kind of 'object')?
Thanks in advance for any suggestions,
Cheers!

If you want to rotate a single record based node then rankdir will work. I tried it for my graph,
digraph plugnoid {
rankdir=LR;
node[shape=Mrecord];
plugnoid [label="swarm| {<load0> onLoad|<plugin0> Plugin|<quit0> onQuit}|{<run0>run|<rehash0>rehash}"];}
The rankdir can have values LR,RL and TB(default). When I changed the rankdir to TB the output changed,
You may want to try them on your graph to get desired results. I experienced that when I used subgraph and set different rankdir the result was not as good. Please see http://www.graphviz.org/doc/info/shapes.html#record for more details.

For a single node, there is the orientation attribute. I just used
node[shape=hexagon, orientation=30]
To make a hexagon with a point at the top rather than a flat top.
Unfortunately doesn't seem to work on 'record' types :-(

there should be a "rotation" attribute on the graph object (see http://www.graphviz.org/doc/info/attrs.html#drotation) but it didn't do anything in my test. and, it would only apply to the whole graph (not cluster/subgraph) according to the docs.
i guess you'd first render the subgraph to postscript and then include it in the final graph as a custom shape for a single placeholder node. if you can't get "rotation" to do its thing, surely postscript has a simple way to apply a transform (rotation in this case), probably as simple as prefixing the generated code with some coordinates definition. sorry for the handwaving but i don't have time to try it now.

Graphviz does not support partial rotation - only entire graphs or polygonial nodes (https://www.graphviz.org/docs/attrs/rotate/ and https://graphviz.org/docs/attrs/orientation/).
To accomplish your goal, create a separate graph for each node or cluster you want rotated, and use dot (or desired engine) to create images (png, svg, etc.) Then include each image into an node using the image attribute (https://graphviz.org/docs/attrs/image/).
Note that Graphviz only supports rotate=90, while you are asking for -90. Use some other image manipulation program to rotate the result by 180 (good grief)
of the complete graphLike so:
rotatePart1a.gv
digraph graphname {
node [fontname=Monospace, fontsize=14];
subgraph clusterMasterBox {
label="A"
{rank=same // keep on same rank
l2 [shape=plain label="" image="rotatePart1b.png"]
node [shape=record];
l1 [label = "{ horiz-1 \r| \
horiz-2 \r| \
horiz-3 \r| \
horiz-4 \r} \
"];
}
}
}
rotatePart1b.gv
digraph graphname {
rotate=90;
node [fontname=Monospace, fontsize=14];
subgraph clusterSubRotateBox {
node [shape=record] // rotation at node-level is silently ignored
l2 [label = "{ verti-1 \r| \
verti-2 \r| \
verti-3 \r| \
verti-4 \r} \
"];
label="B";
}
}
Giving:

Related

Can I get graphviz to draw a flowchart-terminal shape?

In flowcharts, one of the "standard" node shapes is that of a terminal:
But this shape does not seem to be directly supported by Graphviz, according to the documentation here. This seems a bit strange to me...
Is there some way to get graphviz to draw this shape, that I'm missing?
Try shape=Mrecord, like so:
digraph D {
A [shape=Mrecord label="Tip Top"];
A -> B
}
Giving:
You can use "rounded style" on your node shapes, e.g.:
digraph G {
node [style="rounded", shape=box]; a;
node [style="" shape=box]; b;
a -> b;
}
produces this:

Problems with designing UML - like diagrams in graphviz

I'm currently having issues with designing UML-like diagrams on graphiz. The reason for the problem is that they are not exactly UML diagrams. The main difference is that I make use of indentations to add an hierarchy to an object's properties. Implementing these idiosyncrasies is a little difficult for me. What I'm trying to achieve is this:
I normally use a node shape called record to design these diagrams. The problem arises when I have to link two of these UML-like diagrams just like relationships in UML i.e. aggregation, association, composition, etc.
When I have the diagrams, I can't make the relationship with the arrows because the arrows only go from a random part of one node to another random part of the other node.
The way I have the UML-like diagrams is good, but the relationship arrow causes it not to be what I want as I want the arrows to go from a specific point of one node to another specific point of another node.
The DOT code I used to create this graph is like this:
digraph G {
fontname = "Bitstream Vera Sans"
fontsize = 8
node [
fontname = "Bitstream Vera Sans"
fontsize = 8
shape = "record"
]
edge [
fontname = "Bitstream Vera Sans"
fontsize = 8
]
Person [
label = "{Person \l\l \ age : int\l \ livesIn : City \l \ \ \ sinceYear : int}"
] // \l -new line, \ -indentation
City [
label = "{City \l \ \ name : string}"
]
Person -> City
}
I tried getting around this problem by using horizontal line divisions within the nodes even though I didn't want the lines. The horizontal line divisions make it possible for me to make this specific relationship possible by using ports, but they create a new problem of their own. The problem they create is that they get rid of the indentations I want and had in the previous graph. The way I tried to get around the arrow problems works, but new problems are created - the indentation disappears and the horizontal line divisions can't be made invisible
.
The code I used to create this graph is:
digraph G {
fontname = "Bitstream Vera Sans"
fontsize = 8
node [
fontname = "Bitstream Vera Sans"
fontsize = 8
shape = "record"
penwidth = 0.5
]
edge [
fontname = "Bitstream Vera Sans"
fontsize = 8
]
Person [
label = "{<g0> Person | <g1> age : int | <g2> livesIn : City | <g3> sinceYear : int}"
] // \l -new line, \ -indentation
City [
label = "{<f0> City | <f1> name : string}"
]
Person:<g2> -> City:<f1> [arrowhead = "empty", headlabel = "*"]
}
These indentations are a big part of the relationship, so I'm wondering if anyone knows what I can do to have these indentations back in the diagrams as well what I can do to make the horizontal line divisions invisible?
I'll appreciate if someone has a better way/idea that's also totally different from what I have done in diagrams 2 & 3, that will help me achieve diagram 1.
Your original attempt wasn't bad. I would say using ports is definitely the way to go.
If you place the node in a cluster you can use the cluster's border and hide the border of the record node, getting rid of those divider lines.
As you noted, using a backslash \ no longer works to escape a space. The workaround is to either use \ instead, this will escape the whitespace. As an alternative you could also replace each space with an &nnbsp;. Either one will achieve the required effect.
I made some minor changes to make things more readable, like put Graph properties in a graph block instead of in the root of the graph and rename the port-names to something more sensible. I also removed any ports not in use.
The final result I came up with was this:
...and this is the DOT code I used:
digraph G {
graph [
compound = true // To clip the head at the cluster border
penwidth = 2 // Make the cluster's borders a bit thicker
rankdir = "LR" // Make the arrow and nodes go from Left to Right
ranksep = 1 // Add a bit more space inbetween nodes
]
node [
color = none // Hide the node's border
fontname = "Bitstream Vera Sans"
height = 0 // Make the node as small as possible (it will grow if it needs more space)
margin = 0 // Remove unneeded whitespace
shape = "record" // So we can use ports
]
edge [
arrowhead = "open"
labelangle = -5 // Place the asteriks closer to the line
labeldistance = 2.5 // Place the asteriks further away from the arrow head
penwidth = 2 // Make the line a bit thicker
]
/* #NOTE: escaping spaces in the label using '\' doesn't work so use '&nbsp' or '&#92' instead. */
subgraph cluster_Person {
Person [
label = "\N\l | \ \ \ age : int\l | <livesIn> \ \ \ livesIn : City\l | \ \ \ \ \ \ sinceYear : int\l"
]
}
subgraph cluster_City {
City [
label = "<city> \N\l | \ \ \ name : string\l"
]
}
Person:livesIn -> City:city [headlabel = "*", lhead = "cluster_City"] // lhead allows us to point to the cluster's border instead of the node, as long as we add `compound = true` to the graph
}

How do I set the Cluster font attributes in Graphviz?

I am able to successfully change the edge font, and the node font, but my attempts to change the cluster labels have no affect. Can someone point me in the right direction?
I have tried labelfontname=, fontname= (on the edge and the node), but can't seem to find the magic formula for cluster labels.
fontname is working for cluster labels.
Here's an example with illustration - it's quite simple, just set it before setting the content of the label.
digraph g{
node[fontname="Impact"];
subgraph cluster0 {
"Cluster node";
fontname="Courier";
label="Cluster label";
}
fontname="Arial";
label="Graph Label";
}
The result:

How do you center a title for a diagram output to SVG using dot?

So far I tried this line but dot keeps pushing it aside making room for my nodes (pushes it to the right):
_diagram_info [shape="plaintext", label="My Diagram\l", fontsize=13]
Is there a way to center the label by pos, using dot?
That's how I'd add a title for a graph:
digraph {
// nodes, edges, subgraphs
...
// title
labelloc="t";
label="My Diagram";
}
This will add a centered title to the top of the graph.
The same syntax can also be used for subgraphs.

record nodes and rankdir in graphviz

When I changed the rankdir of my graph from LR to TD, my record nodes also changed their layout direction so they no longer look like a 'record'. I tried applying a separate rankdir to the nodes, but this had no effect.
How does one keep the record nodes with the correct layout?
digraph sample {
graph [rankdir=TD];
node [shape=record];
A [label="ShouldBeTop | ShouldBeBottom"];
B [label="Top | Bottom"];
A -> B;
}
Taking into account that rankdir effectively replaces the notion of "top" and "bottom" for the given graph, that's not surprising.
I am afraid that there is no easy remedy for this, save hacking the source (and that would not be easy at all). You can surround your labels in "{}" with some kind of mass search-replace solution to get the requested effect:
digraph sample { graph [rankdir=TD]; node [shape=record];
A [label="{ShouldBeTop | ShouldBeBottom}"];
B [label="{Top | Bottom}"]; A -> B;
}
You can use html table like labels instead of records. IIRC the table based labels do not rotate with the rank direction. See http://www.graphviz.org/doc/info/shapes.html#html

Resources