Following the helpful answer of a previous question, there is still an unresolved issue, that the hourglass symbol (i.e. the text in custom node) is not centered, so that vertical edges are not in the middle. I tried also different html-style centering options, but with no success. Any method or a completely different approach would be welcome.
library(DiagrammeR)
graph <- "
digraph logistic_growth {
graph [rankdir = 'LR', bgcolor='none', fontsize=10]
node [shape = circle, fontsize=8, penwidth=0.7, fontname='Open Sans']
r [xlabel=' intrinsic growth rate']
K [xlabel=' carrying capacity']
node [shape = box, penwidth=2]
N [label='Population N']
node [shape = octagon, width='', penwidth=0.5, style='rounded', fixedsize=25]
Source Sink
node [shape=plaintext, width=0.2, height=0.2]
growth [label=<<table cellpadding='0' border='0' cellspacing='0'><tr><td height='10'></td></tr><tr><td><FONT POINT-SIZE='20'>⧖</FONT></td></tr><tr><td>growth</td></tr></table>>]
edge [penwidth=1.5]
Source -> growth [dir = none, color = 'blue' headclip=false]
growth -> N [dir = left, color = 'blue' tailclip=false]
N -> Sink
edge [penwidth=0.7, tailport = 'n', headport = 'n', constraint = false, color=tomato]
N -> growth
edge [penwidth=0.7, tailport = 'e', headport = 'n', constraint = false, color=tomato]
r -> growth
K -> growth
}
"
grViz(graph)
Here is a convoluted but solid solution.
dot input:
digraph logistic_growth {
graph [rankdir = "LR", XXbgcolor="none", fontsize=10]
node [shape = circle, fontsize=8, penwidth=0.7, fontname="Open Sans"]
r [xlabel=" intrinsic growth rate"]
K [xlabel=" carrying capacity"]
node [shape = box, penwidth=2]
N [label="Population N"]
node [shape = octagon, width="", penwidth=0.5, style="rounded", fixedsize=25]
Source Sink
node [shape=plaintext, width=0.2, height=0.2]
growth [label="" xlabel="\N" hourglass=1] // any undefined attribute name
edge [penwidth=1.5]
Source -> growth [dir = none, color = "blue" headclip=false]
growth -> N [dir = left, color = "blue" tailclip=false]
N -> Sink
edge [penwidth=0.7, tailport = "n", headport = "n", constraint = false, color=tomato]
N -> growth:n
edge [penwidth=0.7, tailport = "e", headport = "n", constraint = false, color=tomato]
r -> growth:n
K -> growth:n
}
gvpr program (save as hourglass.gvpr):
BEGIN{
int i;
edge_t hGlass;
string x1, y1, x2, y2, pp1, p2, p3, p4, segment1, segment2, segment3, segment4;
}
N[hourglass=="1"]{
// first, move xlabel
oldXLP=xlp;
xlp=(string)$.X + ","+ (string) yOf($.xlp);
// create a very bogus edge that will become the hourglass figure
// need to convert inches to points then divide by 2 == *72/2 == *36
x1=(string)($.X-(((float)$.width/2)*72));
x2=(string)($.X+(((float)$.width/2)*72));
y1=(string)($.Y-(((float)$.height/2)*72));
y2=(string)($.Y+(((float)$.height/2)*72));
p1=x1 + "," + y1 + " ";
p2=x2 + "," + y1 + " ";
p3=x1 + "," + y2 + " ";
p4=x2 + "," + y2 + " ";
segment1=p1 + p1 + p1 + p2;
segment2=p2 + p2 + p3;
segment3=p3 + p3 + p4;
segment4=p4 + p4 + p1;
hGlass=edge($, $, ""); //$.name + "->" + $.name);
hGlass.pos=segment1 + segment2 + segment3 + segment4;
hGlass.color="black";
}
Finally, the command line (Linux) (Windows can be broken into separate steps)
dot myFile.gv |gvpr -cfhourglass.gvpr |neato -n2 -Tsvg >myFile.svg