[英]Large enough bounding box for graph cluster
I want to programmatically draw graphs using dot
, gvpack
and neato
.我想使用
dot
、 gvpack
和neato
以编程方式绘制图形。 I can generate the graph structure using a library, then write a file containing the graph described with dot
, and then pack all graphs in the same file.我可以使用库生成图形结构,然后编写一个包含用
dot
描述的图形的文件,然后将所有图形打包在同一个文件中。 Each graph has a label that acts as a title for it, which contains essential information and cannot be omitted.每张图都有一个 label 作为它的标题,包含重要信息,不能省略。 Unfortunately, the label is sometimes too wide.
不幸的是,label 有时太宽了。
Now, the result is as I expected.现在,结果如我所料。 However, I would like the bounding boxes of the individual graphs to be larger in order for them to fit the entirety of the "title".
但是,我希望单个图形的边界框更大,以便它们适合整个“标题”。 Then, I would like the graphs to be arranged in such a way that not even the bounding boxes overlap.
然后,我希望以这样的方式排列图形,即使边界框也不重叠。
But I don't know how to tell dot
, gvpack
and/or neato
to use a bounding box large enough to fit each individual graph while disallowing overlap.但我不知道如何告诉
dot
、 gvpack
和/或neato
使用一个足够大的边界框来适应每个单独的图形,同时不允许重叠。
Can this be done?这可以做到吗? If so, how?
如果是这样,如何? Thank you!
谢谢!
These are the only two trees of 4 vertices in the image above.这是上图中仅有的两棵 4 个顶点的树。 File
tree_04_00.raw
:文件
tree_04_00.raw
:
graph {
layout = neato
subgraph cluster_0 {
label = "idx= 0, centre=(0,1), centroid= (0,1)";
nd_0 [label= "0"];
nd_1 [label= "1"];
nd_2 [label= "2"];
nd_3 [label= "3"];
nd_0 -- nd_1;
nd_0 -- nd_3;
nd_1 -- nd_2;
}
}
File tree_04_01.raw
:文件
tree_04_01.raw
:
graph {
layout = neato
subgraph cluster_1 {
label = "idx= 1, centre=(0), centroid= (0)";
nd_4 [label= "0"];
nd_5 [label= "1"];
nd_6 [label= "2"];
nd_7 [label= "3"];
nd_4 -- nd_5;
nd_4 -- nd_6;
nd_4 -- nd_7;
}
}
To actually make the image above, I execute the following commands:为了实际制作上面的图像,我执行以下命令:
# dot for each .raw file
$ dot -Tdot tree_04_00.raw > tree_04_00.dot
$ dot -Tdot tree_04_01.raw > tree_04_01.dot
# now pack all the graphs
$ gvpack -array_it20 tree_04_*.dot > trees_04.dot
# now run neato
$ neato -n2 -Tsvg trees_04.dot > trees_04.svg
The result of the last command is shown in the image above.最后一条命令的结果如上图所示。
neato does not recognize clusters (except for neato -n ) and regular subgraphs don't have labels, so it is surprising that you got any label on the output. neato不识别簇( neato -n除外)并且常规子图没有标签,因此令人惊讶的是您在 output 上得到了任何 label。
Below is a gvpr ( http://www.graphviz.org/pdf/gvpr.1.pdf ) program that takes the output from any of the layout engines in dot / xdot format ie with pos values (positions calculated), and下面是一个gvpr ( http://www.graphviz.org/pdf/gvpr.1.pdf ) 程序,它从任何布局引擎中以dot / xdot格式获取 output ,即具有pos值(计算的位置),和
Remember, neato will recognize these clusters because neato -n/n2请记住, neato会识别这些集群,因为neato -n/n2
The gvpr program ( clusterWrap.gvpr): gvpr程序(clusterWrap.gvpr):
//
// creates clusters around the entire graph, allowing user to save graph label
// also "fixes" node labels by instantiating default values (\N -> actual node name)
//
BEGIN{
graph_t aGraph, Root, innerCluster, outerCluster;
node_t aNode;
edge_t anEdge;
int i, cnt, topNode[], topSubgraph[], topEdge[];
float delta=8., deltaX, deltaY;
string st;
string copyAtt[int];
/////////////////////////////////////////////////////////////////////////////
split("label|lheight|lwidth|lp|bb", copyAtt, "|");
// deltaX=delta;
// deltaY=delta;
}
BEG_G{
Root=$G;
// get graphs, nodes, and edges(?) directly "under" Root graph
for (aNode=fstnode($G);aNode;aNode = nxtnode(aNode)){
topNode[aNode]=1;
}
for (aGraph = fstsubg($G); aGraph; aGraph = nxtsubg(aGraph)) {
topSubgraph[aGraph]=1;
}
// we will find top-level edges later
// create wrapper clusters
outerCluster=subg(Root,"clusterPad000");
innerCluster=subg(outerCluster,"clusterWrapper000");
if (hasAttr(Root, "layout")){
Root.layout="neato"; // other values (including "") cause problems with later execution
}
//Root.OLDbb=Root.bb;
// "move" attribute values to new cluster
for (copyAtt[i]){
if (hasAttr(Root, copyAtt[i])){
st=aget(Root, copyAtt[i]);
aset(innerCluster, copyAtt[i], st);
aset(Root, copyAtt[i], "");
}
}
innerCluster.peripheries=0;
// create a pad/margin between the two new clusters
outerCluster.bb=(string)((float)xOf(llOf(innerCluster.bb))-delta) + "," +
(string)((float)yOf(llOf(innerCluster.bb))-delta) + "," +
(string)((float)xOf(urOf(innerCluster.bb))+delta) + "," +
(string)((float)yOf(urOf(innerCluster.bb))+delta);
}
N{
$.OLDpos=$.pos;
// "fix" node labels by creating explicit label
if (hasAttr($, "label") && ($.label!="")){
print("// starting label: ", $.label);
$.label=gsub($.label, "\\\\N", $.name); // ugh, backslashes
$.label=gsub($.label, "\\\\G", $G.name); // ugh, backslashes
}else{
print("// starting label: >", $.label,"<");
$.label=$.name;
}
}
E{
// find all edges defined directly under Root
if (isSubedge(Root, $)){
topEdge[$]=1;
}
}
END_G{
// now move graphs, nodes, and edges "under" inner cluster
for (topSubgraph[aGraph]){
print("// cloning subg :", aGraph.name);
clone(innerCluster, aGraph);
delete(Root, aGraph);
}
for (topNode[aNode]){
print("// moving node :", aNode.name);
subnode(innerCluster, aNode);
}
for (topEdge[anEdge]){
print("// moving edge :", anEdge.name);
subedge(innerCluster, anEdge);
}
}
A modified version of your command stream to show gvpr usage:命令 stream 的修改版本显示gvpr用法:
# dot for each .raw file
$ dot -Tdot tree_04_00.raw |gvpr -cf clusterWrap.gvpr > tree_04_00.dot
$ dot -Tdot tree_04_01.raw |gvpr -cf clusterWrap.gvpr > tree_04_01.dot
# now pack all the graphs
$ gvpack -array_it20 tree_04_*.dot > trees_04.dot
# now run neato
$ neato -n2 -Tsvg trees_04.dot > trees_04.svg
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.