简体   繁体   English

足够大的图形集群边界框

[英]Large enough bounding box for graph cluster

I want to programmatically draw graphs using dot , gvpack and neato .我想使用dotgvpackneato以编程方式绘制图形。 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.但我不知道如何告诉dotgvpack和/或neato使用一个足够大的边界框来适应每个单独的图形,同时不允许重叠。

Can this be done?这可以做到吗? If so, how?如果是这样,如何? Thank you!谢谢!

MWE MWE

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值(计算的位置),和

  • wraps the result in two nested clusters (Two nested clusters make for better padding)将结果包装在两个嵌套的簇中(两个嵌套的簇可以更好地填充)
  • moves any graph labels to the inner cluster将任何图形标签移动到内部集群
  • moves "top-level" graphs, nodes, and edges to the inner cluster将“顶级”图、节点和边移动到内部集群
  • adjusts node labels to prevent "label modification" if gvpack will be used downstream如果gvpack将在下游使用,则调整节点标签以防止“标签修改”
  • sets bb values for both nested clusters为两个嵌套集群设置bb

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

Giving:给予:
在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM