问题
I'm trying to generate family tree visualizations from a database using Dot/Graphviz. First results look promising, but there is one layout issue that I haven't been able to fix yet.
When I use the code listed below, it will produce
I'm totally happy with this. But as soon as I try to add another node between families F4/M4/M5 and F2/M2, which can be done by uncommenting the two lines in the code below, it will give me
Male2 is now placed far away from Female2 and between Female4 and Male4. So the families F2/M2 and F4/M4/M5 are completely torn apart. I tried to increase the weight for the family connections (value is 100) in order to make sure families F2/M2 and F4/M4/M5 are placed together, but this doesn't work. Also changing order of nodes or connections did not help so far. The best solution would be, if family F4/M4/M5 could be placed on the left, MaleX in the center and family F2/M2 on the right.
Does anyone have a suggestion? I would prefer to not change the order in which the nodes and connections are defined in the code, because this is done by a script and is kind of predefined by the database structure.
graph Test {
rankdir = BT;
splines = ortho;
center = true;
{
rank = same;
NodeFemale1 [label = Female1];
NodeMale1 [label = Male1];
ConnectionFemale1Male1 [shape = box, label = "", height = 0, width = 1, margin = 0, penwidth = 1];
NodeFemale1 -- ConnectionFemale1Male1 -- NodeMale1 [weight = 100, penwidth = 2];
}
ConnectionChildren11 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
ConnectionFemale1Male1 -- ConnectionChildren11 [penwidth = 2];
{
rank = same;
NodeFemale2 [label = Female2];
NodeMale2 [label = Male2];
ConnectionFemale2Male2 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
NodeFemale2 -- ConnectionFemale2Male2 -- NodeMale2 [weight = 100, penwidth = 2];
}
ConnectionChildren11 -- NodeMale2 [penwidth = 2];
ConnectionChildren22 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
ConnectionFemale2Male2 -- ConnectionChildren22 [penwidth = 2];
NodeMale3 [label = Male3];
ConnectionChildren22 -- NodeMale3 [weight = 10, penwidth = 2];
NodeFemale3 [label = Female3];
ConnectionChildren22 -- NodeFemale3 [penwidth = 2];
// NodeMaleX [label = MaleX];
// ConnectionChildren11 -- NodeMaleX [weight = 10, penwidth = 2];
{
rank = same;
NodeFemale4 [label = Female4];
NodeMale4 [label = Male4];
NodeMale5 [label = Male5];
ConnectionFemale4Male4 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
NodeFemale4 -- ConnectionFemale4Male4 -- NodeMale4 [weight = 100, penwidth = 2];
ConnectionMale4Male5 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
NodeMale4 -- ConnectionMale4Male5 -- NodeMale5 [weight = 100, penwidth = 2];
}
ConnectionChildren11 -- NodeFemale4 [penwidth = 2];
ConnectionChildren44 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
ConnectionFemale4Male4 -- ConnectionChildren44 [penwidth = 2];
NodeFemale6 [label = Female6];
ConnectionChildren44 -- NodeFemale6 [weight = 10, penwidth = 2];
NodeFemale7 [label = Female7];
ConnectionChildren44 -- NodeFemale7 [penwidth = 2];
ConnectionChildren45 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
ConnectionMale4Male5 -- ConnectionChildren45 [penwidth = 2];
NodeFemale8 [label = Female8];
ConnectionChildren45 -- NodeFemale8 [penwidth = 2];
}
回答1:
I don't think you can take control the way you want without resorting to subgraph
. This may or may not be helpful in the context of your script and database that provides you with the nodes and edges but I have tried something that hopefully comes close to what you want:
graph Test
{
/* layout / format */
rankdir = BT; // bottoms to top
splines = ortho; // edges orthogonal
center = true; // page center
edge [ penwidth = 2 ]; // edge thickness
node [ width = 1.1 ]; // conistent node size
/* node and edge definitions as produced by the script (?) */
NodeFemale1 [label = Female1];
NodeMale1 [label = Male1];
ConnectionFemale1Male1 [shape = box, label = "", height = 0, width = 1, margin = 0, penwidth = 1];
// 1 NodeFemale1 -- ConnectionFemale1Male1 -- NodeMale1 [weight = 100, penwidth = 2];
ConnectionChildren11 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
// 2 ConnectionFemale1Male1 -- ConnectionChildren11 [penwidth = 2];
NodeFemale2 [label = Female2];
NodeMale2 [label = Male2];
ConnectionFemale2Male2 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
// 3 NodeFemale2 -- ConnectionFemale2Male2 -- NodeMale2 [weight = 100, penwidth = 2];
// 4 ConnectionChildren11 -- NodeMale2 [penwidth = 2];
ConnectionChildren22 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
// 5 ConnectionFemale2Male2 -- ConnectionChildren22 [penwidth = 2];
NodeMale3 [label = Male3];
// 6 ConnectionChildren22 -- NodeMale3 [weight = 10, penwidth = 2];
NodeFemale3 [label = Female3];
// 7 ConnectionChildren22 -- NodeFemale3 [penwidth = 2];
NodeMaleX [label = MaleX];
// 8 ConnectionChildren11 -- NodeMaleX [weight = 10, penwidth = 2];
NodeFemale4 [label = Female4];
NodeMale4 [label = Male4];
NodeMale5 [label = Male5];
ConnectionFemale4Male4 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
// 9 NodeFemale4 -- ConnectionFemale4Male4 -- NodeMale4 [weight = 100, penwidth = 2];
ConnectionMale4Male5 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
// 10 NodeMale4 -- ConnectionMale4Male5 -- NodeMale5 [weight = 100, penwidth = 2];
// 11 ConnectionChildren11 -- NodeFemale4 [penwidth = 2];
ConnectionChildren44 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
// 12 ConnectionFemale4Male4 -- ConnectionChildren44 [penwidth = 2];
NodeFemale6 [label = Female6];
// 13 ConnectionChildren44 -- NodeFemale6 [weight = 10, penwidth = 2];
NodeFemale7 [label = Female7];
// 14 ConnectionChildren44 -- NodeFemale7 [penwidth = 2];
ConnectionChildren45 [shape = box, label = "", height = 0, width = 0, margin = 0, penwidth = 1];
// 15 ConnectionMale4Male5 -- ConnectionChildren45 [penwidth = 2];
NodeFemale8 [label = Female8];
// 16 ConnectionChildren45 -- NodeFemale8 [penwidth = 2];
/* family / generation subgraphs */
subgraph cluster0
{
style = filled;
fillcolor = lightgrey;
color = white;
{ rank = same; NodeFemale1; ConnectionFemale1Male1; NodeMale1 }
NodeFemale1 -- ConnectionFemale1Male1 -- NodeMale1;
}
ConnectionFemale1Male1 -- ConnectionChildren11;
subgraph cluster1
{
{ rank = same; NodeMale2; ConnectionFemale2Male2; NodeFemale2 }
NodeFemale2 -- ConnectionFemale2Male2 -- NodeMale2;
}
ConnectionChildren11 -- NodeMale2;
subgraph cluster2
{
NodeMaleX;
}
ConnectionChildren11 -- NodeMaleX;
subgraph cluster3
{
{ rank = same; NodeFemale4; NodeMale4; NodeMale5; ConnectionFemale4Male4; ConnectionMale4Male5 }
NodeFemale4 -- ConnectionFemale4Male4 -- NodeMale4 -- ConnectionMale4Male5 -- NodeMale5;
}
ConnectionChildren11 -- NodeFemale4;
subgraph cluster4
{
color = white;
{ rank = same; NodeMale3; NodeFemale3 }
}
ConnectionFemale2Male2 --ConnectionChildren22;
ConnectionChildren22 -- { NodeMale3 NodeFemale3 };
subgraph cluster5
{
color = white;
{ rank = same; NodeFemale6; NodeFemale7 }
}
ConnectionFemale4Male4 --ConnectionChildren44;
ConnectionChildren44 -- { NodeFemale6 NodeFemale7 };
subgraph cluster6
{
color = white;
NodeFemale8;
}
ConnectionMale4Male5 --ConnectionChildren45;
ConnectionChildren45 -- NodeFemale8;
}
The clusters can be customized, as demonstrated on the parents level. If you just set color = white
they become "invisible", as shown in the grandchildren generation.
来源:https://stackoverflow.com/questions/33446775/node-placement-in-family-tree-visualization-with-dot-graphviz