I am receiving this error:
>neato house.dot -Tgif -o house2.gif -Tdot -o x.dot
neato: failure to create cairo surface: out of memory
>neato -V
neato - graphviz version 2.28.0 (20110507.0327)
I have lots of memory - about 5Gigs free
Here is house.dot
graph g {
node [shape=box]
north [ pos = "286.0,370.0!" ];
Vestibulo -- Escalera
Sala -- Vestibulo
Comedor -- Sala
CocServ -- Comedor
DormP -- BanoP
DormH -- Bano
Sala -- Bano
Sala -- DormP
CocServ -- north
}
If I unpin the 'north' node then neato completes without error - but North is not located where I want it.
I have upgraded to graphviz version 2.30.1 - still the same problem
dot -Tsvg 99winsert.gv -v > out.svg
you can try transform to svg not png, then you can browse it from Chrome or transform svg to png. it won`t failed since too much memory allocated.
failure to create cairo surface: out of memory
The work around is to use smaller values for the pinned locations.
Like this:
graph g {
node [shape=box]
north [ pos = "1.0,10.0!" ];
south [ pos = "1.0,-10.0!" ];
east [ pos = "-10.0,0.0!" ];
west [ pos = "10.0,0.0!" ];
Vestibulo -- Escalera
Sala -- Vestibulo
Comedor -- Sala
CocServ -- Comedor
DormP -- BanoP
DormH -- Bano
Sala -- Bano
Sala -- DormP
CocServ -- north
}
Which produces this
Related
I want to programmatically draw graphs (preferably using dot, gvpack and neato). I can generate the graph structure using a library, then write a file containing the graph described with dot, and then pack all graphs in the same file. Each graph has a label that acts as a title for it, which contains essential information and cannot be omitted. Unfortunately, the label is sometimes too wide.
Now, the result is as I expected. However, I would like the bounding boxes of the individual graphs to be larger in order for them to fit the entirety of the "title". Then, I would like the graphs to be arranged in such a way that not even the bounding boxes overlap.
But I don't know how to tell dot, gvpack and/or neato to use a bounding box large enough to fit each individual graph while disallowing overlap.
Can this be done? If so, how? Thank you!
MWE
These are the only two trees of 4 vertices in the image above.
File tree_04_00.raw:
graph {
layout = neato
subgraph cluster_0 {
label = "idx= 0, centre=(0,1), centroid= (0,1)";
nd_0 [label= "0"];
nd_1 [label= "1"];
nd_2 [label= "2"];
nd_3 [label= "3"];
nd_0 -- nd_1;
nd_0 -- nd_3;
nd_1 -- nd_2;
}
}
File tree_04_01.raw:
graph {
layout = neato
subgraph cluster_1 {
label = "idx= 1, centre=(0), centroid= (0)";
nd_4 [label= "0"];
nd_5 [label= "1"];
nd_6 [label= "2"];
nd_7 [label= "3"];
nd_4 -- nd_5;
nd_4 -- nd_6;
nd_4 -- nd_7;
}
}
To actually make the image above, I execute the following commands:
# dot for each .raw file
$ dot -Tdot tree_04_00.raw > tree_04_00.dot
$ dot -Tdot tree_04_01.raw > tree_04_01.dot
# now pack all the graphs
$ gvpack -array_it20 tree_04_*.dot > trees_04.dot
# now run neato
$ neato -n2 -Tsvg trees_04.dot > trees_04.svg
The result of the last command is shown in the image above.
Software
I'm using
neato - graphviz version 2.43.0 (0)
dot - graphviz version 2.43.0 (0)
gvpack (unknown version)
gvpr version 2.43.0 (0)
neato has problems with clusters.
Old (pre 2..43.0?) versions did not "do" clusters at all(?), and the current version incorrectly handles cluster labels (the problem you have encountered).
Below is a gvpr (http://www.graphviz.org/pdf/gvpr.1.pdf) program that takes the output from any of the layout engines in dot/xdot format i.e. with pos values (positions calculated), and
wraps the result in two nested clusters (Two nested clusters make for better padding)
moves any graph labels to the inner cluster
moves "top-level" graphs, nodes, and edges to the inner cluster
adjusts node labels to prevent "label modification" if gvpack will be used downstream
sets bb values for both nested clusters
neato will do better with these clusters because neato -n/n2
The gvpr program ( clusterWrap.gvpr):
//
// creates clusters around the entire graph, allowing user to save graph label
// also "fixes" node labels by instantiating default values (\N -> actual node name)
//
BEGIN{
graph_t aGraph, Root, innerCluster, outerCluster;
node_t aNode;
edge_t anEdge;
int i, cnt, topNode[], topSubgraph[], topEdge[];
float delta=8., deltaX, deltaY;
string st;
string copyAtt[int];
/////////////////////////////////////////////////////////////////////////////
split("label|lheight|lwidth|lp|bb", copyAtt, "|");
// deltaX=delta;
// deltaY=delta;
}
BEG_G{
Root=$G;
// get graphs, nodes, and edges(?) directly "under" Root graph
for (aNode=fstnode($G);aNode;aNode = nxtnode(aNode)){
topNode[aNode]=1;
}
for (aGraph = fstsubg($G); aGraph; aGraph = nxtsubg(aGraph)) {
topSubgraph[aGraph]=1;
}
// we will find top-level edges later
// create wrapper clusters
outerCluster=subg(Root,"clusterPad000");
innerCluster=subg(outerCluster,"clusterWrapper000");
if (hasAttr(Root, "layout")){
Root.layout="neato"; // other values (including "") cause problems with later execution
}
//Root.OLDbb=Root.bb;
// "move" attribute values to new cluster
for (copyAtt[i]){
if (hasAttr(Root, copyAtt[i])){
st=aget(Root, copyAtt[i]);
aset(innerCluster, copyAtt[i], st);
aset(Root, copyAtt[i], "");
}
}
innerCluster.peripheries=0;
// create a pad/margin between the two new clusters
outerCluster.bb=(string)((float)xOf(llOf(innerCluster.bb))-delta) + "," +
(string)((float)yOf(llOf(innerCluster.bb))-delta) + "," +
(string)((float)xOf(urOf(innerCluster.bb))+delta) + "," +
(string)((float)yOf(urOf(innerCluster.bb))+delta);
}
N{
$.OLDpos=$.pos;
// "fix" node labels by creating explicit label
if (hasAttr($, "label") && ($.label!="")){
print("// starting label: ", $.label);
$.label=gsub($.label, "\\\\N", $.name); // ugh, backslashes
$.label=gsub($.label, "\\\\G", $G.name); // ugh, backslashes
}else{
print("// starting label: >", $.label,"<");
$.label=$.name;
}
}
E{
// find all edges defined directly under Root
if (isSubedge(Root, $)){
topEdge[$]=1;
}
}
END_G{
// now move graphs, nodes, and edges "under" inner cluster
for (topSubgraph[aGraph]){
print("// cloning subg :", aGraph.name);
clone(innerCluster, aGraph);
delete(Root, aGraph);
}
for (topNode[aNode]){
print("// moving node :", aNode.name);
subnode(innerCluster, aNode);
}
for (topEdge[anEdge]){
print("// moving edge :", anEdge.name);
subedge(innerCluster, anEdge);
}
}
One modified input file with cluster reference removed:
graph {
layout = neato
//subgraph cluster_0 {
label = "idx= 0, centre=(0,1), centroid= (0,1)";
nd_0 [label= "0"];
nd_1 [label= "1"];
nd_2 [label= "2"];
nd_3 [label= "3"];
nd_0 -- nd_1;
nd_0 -- nd_3;
nd_1 -- nd_2;
//}
}
A modified version of your command stream to show gvpr usage:
# dot for each .raw file
$ dot -Tdot tree_04_00.raw |gvpr -cf clusterWrap.gvpr > tree_04_00.dot
$ dot -Tdot tree_04_01.raw |gvpr -cf clusterWrap.gvpr > tree_04_01.dot
# now pack all the graphs
$ gvpack -array_it20 tree_04_*.dot > trees_04.dot
# now run neato
$ neato -n2 -Tsvg trees_04.dot > trees_04.svg
Giving:
I am using fruchterman_reingold_force_directed_layout algorithm on my graph
to get a cluster free layout. Below is code for my vertices and edge
using RectTopology = boost::rectangle_topology<>;
using point = RectTopology::point_type;
class MyVertex{
public:
MyVertex(){ myObject = NULL; }
Mybject* myObject;
point position;
std::string name;
};
class MyEdge{
public:
MyEdge(){ myLine = NULL; }
MyLine* myLine;
double weight;
};
//Boost graph defination
using graphT = boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, MyVertex, MyEdge>;
using vertexT = boost::graph_traits<graphT>::vertex_descriptor; //Define Vertex
using vertexIt = boost::graph_traits<graphT>::vertex_iterator; //Vertex Iterator
using edgeT = boost::graph_traits<graphT>::edge_descriptor; //Define Edge
using edgeIt = boost::graph_traits<graphT>::edge_iterator; //Edge Iterator
forcedDirLay(){
boost::minstd_rand gen;
RectTopology rect_top(gen, 0, 0, 1, 1);
boost::random_graph_layout(myGraph, boost::get(&SLDVertex::position, myGraph), rect_top);
boost::fruchterman_reingold_force_directed_layout(myGraph, boost::get(&SLDVertex::position, myGraph), rect_top);
}
Imagine now I have a graph and perform my layout algorithm which all works fine
and I have position info for every vertices.
How can I visualize each vertex where they end up after layout algorithm
finished ? Is there a way to get position info to Dot file and I can visualize
Dot file ?
I have a function to convert my graph to dot file but don't know how
to get position info to dot
file. Thanks in advance.
GraphToDotFile(){
std::ofstream dot(".\\graph.dot");
boost::write_graphviz(dot, myGraph,
boost::make_label_writer(boost::get(&MyVertex::name, myGraph)));
dot.close();
}
You can use dynamic properties to add graphviz attributes, see the example:
https://www.boost.org/doc/libs/1_74_0/libs/graph/example/graphviz.cpp
The attributes that specify the position in graphviz are here:
Position of node, or spline control points.
For nodes, the position indicates the center of the node. On output,
the coordinates are in points.
In neato and fdp, pos can be used to set the initial position of a
node. By default, the coordinates are assumed to be in inches.
However, the -s command line flag can be used to specify different
units. As the output coordinates are in points, feeding the output of
a graph laid out by a Graphviz program into neato or fdp will almost
always require the -s flag.
When the -n command line flag is used with neato, it is assumed the
positions have been set by one of the layout programs, and are
therefore in points. Thus, neato -n can accept input correctly without
requiring a -s flag and, in fact, ignores any such flag.
Valid for: Edges, Nodes.
The neato -n trick works like a champ.
Adding a bit to the above,
yourProg produces graph.dot; then
neato -n -Tpng graph.dot >graph.png
You may have to fiddle with yourProg to make sure that graph.dot has all the required attributes, units are correct, etc. You can produce a tiny example by hand, then
dot -Tdot tiny.gv >tiny.dot
and compare the two .dot files
I am using graphviz twopi to generate a png file. I have many dot files but only three which cannot be converted to png. Below is one simplified example which cannot be converted:
digraph G{
overlap = false;
splines = true;
root = "a";
"a" [label ="ATCC 12633"];
"b" [label = "R M Egan",fontsize=25];
"a" -> "b" [label = "paper:1",penwidth = 4,color = black ,len=2];
"c" [fontsize=25, label = "ATCC 8014"];
"b" -> "c" [label = "paper:1"];
}
I use -v to see the details, which are:
mongodb#mongodb:/home/wuchang/newStore/allYear$ sudo twopi ATCC_12633_1977.dot -Tpng -o 77.png -v
twopi - graphviz version 2.26.3 (20100126.1600)
Activated plugin library: libgvplugin_pango.so.6
Using textlayout: textlayout:cairo
Activated plugin library: libgvplugin_neato_layout.so.6
Using layout: twopi:neato_layout
Using render: cairo:cairo
Using device: png:cairo:cairo
The plugin configuration file:
/usr/lib/graphviz/config6
was successfully loaded.
render : cairo dot fig gd map ps svg tk vml vrml xdot
layout : circo dot fdp neato nop nop1 nop2 osage patchwork sfdp twopi
textlayout : textlayout
device : canon cmap cmapx cmapx_np dot eps fig gd gd2 gif gv imap imap_np ismap jpe jpeg jpg pdf plain plain-ext png ps ps2 svg svgz tk vml vmlz vrml wbmp x11 xdot xlib
loadimage : (lib) eps gd gd2 gif jpe jpeg jpg png ps svg
fontname: "Times-Roman" resolved to: (ps:pango Times Roman,) (PangoCairoFcFont) "DejaVu Sans 14"
root = a
Rank separation = 0.000 1.000 2.000
Adjusting G using Voronoi
Node separation: add=1 (4.000000,4.000000)
I doubt it is just a bug in graphviz. My graphviz version is 2.26.3, my OS is Ubuntu 12.04.3 LTS.
Compared with a successfully-converted dot file whose convertion output is:
mongodb#mongodb:/home/wuchang/newStore/allYear$ sudo twopi ATCC_12633_1988.dot -Tpng -o 88.png -v
twopi - graphviz version 2.26.3 (20100126.1600)
Activated plugin library: libgvplugin_pango.so.6
Using textlayout: textlayout:cairo
Activated plugin library: libgvplugin_neato_layout.so.6
Using layout: twopi:neato_layout
Using render: cairo:cairo
Using device: png:cairo:cairo
The plugin configuration file:
/usr/lib/graphviz/config6
was successfully loaded.
render : cairo dot fig gd map ps svg tk vml vrml xdot
layout : circo dot fdp neato nop nop1 nop2 osage patchwork sfdp twopi
textlayout : textlayout
device : canon cmap cmapx cmapx_np dot eps fig gd gd2 gif gv imap imap_np ismap jpe jpeg jpg pdf plain plain-ext png ps ps2 svg svgz tk vml vmlz vrml wbmp x11 xdot xlib
loadimage : (lib) eps gd gd2 gif jpe jpeg jpg png ps svg
fontname: "Times New Roman Bold" resolved to: (PangoCairoFcFont) "DejaVu Sans Bold 30"
fontname: "Times-Roman" resolved to: (ps:pango Times Roman,) (PangoCairoFcFont) "DejaVu Sans 24.9990234375"
root = -290487096
Rank separation = 0.000 1.000 2.000
Adjusting G using Voronoi
Node separation: add=1 (4.000000,4.000000)
Number of iterations = 5
Number of increases = 3
Edge separation: add=1 (3.200000,3.200000)
Creating edges using splines
Using render: cairo:cairo
Using device: png:cairo:cairo
twopi: allocating a 1477K cairo image surface (907 x 417 pixels)
I tried many many modifications such as:
If I remove overlap=false, it can generate the png file but the
generated graph's node is overlapped, which doesn't meet my
requirement.
When I remove fontsize = 23 for node "c", it also
can generate the png file, but the png file is completely
wrong.
I'd suggest updating to a newer version of Graphviz. There has been a lot of development in the last four years. Because your verbose output ends before the number of iterations is displayed, I strongly suspect it's a bug (maybe an infinite loop) the version of Graphviz you're using.
Using 2.36.0 under OS X, your file gives me this (which is obviously not what you want):
If I comment out the line root = "a"; I get this:
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 ' ' or '\' 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
}
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: