graphviz - 如何在 GraphViz 中为点格式设置输出大小?

标签 graphviz networkx pygraphviz pyprocessing

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

我认为边界框将是使用 bb 的解决方案属性,但 dot 和neato 都简单地覆盖了它。

例如我的图表:

strict digraph {
    1,2,3;
    1 -> 3;
    3 -> 2;
}
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 的任何值,我都得到相同的位置或 size 的任意组合和 dpi .

我需要的是将所有节点都放在给定的框中。

任何建议如何做到这一点?

全文:

我正在使用来自 networkx 的 *graphviz_layout* 来布局我的图表。我用 pyprocessing 绘制图形。我想避免重新缩放 *graphviz_layout* 的结果,如果有办法告诉neato 我的边界。

最佳答案

这是 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

用空白填充图像,使其正好为 900 x 1500 像素;哪里convertImageMagick 的一部分套房。

这是详细的解释:

澄清:
  • The bb attribute is marked as "write-only" ,因此没有一个 Graphviz 布局引擎可能会尊重您在处理之前提交的任何值。
  • 一般情况下,Graphviz can generate both vector (scalable) and bitmap graphics ,因此 DPI 并不总是一个有意义的指标。

    特别是 dpi 属性仅对位图和 SVG 输出格式有效。

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

    让我们以任意图为例。

    命令 gvgen‎ -dh3将生成三次有向超立方体。 (如果您想了解更多详细信息,gvgen 手册页的 PDF 版本是 here ,但没关系,它只是用于演示目的的任意图形。)

    可以通过运行以下命令来创建该图形的默认点生成 PNG 渲染:
    gvgen -dh3 | dot -Tpng -oexample.png
    

    当我这样做时,我会得到一个 275 x 347 像素的 PNG 格式(位图)图像。 (据 file example.png 报道。)

    size 属性允许您推荐输出图像的最大或所需高度和宽度(以英寸为单位)。即,属性 size=3,5告诉 Graphviz 最多生成 3 x 5 英寸的图像。如果图像开始时小于 3 x 5,Graphviz 将不理会它。如果图像开始时大于 3 英寸 x 5 英寸,Graphviz 将缩小它,直到它适合 3 x 5 英寸的 Canvas (保留原始图像的纵横比)。

    添加感叹号会更改 size属性从最大大小到所需大小。现在,如果两个尺寸都小于指定尺寸,则将按比例放大绘图,直到至少一个尺寸等于指定尺寸。

    例如,运行:
    gvgen -dh3 | dot -Tpng -Gsize=3,5\! -oexample.png
    

    (请注意, \! 转义了 bash 的感叹号。在 DOT 文件中,您只需编写 size=3,5! 。)

    生成一个 288 x 363 像素的图像,在两个维度上都比默认值略大。

    dot 是如何得出这些数字的?好吧,Graphviz 的默认 DPI 值是每英寸 96 像素。在该分辨率下,3 x 5 英寸的图像是 288 x 480 像素的图像。布局引擎只是简单地放大图像,直到至少一个尺寸与所需尺寸匹配。

    您可以使用 dpi attribute 覆盖默认 DPI 值。 ,像这样:
    gvgen -dh3 | dot -Tpng -Gsize=3,5\! -Gdpi=200 -oexample.png
    

    现在生成的图像大小为 600 x 757 像素。同样,Graphviz 只是简单地放大图像,直到其中一个尺寸与所需尺寸匹配(但在此分辨率下,3 x 5 英寸的图像是 600 x 1000 像素的图像)。

    因此,如果您想生成包含任意数量像素的图像,您需要同时设置 sizedpi适本地。

    即,假设您要创建 900 x 1500 像素的图像。你可以使用:
    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 attribute的地方发挥作用。

    命令:
    gvgen -dh3 | dot -Tpng -Gsize=3,5\! -Gdpi=300 -Gratio=fill -oexample.png
    

    应该给你一个你正在寻找的精确尺寸的图像,但有几个警告:
  • 在实践中,它似乎有时会产生与预期略有不同的大小。例如,当我运行上面的命令时,我得到了一个 900 x 1472 像素的图像(而不是 900 x 1500)。我不知道这是由于四舍五入错误还是什么。
  • 为了实现这一点,Graphviz 必须在每个维度上独立地缩放布局。它足够智能,可以缩放布局而不是图像,因此图像本身不会失真,但是根据您请求的纵横比与布局的“自然”纵横比的不同,水平与垂直间距可能看起来有点奇怪的。
  • ratio也接受一些不同的值。见 the documentation和/或尝试一下看看他们做了什么。

    对于它的值(value),如果你真的想要一张你所要求的精确像素尺寸的图像,我的建议是让 Graphviz 缩放图像,使得两个维度之一匹配,然后使用类似 ImageMagick 的东西。填充图像以获得您正在寻找的精确纵横比。例如,命令:
    convert in.png -gravity center -background white -extent 900x1500 out.png
    

    通过根据需要填充水平或垂直尺寸,将图像(来自 in.png )在 900 x 1500 像素的 Canvas 上居中(将其保存到 out.png )

    关于graphviz - 如何在 GraphViz 中为点格式设置输出大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14784405/

    相关文章:

    graph - 在 graphviz 中先水平组织盒子,然后垂直组织盒子

    python - 如何向networkx中的节点添加属性

    graph - 使用 NetworkX 读取图形数据的文本文件

    python - 没有名为 _graphviz 的模块

    python - 水平绘制具有层次结构的 networkx 图并操纵箭头的长度

    graphviz - 如何防止dot花费的时间过长?

    python - Graphviz中如何设置输出图像的宽高

    python - PyGraphviz 只是没有安装在 OS-X 10.9.4 中

    c - 生成函数调用图 Doxygen+Graphviz

    python-3.x - 是否可以将无向和有向边添加到 networkx 中的图形对象?