如何在GraphViz中设置dot格式的输出大小?

48

我希望确保所有节点在布局后都在某个范围内(比如[0,0,W,H])。

我认为通过使用bb属性来确定边界框是解决方案,但是dotneato都会覆盖它。

例如,我的图形:

strict digraph {
    1,2,3;
    1 -> 3;
    3 -> 2;
}
< p > neato -Gbb="0,0,50,50" -T dot file.txt的输出:

strict digraph {
        graph [bb="0,0,120.49,162.36"];
        node [label="\N"];
        1        [height=0.5,
                pos="27,18",
                width=0.75];
        3        [height=0.5,
                pos="70.233,75.918",
                width=0.75];
        1 -> 3   [pos="e,57.954,59.469 39.043,34.133 43.004,39.441 47.504,45.468 51.827,51.261"];
        2        [height=0.5,
                pos="93.485,144.36",
                width=0.75];
        3 -> 2   [pos="e,87.436,126.56 76.221,93.545 78.643,100.67 81.496,109.07 84.177,116.97"];
}

无论bb的值是什么,或者sizedpi的任何组合,我都会得到相同的位置。
我需要的是在给定框内的所有节点。
有没有什么建议如何做到这一点?
完整故事:
我正在使用来自networkx库的*graphviz_layout*来布局我的图形。我使用pyprocessing绘制图形。如果有一种方法可以告诉neato我的边界,我想避免重新缩放*graphviz_layout*的结果。
1个回答

94

这里是TL;DR版本:

要从foo.gv图形生成一个900 x 1500像素的PNG图片,您可以运行以下命令:

dot -Tpng -Gsize=9,15\! -Gdpi=100 -ofoo.png foo.gv

要生成一个宽度恰好为900像素或高度为1500像素的图像,但不一定是两者都满足;然后:
convert foo.png -gravity center -background white -extent 900x1500 final.png

将图像用空白填充,使其恰好为900x1500像素;其中convertImageMagick套件的一部分。

以下是详细说明:

澄清一下:

  1. bb属性被标记为“只写”,因此在处理之前,Graphviz布局引擎不太可能尊重您提交的任何值。

  2. 一般情况下,Graphviz可以生成矢量(可缩放)和位图图形,因此DPI并不总是有意义的度量标准。

    特别地,dpi属性仅适用于位图和SVG输出格式。

你所要做的事情有些复杂,因为Graphviz生成的图像的像素大小由几个交互属性驱动。

我们以任意图形为例。

命令gvgen -dh3将生成一个度为三的有向超立方体。(如果您想了解更多细节,请参阅gvgen的手册PDF版本here,但这不重要,它只是用于演示目的的任意图形。)

可以通过运行以下命令创建默认的dot生成的PNG渲染图:

gvgen -dh3 | dot -Tpng -oexample.png

当我这样做时,我得到了一个275 x 347像素的PNG格式(位图)图像。(如file example.png所报告的。) size属性允许您建议输出图像的最大或期望高度和宽度(以英寸为单位)。 即,属性size=3,5告诉Graphviz生成一个最多为3乘5英寸的图像。 如果图像本来就比3乘5小,Graphviz将保持不变。 如果图像本来比3英寸乘5英寸大,Graphviz将缩小它,直到它适合3英寸乘5英寸的画布(保留原始图像的纵横比)。
添加感叹号会将size属性从最大尺寸更改为期望尺寸。 现在,如果两个维度都小于指定的大小,则绘图将被放大,直到至少一个维度等于指定的大小。
例如,运行:
gvgen -dh3 | dot -Tpng -Gsize=3,5\! -oexample.png

请注意,!用于在bash中转义感叹号。在DOT文件中,您只需编写size=3,5!
生成一个288 x 363像素的图像,两个维度都比默认值略大。
那么,dot是如何得出这些数字的呢?Graphviz的默认DPI值为96像素每英寸。在这个分辨率下,一个3乘5英寸的图像是一个288乘480像素的图像。布局引擎简单地将图像缩放到至少一个维度匹配所需大小。
您可以使用dpi属性覆盖默认的DPI值,如下所示:
gvgen -dh3 | dot -Tpng -Gsize=3,5\! -Gdpi=200 -oexample.png

现在生成的图片尺寸为600x757像素。同样地,Graphviz只是将图像缩放,直到其中一个维度匹配所需的大小(但在这个分辨率下,一个3x5英寸的图像是一个600x1000像素的图像)。
因此,如果您想生成包含任意数量像素的图像,则需要适当设置sizedpi
例如,假设您想创建一个900x1500像素的图像。您可以使用以下命令:
gvgen -dh3 | dot -Tpng -Gsize=9,15\! -Gdpi=100 -oexample.png

或者

gvgen -dh3 | dot -Tpng -Gsize=3,5\! -Gdpi=300 -oexample.png

甚至可能是:
gvgen -dh3 | dot -Tpng -Gsize=900,1500\! -Gdpi=1 -oexample.png

(但是在快速测试中,最后一个方法似乎对我有效,但为了保险起见,我建议坚持使用更常规的DPI值。)
这解决了大部分问题,但请注意Graphviz仅将图像缩放到其中一个维度与指定大小匹配。根据原始图像的宽高比,您可能无法获得所需的确切尺寸。
这就是ratio属性发挥作用的地方。
命令:
gvgen -dh3 | dot -Tpng -Gsize=3,5\! -Gdpi=300 -Gratio=fill -oexample.png

应该可以给您提供所需尺寸的图像,但有一些注意事项:

  • 实际上,它似乎有时会产生略微不同于期望的大小。例如,当我运行上面的命令时,我得到一个900 x 1472像素的图像(而不是900 x 1500)。我不知道这是由于四舍五入误差还是其他原因。

  • 为了实现这一点,Graphviz必须独立地在每个维度上进行布局缩放。它足够聪明,可以缩放布局而不是图像,因此图像本质上不会变形,但是取决于您请求的纵横比与布局的“自然”纵横比之间的差异,水平和垂直间距可能看起来有点奇怪。

ratio 还接受几个不同的值。请参阅文档或进行一些实验以查看它们的作用。

如果你确实想要一个精确的像素尺寸的图片,我的建议是让Graphviz缩放图像,使得其中一个维度匹配,然后使用ImageMagick之类的工具来添加填充以达到所需的精确宽高比。例如,使用以下命令:

convert in.png -gravity center -background white -extent 900x1500 out.png

这段代码将会把图片(来自in.png)居中显示在一个 900 x 1500 像素的画布上(并保存到out.png),必要时会通过填充水平或垂直维度来实现。


1
这是一篇精彩的文章。感谢您抽出时间来写它!+1,希望我能为您接受。 - sigpwned
我在处理pdf输出时遇到了类似的问题。后来,我发现需要调整分页媒体的边距(margin),并在这里找到了答案:http://www.graphviz.org/content/dot-inconsistent-default-margins-png-vs-pdf - Mr. Tao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接