问题描述
(Visual)C ++世界。我有一个树结构,想要可视化它。具体来说:
我有一个树数据。我想要处理这个数据的库,并计算每个节点的坐标(在任何逻辑坐标空间,例如2000x2000个逻辑像素),以及连接它们的每个线。连接两个节点的线可能不是一条简单的直线,它可能是曲线或某种由直线段组成的路径。理想情况下,我想要为给定树节点的坐标计算线定义路径,以防用户将拖动和重新排列节点。
我需要的库,将计算所有必要的几何坐标为我,给定的图形。然后我将使用这些坐标来绘制图形,如我所愿,使用GDI。
我听说过Graphviz,点语言等。但我不知道它(或其替代品如OGDF或igraph)可以做我想要的。我想要完成的想法是自己渲染图形,但需要协助生成坐标。另外,用户必须能够重新定位节点,因此连接重新布置的节点的线路路径的重新计算必须是可能的。
是,graphviz可以执行此操作。
布局有向图
让我们假设你在 tree.gv
:
digraph g {
a [label =I];
b [label =am];
c [label =a];
d [label =tree];
e [label =with];
f [label =7];
g [label =nodes];
a - > b - > C;
b - > d - > e;
d - > F;
d - > G;
}
输出此图表:
dot tree.gv
会产生
{
node [label =\ N];
graph [bb =0,0,208,252];
a [label = I,pos =63,234,width =0.75,height =0.5];
b [label = am,pos =63,162,width =0.75,height =0.5];
c [label = a,pos =27,90,width =0.75,height =0.5];
d [label = tree,pos =99,90,width =0.75,height =0.5];
e [label = with,pos =2718,width =0.75,height =0.5];
f [label = 7,pos =99,18,width =0.75,height =0.5];
g [label = nodes,pos =176,18,width =0.89579,height =0.5];
a - > b [pos =e,63,180.1 63,215.7 63,207.98 63,198.71 63,190.11];
b - > c [pos =e,35.304,107.15 54.65,144.76 50.288,136.28 44.853,125.71 39.959,116.2];
b - > d [pos =e,90.696,107.15 71.35,144.76 75.712,136.28 81.147,125.71 86.041,116.2];
d - > e [pos =e,41.796,33.385 84.43,74.834 74.25,64.938 60.476,51.546 48.969,40.359];
d - > f [pos =e,99,36.104 99,71.697 99,63.983 99,54.712 99,46.112];
d - > g [pos =e,159.91,33.626 114.58,74.834 125.4,65.003 140,51.723 152.26,40.582];
}
所有坐标都可以在输出中找到。如果您需要更多关于如何绘制图形的细节,您可以尝试使用 xdot
格式: dot -Txdot tree.gv
digraph g {
node [label =\N];
graph [bb =0,0,208,252,
_draw _ =c 9 - #ffffffff C 9 - #ffffffff P 4 0 -1 0 252 209 252 209 -1,
xdotversion =1.2];
a [label = I,pos =63,234,width =0.75,height =0.5,_draw _ =c 9 - #000000ff e 63 234 27 18,_ldraw _ =F 14.000000 11- -Roman c 9 - #000000ff T 63 228 0 5 1 -I];
b [label = am,pos =63,162,width =0.75,height =0.5,_draw _ =c 9 - #000000ff e 63 162 27 18,_ldraw _ =F 14.000000 11- -Roman c 9 - #000000ff T 63 156 0 17 2 -am];
c [label = a,pos =27,90,width =0.75,height =0.5,_draw _ =c 9 - #000000ff e 27 90 27 18,_ldraw _ =F 14.000000 11 -Times-Roman c 9 - #000000ff T 27 84 0 7 1 -a];
d [label = tree,pos =99,90,width =0.75,height =0.5,_draw _ =c 9 - #000000ff e 99 90 27 18,_ldraw _ =F 14.000000 11 - Times-Roman c 9 - #000000ff T 99 84 0 21 4 -tree];
e [label = with,pos =27,18,width =0.75,height =0.5,_draw _ =c 9 - #000000ff e 27 18 27 18,_ldraw _ =F 14.000000 11 - Times-Roman c 9 - #000000ff T 27 12 0 24 4 - with];
f [label = 7,pos =99,18,width =0.75,height =0.5,_draw _ =c 9 - #000000ff e 99 18 27 18,_ldraw _ =F 14.000000 11 -Times-Roman c 9 - #000000ff T 99 12 0 7 1 -7];
g [label = nodes,pos =176,18,width =0.89579,height =0.5,_draw _ =c 9 - #000000ff e 176 18 32 18,_ldraw _ =F 14.000000 11 -Times-Roman c 9 - #000000ff T 176 12 0 34 5 -nodes];
a - > b [pos =e,63,180.1 63,215.7 63,207.98 63,198.71 63,190.11,_draw_ =c 9 - #000000ff B 4 63 216 63 208 63 199 63 190,_draw_ =S 5 -solid c 9 - #000000ff C 9 - 000000ff P 3 67 190 63 180 60 190];
b - > c [pos =e,35.304,107.15 54.65,144.76 50.288,136.28 44.853,125.71 39.959,116.2,_draw _ =c 9 - #000000ff B 4 55 145 50 136 45 126 40 116,_draw _ =固体c 9 - #000000ff C 9 - #000000ff P 3 43 114 35 107 37 118];
b - > d [pos =e,90.696,107.15 71.35,144.76 75.712,136.28 81.147,125.71 86.041,116.2,_draw _ =c 9 - #000000ff B 4 71 145 76 136 81 126 86 116,_draw _ =固体c 9 - #000000ff C 9 - #000000ff P 3 89 118 91 107 83 114];
d - > e [pos =e,41.796,33.385 84.43,74.834 74.25,64.938 60.476,51.546 48.969,40.359,_draw _ =c 9 - #000000ff B 4 84 75 74 65 60 52 49 40,_draw _ =固体c 9 - #000000ff C 9 - #000000ff P 3 51 38 42 33 47 43];
d - > f [pos =e,99,36.104 99,71.697 99,63.983 99,54.712 99,46.112,_draw _ =c 9 - #000000ff B 4 99 72 99 64 99 55 99 46,_draw _ =固体c 9 - #000000ff C 9 - #000000ff P 3 103 46 99 36 96 46];
d - > g [pos =e,159.91,33.626 114.58,74.834 125.4,65.003 140,51.723 152.26,40.582,_draw _ =c 9 - #000000ff B 4 115 75 125 65 140 52 152 41,_draw _ =固体c 9 - #000000ff C 9 - #000000ff P 3 155 43 160 34 150 38];
}
仅布局边缘/重新计算边
您可以使用以上输出之一,修改任何节点的位置,并将其用作以下命令的输入:
neato -n tree.modified.gv
这将只重新计算边缘(有关neato点和neato选项的详细信息,请参见手册页 b 和的位置。
自动布局:
修改的布局:
(Visual) C++ world. I have a tree structure, want to visualize it. More specifically:
I have a tree data. I want the library that processes this data and computes coordinates (in any logical coordinate space, say 2000x2000 logical pixels) for each nodes, AND for each lines connecting them. Line connecting the two nodes might not be a simple straight line, it might be curve or some sort of path consisting of straight line segments. Ideally I'd like the line defining path to be calculated for the given tree nodes' coordinates as well, in case the user will drag and rearrange the nodes.
Shortly, I need the library that will compute all the necessary geometrical coordinates for me, for the given graph. Then I'll use these coordinates to draw the graph as I wish, using GDI.
I've heard of Graphviz, dot-language, and such. But I'm not sure whether it (or its alternatives like OGDF or igraph) can do what I want. The idea I want to accomplish is to render the graph myself, but need the assistance in generating coordinates. Also user must be able to reposition the nodes, so the re-computation of line path that connects rearranged nodes must be possible, so that e.g. lines do not cross any existing nodes.
Yes, graphviz can do this.
Layout a directed graph
Let's say you have the following graph in tree.gv
:
digraph g{
a[label="I"];
b[label="am"];
c[label="a"];
d[label="tree"];
e[label="with"];
f[label="7"];
g[label="nodes"];
a -> b -> c;
b -> d -> e;
d -> f;
d -> g;
}
dot
can lay out this graph: dot tree.gv
which results in
digraph g {
node [label="\N"];
graph [bb="0,0,208,252"];
a [label=I, pos="63,234", width="0.75", height="0.5"];
b [label=am, pos="63,162", width="0.75", height="0.5"];
c [label=a, pos="27,90", width="0.75", height="0.5"];
d [label=tree, pos="99,90", width="0.75", height="0.5"];
e [label=with, pos="27,18", width="0.75", height="0.5"];
f [label=7, pos="99,18", width="0.75", height="0.5"];
g [label=nodes, pos="176,18", width="0.89579", height="0.5"];
a -> b [pos="e,63,180.1 63,215.7 63,207.98 63,198.71 63,190.11"];
b -> c [pos="e,35.304,107.15 54.65,144.76 50.288,136.28 44.853,125.71 39.959,116.2"];
b -> d [pos="e,90.696,107.15 71.35,144.76 75.712,136.28 81.147,125.71 86.041,116.2"];
d -> e [pos="e,41.796,33.385 84.43,74.834 74.25,64.938 60.476,51.546 48.969,40.359"];
d -> f [pos="e,99,36.104 99,71.697 99,63.983 99,54.712 99,46.112"];
d -> g [pos="e,159.91,33.626 114.58,74.834 125.4,65.003 140,51.723 152.26,40.582"];
}
All the coordinates can be found in the output. If you need even more details on how to draw the graph, you may try using the xdot
format: dot -Txdot tree.gv
digraph g {
node [label="\N"];
graph [bb="0,0,208,252",
_draw_="c 9 -#ffffffff C 9 -#ffffffff P 4 0 -1 0 252 209 252 209 -1 ",
xdotversion="1.2"];
a [label=I, pos="63,234", width="0.75", height="0.5", _draw_="c 9 -#000000ff e 63 234 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 63 228 0 5 1 -I "];
b [label=am, pos="63,162", width="0.75", height="0.5", _draw_="c 9 -#000000ff e 63 162 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 63 156 0 17 2 -am "];
c [label=a, pos="27,90", width="0.75", height="0.5", _draw_="c 9 -#000000ff e 27 90 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 27 84 0 7 1 -a "];
d [label=tree, pos="99,90", width="0.75", height="0.5", _draw_="c 9 -#000000ff e 99 90 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 99 84 0 21 4 -tree "];
e [label=with, pos="27,18", width="0.75", height="0.5", _draw_="c 9 -#000000ff e 27 18 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 27 12 0 24 4 -with "];
f [label=7, pos="99,18", width="0.75", height="0.5", _draw_="c 9 -#000000ff e 99 18 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 99 12 0 7 1 -7 "];
g [label=nodes, pos="176,18", width="0.89579", height="0.5", _draw_="c 9 -#000000ff e 176 18 32 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 9 -#000000ff T 176 12 0 34 5 -nodes "];
a -> b [pos="e,63,180.1 63,215.7 63,207.98 63,198.71 63,190.11", _draw_="c 9 -#000000ff B 4 63 216 63 208 63 199 63 190 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 67 190 63 180 60 190 "];
b -> c [pos="e,35.304,107.15 54.65,144.76 50.288,136.28 44.853,125.71 39.959,116.2", _draw_="c 9 -#000000ff B 4 55 145 50 136 45 126 40 116 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 43 114 35 107 37 118 "];
b -> d [pos="e,90.696,107.15 71.35,144.76 75.712,136.28 81.147,125.71 86.041,116.2", _draw_="c 9 -#000000ff B 4 71 145 76 136 81 126 86 116 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 89 118 91 107 83 114 "];
d -> e [pos="e,41.796,33.385 84.43,74.834 74.25,64.938 60.476,51.546 48.969,40.359", _draw_="c 9 -#000000ff B 4 84 75 74 65 60 52 49 40 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 51 38 42 33 47 43 "];
d -> f [pos="e,99,36.104 99,71.697 99,63.983 99,54.712 99,46.112", _draw_="c 9 -#000000ff B 4 99 72 99 64 99 55 99 46 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 103 46 99 36 96 46 "];
d -> g [pos="e,159.91,33.626 114.58,74.834 125.4,65.003 140,51.723 152.26,40.582", _draw_="c 9 -#000000ff B 4 115 75 125 65 140 52 152 41 ", _hdraw_="S 5 -solid c 9 -#000000ff C 9 -#000000ff P 3 155 43 160 34 150 38 "];
}
Detailed information about this format can be found on the graphviz web site.
Layout only edges / recompute edges
You may use one of the above outputs, modify positions of any nodes, and use it as input for the following command:
neato -n tree.modified.gv
This will recompute only the edges (more information on neato dot and neato options can be found on their manual pages).
Below you can see an example of an unmodified and a modified layout - I changed positions for the b and g nodes.
Automatic layout:
Modified layout:
这篇关于树可视化库 - 计算给定树数据的所有节点和线坐标的图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!