Node placement in family tree visualization with Dot/Graphviz

自作多情 提交于 2019-12-08 09:16:35

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!