I would like to create a figure where the arcs only enter a node on the left hand side, and exit only from the right hand side.
I have created the following dot file, and its picture is shown below:
digraph net {
"C0" [shape=oval label="C0"]
"C1" [shape=oval label="C1"]
"B0" [shape=box label="B0"]
rankdir="LR"
"C0" -> "B0"
"B0" -> "C1"
"C1" -> "B0"
}
But I would like to see the arc C1->B0 as exiting C1 from its right hand side, and curving (or even a rectangular arc) back to the left side of B0. How do I do that?
Use port positions (https://graphviz.org/docs/attr-types/portPos/) to specify tail & head positions.
Note the syntax including/excluding " character. (The "s are not needed for these node names)
digraph net {
"C0" [shape=oval label="C0"]
"C1" [shape=oval label="C1"]
"B0" [shape=box label="B0"]
rankdir="LR"
"C0" -> "B0"
"B0" -> "C1"
"C1":e -> B0:w // note portpos with/without "s. Both work
}
Giving:
I'm using this Python project "Family Tree Maker" to generate a family tree. It works with GraphViz, creates a nice DOT file and then a PNG. "Minimum Viable Product" check. It works :D
Now I'd like to make it a bit nicer.
Is there a simple way (e.g. not having to increase the length of the edge per hand) to force the right-most vertical edge (between Father1-Mother2 and Franz) to be straight/vertical like displayed below?
Thanks!
Edit: as correctly stated by #albert in the comments, webgraphviz.com displays the correct output while viz-js.com doesn't.
PS: Here's the DOT code that generate this Graph:
digraph {
graph [splines=ortho];
node [shape=box, fontname = "calibri"];
edge [dir=none];
Father1[label="Father1",style=filled,fillcolor=azure2];
Mother1[label="Mother1",style=filled,fillcolor=bisque];
Child1[label="Child 1",style=filled,fillcolor=azure2];
Child2[label="Child 2",style=filled,fillcolor=bisque];
Child3[label="Child 3",style=filled,fillcolor=azure2];
Child4[label="Child 4",style=filled,fillcolor=azure2];
Mother2[label="Mother2",style=filled,fillcolor=bisque];
Franz[label="Franz",style=filled,fillcolor=azure2];
{ rank=same;
Mother1 -> h0 -> Father1;
h0[shape=circle,label="",height=0.01,width=0.01];
Father1 -> h1 -> Mother2;
h1[shape=circle,label="",height=0.01,width=0.01];
}
{ rank=same;
h0_0 -> h0_1 -> h0_2 -> h0_3 -> h0_4;
h0_0[shape=circle,label="",height=0.01,width=0.01];
h0_1[shape=circle,label="",height=0.01,width=0.01];
h0_2[shape=circle,label="",height=0.01,width=0.01];
h0_3[shape=circle,label="",height=0.01,width=0.01];
h0_4[shape=circle,label="",height=0.01,width=0.01];
h0_4 -> h1_0 [style=invis];
h1_0;
h1_0[shape=circle,label="",height=0.01,width=0.01];
}
h0 -> h0_2;
h0_0 -> Child1;
h0_1 -> Child2;
h0_3 -> Child3;
h0_4 -> Child4;
h1 -> h1_0;
h1_0 -> Franz;
{ rank=same;
Child1 -> Child2 [style=invis];
Child2 -> Child3 [style=invis];
Child3 -> Child4 [style=invis];
Child4 -> Franz [style=invis];
}
{ rank=same;
}
}
As expected after discussing with #Albert in the comments, using version 2.28 of GraphViz, I get the result I wanted.
I created an issue report on GraphViz's Gitlab: https://gitlab.com/graphviz/graphviz/issues/1627
I'm not really sure how to describe what my client wants, so I'll let a picture do most of the talking. I'm using DOT to produce graphs for what is more or less the bill of materials problem. (Show an incoming lot and all the outgoing lots, at all levels, that were created from the material in the incoming lot.) I've got the code to create a graph that contains the data structured appropriately. For example, I generate this GV file:
digraph LotTrc {
rankdir=LR;
graph[label="Lot #AD626", labelloc=top, labeljust=left, fontsize=24];
PO_AD626_0000003333[shape=triangle,color=greenyellow,style=filled,label=AD626];
AJ_AD626_SJ00000099[shape=circle,color=red2,style=filled,label=AD626];
PO_AD626_0000003333 -> AJ_AD626_SJ00000099;
AJ_AD626_SJ00000103[shape=circle,color=red2,style=filled,label=AD626];
PO_AD626_0000003333 -> AJ_AD626_SJ00000103;
WO_AD627_RE00002230[shape=ellipse,color=lemonchiffon,style=filled,label=AD627];
PO_AD626_0000003333 -> WO_AD627_RE00002230;
SO_AD627_OZ00025429[shape=box,color=cyan3,style=filled,label=AD627];
WO_AD627_RE00002230 -> SO_AD627_OZ00025429;
SO_AD627_OZ00025434[shape=box,color=cyan3,style=filled,label=AD627];
WO_AD627_RE00002230 -> SO_AD627_OZ00025434;
SO_AD627_OZ00025439[shape=box,color=cyan3,style=filled,label=AD627];
WO_AD627_RE00002230 -> SO_AD627_OZ00025439;
SO_AD627_OZ00025444[shape=box,color=cyan3,style=filled,label=AD627];
WO_AD627_RE00002230 -> SO_AD627_OZ00025444;
WO_AD628_RE00002231[shape=ellipse,color=lemonchiffon,style=filled,label=AD628];
PO_AD626_0000003333 -> WO_AD628_RE00002231;
SO_AD628_OZ00025430[shape=box,color=cyan3,style=filled,label=AD628];
WO_AD628_RE00002231 -> SO_AD628_OZ00025430;
SO_AD628_OZ00025435[shape=box,color=cyan3,style=filled,label=AD628];
WO_AD628_RE00002231 -> SO_AD628_OZ00025435;
SO_AD628_OZ00025440[shape=box,color=cyan3,style=filled,label=AD628];
WO_AD628_RE00002231 -> SO_AD628_OZ00025440;
SO_AD628_OZ00025445[shape=box,color=cyan3,style=filled,label=AD628];
WO_AD628_RE00002231 -> SO_AD628_OZ00025445;
WO_AD629_RE00002232[shape=ellipse,color=lemonchiffon,style=filled,label=AD629];
PO_AD626_0000003333 -> WO_AD629_RE00002232;
SO_AD629_OZ00025431[shape=box,color=cyan3,style=filled,label=AD629];
WO_AD629_RE00002232 -> SO_AD629_OZ00025431;
SO_AD629_OZ00025436[shape=box,color=cyan3,style=filled,label=AD629];
WO_AD629_RE00002232 -> SO_AD629_OZ00025436;
SO_AD629_OZ00025441[shape=box,color=cyan3,style=filled,label=AD629];
WO_AD629_RE00002232 -> SO_AD629_OZ00025441;
SO_AD629_OZ00025446[shape=box,color=cyan3,style=filled,label=AD629];
WO_AD629_RE00002232 -> SO_AD629_OZ00025446;
WO_AD630_RE00002233[shape=ellipse,color=lemonchiffon,style=filled,label=AD630];
PO_AD626_0000003333 -> WO_AD630_RE00002233;
SO_AD630_OZ00025432[shape=box,color=cyan3,style=filled,label=AD630];
WO_AD630_RE00002233 -> SO_AD630_OZ00025432;
SO_AD630_OZ00025437[shape=box,color=cyan3,style=filled,label=AD630];
WO_AD630_RE00002233 -> SO_AD630_OZ00025437;
SO_AD630_OZ00025442[shape=box,color=cyan3,style=filled,label=AD630];
WO_AD630_RE00002233 -> SO_AD630_OZ00025442;
SO_AD630_OZ00025447[shape=box,color=cyan3,style=filled,label=AD630];
WO_AD630_RE00002233 -> SO_AD630_OZ00025447;
WO_AD631_RE00002234[shape=ellipse,color=lemonchiffon,style=filled,label=AD631];
PO_AD626_0000003333 -> WO_AD631_RE00002234;
SO_AD631_OZ00025433[shape=box,color=cyan3,style=filled,label=AD631];
WO_AD631_RE00002234 -> SO_AD631_OZ00025433;
SO_AD631_OZ00025438[shape=box,color=cyan3,style=filled,label=AD631];
WO_AD631_RE00002234 -> SO_AD631_OZ00025438;
SO_AD631_OZ00025443[shape=box,color=cyan3,style=filled,label=AD631];
WO_AD631_RE00002234 -> SO_AD631_OZ00025443;
SO_AD631_OZ00025448[shape=box,color=cyan3,style=filled,label=AD631];
WO_AD631_RE00002234 -> SO_AD631_OZ00025448;
}
and it produces this graph:
But what my client really wants is something that looks more like this, where the edges are straight lines, using 90 degree angles as needed. (Note that this is generic, not based on the example above.)
Is there a way to use DOT to produce something like that?
You can experiment with splines=ortho graph attibute. It makes the very straight connections with 90 degree angles.
But I won't recommend it. It's almost impossible to control them, port specification often doesn't work with them, and also, ortho splines may eat up some of the edge lables.
Possible solution would be using dummy nodes with point shape (this shape is convenient because it removes node lable by default) and width=0. Use these dummy nodes in places where the 90 degree turn is needed. You will have to group them with main nodes in subgraphs and add rank=same attribute to force these nodes to stay at the same level.
You would probably also need to add weight to some edges to prevent them from being bent (edges with higher weight tend to be straight).
Example
I've implemented part of your example graph using mentioned techniques, the code and image are below:
digraph {
rankdir=LR
ranksep=1
nodesep=0.5
LOT1 [shape=rect]
LOT2 [shape=rect]
LOT3 [shape=rect]
LOT4 [shape=rect]
LOT5 [shape=rect]
{rank=same
PO
dot1 [shape=point width=0]
dot2 [shape=point width=0]
PO -> dot1 -> dot2 [arrowhead=none]
}
dot1 -> WO1 [weight=20]
{
rank=same
WO1
dot21 [shape=point width=0]
dot22 [shape=point width=0]
WO1 -> dot21 -> dot22 [arrowhead=none]
}
dot21 -> LOT1 [weight=20]
dot22 -> LOT2 [weight=20]
{
rank=same
dot31 [shape=point width=0]
dot32 [shape=point width=0]
dot33 [shape=point width=0]
dot31 -> dot32 -> dot33 [arrowhead=none]
}
dot2 -> WO2 [weight=20]
{
WO2
rank=same
dot23 [shape=point width=0]
dot24 [shape=point width=0]
dot25 [shape=point width=0]
WO2 -> dot23 -> dot24 -> dot25 [arrowhead=none]
}
dot23 -> LOT3 [weight=20]
dot24 -> LOT4 [weight=20]
dot25 -> LOT5 [weight=20]
dot31 -> SO1
dot33 -> SO2
LOT1 -> dot32
}
Result:
I have a graph that represents one large process made up of two smaller processes. Each of the smaller processes is represented by a subgraph. But when I connect the end of one of those subprocesses (let's say "one") to the start of the other ("two"), the starting shape for the other process ("two") ends up in the same cluster as the ending of "one". How can I get the arrow from the end of one to point to the start of two, but keep the starting shape of two within its cluster?
digraph BigProcess {
graph [ label="Some big process" ]
subgraph clusterSubProcess1 {
graph [ label="Subprocess one", color="red" ]
start1_1 -> start1_2;
start1_2 -> start1_3a;
start1_2 -> start1_3b;
start1_3a -> start1_4;
start1_3b -> start1_5;
start1_4 -> start1_1;
start1_5 -> start2_1;
}
subgraph clusterSubProcess2 {
graph [ label="Subprocess two", color="blue" ]
start2_1 -> start2_2;
start2_2 -> start2_3a;
start2_2 -> start2_3b;
start2_3a -> start2_4;
start2_3b -> start2_5;
start2_4 -> start2_1;
start2_5 -> end1;
}
}
This results in the following, where I really want start2_1 to be the top node within the blue bounded box.
That's happening because the line start1_5 -> start2_1; in the first subgraph is defining start2_1 in that subgraph. You need to define start1_5 in the first subgraph but leave it unconnected until after you define start2_1 in the second subgraph.
digraph BigProcess {
graph [ label="Some big process" ]
subgraph clusterSubProcess1 {
graph [ label="Subprocess one", color="red" ]
start1_1 -> start1_2;
start1_2 -> start1_3a;
start1_2 -> start1_3b;
start1_3a -> start1_4;
start1_3b -> start1_5;
start1_4 -> start1_1;
start1_5;
}
subgraph clusterSubProcess2 {
graph [ label="Subprocess two", color="blue" ]
start2_1 -> start2_2;
start2_2 -> start2_3a;
start2_2 -> start2_3b;
start2_3a -> start2_4;
start2_3b -> start2_5;
start2_4 -> start2_1;
start2_5 -> end1;
}
//Now connect the nodes in the two different subgraphs
start1_5 -> start2_1;
}
I'm a newbie with Graphviz, and I'm trying to draw a tree centered in an entity (I'm using the twopi command).
If I put overlap=true it overlaps even if it has a lot of space aroud the overlapped labels.
If I put overlap=false, labels become too small.
How can I have the first situation without overlapping?
Complete code:
digraph g {
graph [ fontname = "Helvetica",
fontsize = 10,
size = "500,500",
splines=true,
overlap=false,
ratio=.5 ];
node [ shape = plaintext,
fontname = "Helvetica" ];
root="owl:Thing";
"owl:Thing" -> "Work";
"Work" -> "WrittenWork";
"Work" -> "Software";
"Work" -> "Website";
"Work" -> "Film";
"owl:Thing" -> "Agent";
"Agent" -> "Organisation";
"Organisation" -> "Non-ProfitOrganisation";
"Organisation" -> "GeopoliticalOrganisation";
"Organisation" -> "SambaSchool";
"Agent" -> "Person";
"Person" -> "Athlete";
"Person" -> "OfficeHolder";
"Person" -> "Astronaut";
"Person" -> "Philosopher";
"Person" -> "Architect";
"owl:Thing" -> "Drug";
"owl:Thing" -> "Place";
"Place" -> "SiteOfSpecialScientificInterest";
"Place" -> "PopulatedPlace";
"PopulatedPlace" -> "Country";
"PopulatedPlace" -> "Continent";
"PopulatedPlace" -> "Atoll";
"Place" -> "ProtectedArea";
"Place" -> "ArchitecturalStructure";
"Place" -> "HistoricPlace";
"Place" -> "NaturalPlace";
"NaturalPlace" -> "Mountain";
"NaturalPlace" -> "Volcano";
"NaturalPlace" -> "MountainRange";
}
Thank you,
Alessio
For this particular graph, you may use overlap=true and then increment ranksep until no labels overlap anymore. ranksep=1.3 seems to be a good value.