用点号进行文本换行(Graphviz)

52
我使用下面的代码使用dot(graphviz)创建图形。
digraph
{
  node [color=Blue,shape=box]

  1.1 [label="Frequency of t exceeds upper threshold"]
  2.1 [label="t has d-mutant tiles"]
  2.2 [label="Valid"]
  3.1 [label="Frequency of t exceeds lower threshold"]
  3.2 [label="Frequency of t exceeds lower threshold"]
  4.1 [label="Insufficient evidence"]
  4.2 [label="Valid"]
  4.3 [label="t has only one d-mutant that exceeds lower threshold"]
  4.4 [label="Are there any d-mutant tiles with significantly higher frequencies?"]
  5.1 [label="Insufficient evidence"]
  node [color=Green] 5.2 [label="Correct t to t'"] node [color=Blue]
  5.3 [label="t has a d-mutant tile t' that is closer than all other d-mutant tiles and for which a corrected base has a higher quality score"]
  5.4 [label="Valid"]
  6.1 [label="Insufficient evidence"]
  6.2 [label="t' is unique"]
  7.1 [label="Insufficient evidence"]
  node [color=Green] 7.2 [label="Correct t to t'"] node [color=Blue]

  1.1 -> 2.1 [label="no"]
  1.1 -> 2.2 [label="yes"]
  2.1 -> 3.1 [label="no"]
  2.1 -> 3.2 [label="yes"]
  3.1 -> 4.1 [label="no"]
  3.1 -> 4.2 [label="yes"]
  3.2 -> 4.3 [label="no"]
  3.2 -> 4.4 [label="yes"]
  4.3 -> 5.1 [label="no"]
  4.3 -> 5.2 [label="yes"]
  4.4 -> 5.3 [label="no"]
  4.4 -> 5.4 [label="yes"]
  5.3 -> 6.1 [label="no"]
  5.3 -> 6.2 [label="yes"]
  6.2 -> 7.1 [label="no"]
  6.2 -> 7.2 [label="yes"]
}

正如你所看到的,图形中的一些方框标签中有很多文字。我可以插入\n字符以确保方框不会太宽,但我想知道是否有办法设置方框的宽度,然后让方框标签进行硬换行。这可行吗?


4个回答

37

graphviz不支持自动换行。您需要手动插入 \n。

您可以为节点设置宽度和高度,并将其定义为fixedsized - 这将限制节点的大小并仅绘制适合节点的文本。


10
对于我来说,事实证明这是错误的,文本只是超出了节点的形状。 - RushPL
如果你有很多节点,这将是不可能的。 - Ooker

6
虽然graphviz本身不支持文本换行,但dot2tex(latex+graphviz)可以实现。 dot2texi latex包提供了一站式解决方案, 用户只需调用一个工具就能创建图表。
以下是一个短小的示例:
\documentclass{standalone}
\usepackage{dot2texi}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows}
\begin{document}
\begin{dot2tex}[dot]
digraph G {                                             
d2toptions ="--autosize"
node    [lblstyle="text width=10em,align=center"]
a       [texlbl="This text will be automatically wrapped, for example at a fixed width."]
b       [texlbl="Manual linebreaks from past century can be avoided!"]
a -> b
}
\end{dot2tex}                                               
\end{document}

这可以通过调用例如 pdflatex --shell-escape myFile.tex 进行编译,文本将自动按指定的固定宽度换行。
顺便说一句,这个工具似乎是解决 graphviz 对节点内容的排版控制有限的一个方便的方法。

这个能生成SVG文件吗? - Ooker
1
@Ooker 我不知道,但你可以通过使用tikz调用外部工具dvisvgmpdf2svg等方法来找到解决方案... - letax
在您的看法中,您如何比较GraphViz和TikZ? - Ooker
@Ooker 两个完全不同的工具用于不同的任务... Tikz 是一种通用语言,用于生成矢量图形。Graphviz 则是一组(非常)专业化的工具,用于自动布局图形(而不需要事先知道节点应该放在哪里)。Dot2tex 允许在 tikz 的灵活框架中使用 graphviz 的求解器。 - letax
嗯,在Tikz中不能自动进行图形布局吗?我以为应该有一个专门用于图形的库,对吧?如果没有,那么Tikz和SVG之间有什么区别呢? - Ooker
显示剩余2条评论

1

原帖作者编写了一整个Perl脚本来实现这个功能。我在他的博客中找到了它:使用dot进行文本换行 (graphviz)

⚠ 注意

这仅适用于标签格式为node [ label=”node label” ]的情况。如果节点是直接声明的(例如”node label”),则无法正常工作。

Perl脚本:

#!/usr/bin/perl
use strict;
 
my $usage = "setdotlabelwidth [char-width] < [dotfile]";
my $width = shift() or die("Usage: $usage $!");
 
while(<STDIN>)
{
  if(m/label="(.*?)"/)
  {
    my $labeltext = $1;
    my @words = split(/ /, $labeltext);
    my @newtext = ();
    my $newline = "";
    foreach my $word(@words)
    {
      if( length($newline) > 0 and
          length($newline) + length($word) > $width )
      {
        push(@newtext, $newline);
        $newline = "";
      }
      $newline .= " " if( length($newline) > 0 );
      $newline .= $word;
    }
    push(@newtext, $newline) if( length($newline) > 0 );
    my $newlabel = join("\\n", @newtext);
    s/label=".*?"/label="$newlabel"/;
  }
  print;
}

将此程序保存为setdotlabelwidth,然后将输出直接导入GraphViz即可。例如,如果您想将宽度设置为35个字符,则命令如下:
./setdotlabelwidth 35 < tile-error-correction.dot | dot -Tpng -o tile-error-correction.png
之前: 之后:

0

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