不同位置的 TikZ-PGF 子节点

不同位置的 TikZ-PGF 子节点

当我使用 TiKz 绘制两棵树时,每棵树都在一个嵌套的图片中,第二棵树的中间子树的位置与第一棵树不同。尽管树的代码基本相同(除了 right=of 测试参数)。

在此处输入图片描述

我做错什么了吗?有没有办法解决这个问题,让两个中间的孩子都直接位于各自父母的领导下?

代码:

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}

\tikzstyle{every node}=[draw]

\node (test) {
\begin{tikzpicture}
\node {}
    child { node {} }
    child { node {} }
    child { node {} };
\end{tikzpicture}
};

\node [right=of test] {
\begin{tikzpicture}
\node {}
    child { node {} }
    child { node {} }
    child { node {} };
\end{tikzpicture}
};

\end{tikzpicture}
\end{document}

答案1

作为Qrrbrbirlbel 解释 forest可以与根一起使用phantom,并提供用于指定树布局的灵活选项。

但是,指定l sep和并s sep不能保证中心子节点与父节点对齐。如果节点内容的宽度不同,则可能会失败:

\begin{forest}
  for tree={
    l sep=1cm,
    s sep=1cm,
    draw,
    align=center
  }
  [,phantom
   [
     [some text here]
     [a multiline node\\in the middle]
     [not much]
   ]
   [
     [this\\node\\needs\\five\\lines]
     [this\\one\\only\\four]
     [finally\\just\\three]
   ]
  ]
\end{forest}

不结盟儿童

发生这种情况的原因是s sep仅指定了最小距离。可以强制设置s为某个值,从而设置距离。但是,最好允许forest找出最佳值,并只给它一些关于我们希望它做什么的提示。calign with current指示forest将当前子级与其父级对齐,这正是本例中所需要的。

\begin{forest}
  for tree={
    draw,
    if={isodd(n_children())}{
      for children={
        if={
          equal(n,int((1+n_children("!u"))/2))
        }{calign with current}{}
      }
    }{},
    align=center
  }
  [,phantom
   [
     [some text here]
     [a multiline node\\in the middle]
     [not much]
   ]
   [
     [this\\node\\needs\\five\\lines]
     [this\\one\\only\\four]
     [finally\\just\\three]
   ]
  ]
\end{forest}

它的工作原理是测试一个节点是否有奇数个子节点。如果是,那么中心子节点将与其父节点对齐:

对齐的子项

但是,如果父节点的边指向子节点的北边,而不是穿过节点,效果会更好。添加可child anchor=north实现此目的:

北方锚点

如果根节点也包含内容,并且这两种情况下内容的高度不同,则会抛出垂直对齐问题:

垂直差异

为了避免这种情况,我们可以使用tier来确保给定级别的所有节点都垂直对齐。添加tier/.wrap pgfmath arg={tier #1}{level()},我们得到以下结果:

垂直对齐

完整代码:

\documentclass[tikz,border=5pt,multi]{standalone}
\usepackage{forest}
\standaloneenv{forest}
\begin{document}

\begin{forest}
  for tree={
    draw,
    if={isodd(n_children())}{
      for children={
        if={
          equal(n,int((1+n_children("!u"))/2))
        }{calign with current}{}
      }
    }{},
    align=center,
    child anchor=north,
    tier/.wrap pgfmath arg={tier #1}{level()}
  }
  [,phantom
   [left tree\\(needs additional explanation)
     [some text here]
     [a multiline node\\in the middle]
     [not much]
   ]
   [right tree
     [this\\node\\needs\\five\\lines]
     [this\\one\\only\\four]
     [finally\\just\\three]
   ]
  ]
\end{forest}
\end{document}

应用于具有空节点的原始树,这也会产生更紧凑的结果:

紧凑树

\documentclass[tikz,border=5pt,multi]{standalone}
\usepackage{forest}
\standaloneenv{forest}
\begin{document}

\begin{forest}
  for tree={
    draw,
    if={isodd(n_children())}{
      for children={
        if={
          equal(n,int((1+n_children("!u"))/2))
        }{calign with current}{}
      }
    }{},
    align=center,
    child anchor=north,
    tier/.wrap pgfmath arg={tier #1}{level()}
  }
  [,phantom
    [
      []
      []
      []
    ]
    [
      []
      []
      []
    ]
  ]
\end{forest}

\end{document}

答案2

如果你将xshift=-4.3725cm, red选项添加到正确的节点,你会得到

在此处输入图片描述

这里的问题是,转换会right=of test潜入底层树(或类似的东西)。

嵌套 TikZ 图片从来都不是一个好主意。

根据你想要实现的目标,你可以做类似的事情

\begin{tikzpicture}[nodes=draw, node distance=4cm]
\node (test)          {} child { node {} } child { node {} } child { node {} };
\node [right=of test] {} child { node {} } child { node {} } child { node {} };
\end{tikzpicture}

或者(在本质上,矩阵实际上是一个节点)

\begin{tikzpicture}[nodes=draw]
\matrix [column sep=1cm] {
  \node {} child { node {} } child { node {} } child { node {} }; &
  \node {} child { node {} } child { node {} } child { node {} }; \\
};
\end{tikzpicture}

使用forest包(\usepackage{forest}),你可以做这样的事情:

\begin{forest} /tikz/nodes=draw, for tree={l sep=1cm, s sep=1cm}
[,phantom
 [ [][][]]
 [ [][][]]
]
\end{forest}

相关内容