如何水平移动 tikz 树的子树

如何水平移动 tikz 树的子树

如何tikz在不影响树的其余部分的情况下将树/qtree的子树向右移动?

考虑下面的树:

\documentclass[tikz]{standalone}

\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage{tikz-qtree}
\usetikzlibrary{shapes, trees}

\begin{document}

\begin{tikzpicture}[
  font=\footnotesize,
  edge from parent/.style={draw, edge from parent fork down},
  frontier/.style={distance from root=250},
  level distance=25,
  phrase/.style={draw, ellipse},
  function/.style={draw, rectangle}
  ]
  \Tree
    [.\node[phrase] {S};
      [.\node[function] {SB}; Tim ]
      [.\node[function] {HD}; wurde ]
      [.\node[function] {OC};
        [.\node[phrase] {VP};
          [.\node[function] {SBP};
            [.\node[phrase] {PP};
              [.\node[function] {AC}; von ]
              [.\node[function] {NK};
              [.\node[phrase] {NP};
                [.\node[function] {NK}; den ]
                [.\node[function] {NK}; Hunden ]
                [.\node[function] {RC};
                  [.\node[phrase] {S};
                    [.\node[function] {SB}; ,die ]
                    [.\node[function] {MO}; laut ]
                    [.\node[function] {HD}; bellten. ]
                  ]
                ]
              ]
            ]
          ]
        ]
        [.\node[function] {HD}; erschreckt ]
      ]
    ]
  ]
\end{tikzpicture}
\end{document}

最后,HD>erschreckt必须位于和之间NK>HundenRC subtree即树枝必须相交。我知道在tikz树中这是不可能的。

我可以把 放在树HD>erschreckt外面tikz,稍后再画出来。但是,这需要RC subtree将 移到右边,为 的绘制腾出空间HD>erschreckt。这就是我被困住的地方。

[missing]之间的节点确实会导致 的右移,但也会将和向左移动,所以这似乎不是一个选择。NK>HundenRC subtreeRC subtreeNK>denNK>Hunden

所以再说一遍:我怎样才能将其RC subtree向右移动而不影响树的其余部分?

(使交叉点在视觉上明确可获得加分。)

感谢您的帮助

答案1

也许最好的做法是将作品放在erschrekt您想要的位置,即 的左侧,die。由于\node是 的缩写,因此\path node您可以在之后添加更多材料以绘制更多内容。使用positioning库,您可以将节点彼此相对放置。将此代码放在适当的位置tikz将负责移动树的其余部分:

示例输出

\documentclass[tikz]{standalone}

\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage{tikz-qtree}
\usetikzlibrary{shapes, trees,calc,positioning}

\begin{document}

\begin{tikzpicture}[
  font=\footnotesize,
  edge from parent/.style={draw, edge from parent fork down},
  frontier/.style={distance from root=250},
  level distance=25,
  phrase/.style={draw, ellipse},
  function/.style={draw, rectangle}
  ]
  \Tree
    [.\node[phrase] {S};
      [.\node[function] {SB}; Tim ]
      [.\node[function] {HD}; wurde ]
      [.\node[function] {OC};
        [.\node[phrase] {VP};
          [.\node[function] {SBP};
            [.\node[phrase] {PP};
              [.\node[function] {AC}; von ]
              [.\node[function] {NK};
              [.\node[phrase] {NP};
                [.\node[function] {NK}; den ]
                [.\node[function] {NK}; Hunden ]
                [.\node[function] {RC};
                  [.\node[phrase] {S};
                    [.\node[function] {SB}; \node (die) {,die}
                    node[node distance=0cm,left=of die] (ert)
                      {\strut erschreckt}; ]
                    [.\node[function] {MO}; laut ]
                    [.\node[function] {HD}; bellten. ]
                  ]
                ]
              ]
            ]
          ]
        ]
        [.\node[function] (ers) {HD}; ]
      ]
    ]
  ];
  \draw[red] (ers.south) |- ($(ers.south)!0.65!(ert.north)$)-| (ert.north);
\end{tikzpicture}
\end{document}

请注意,我添加了\strut新节点以确保其具有统一的深度。其他tikz方法是text height/depth一般地指定您的节点。

第二种方法如果您需要进一步调整路径和节点的位置,那么我认为放弃树函数并从头开始绘制图表实际上更容易。树函数对子节点的放置方法相当简单。以下是执行此操作的一种方法:

第二个示例输出

\documentclass{article}

\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{shapes,calc,matrix}

\begin{document}

\begin{tikzpicture}[font=\footnotesize,anchor=base,
  phrase/.style={draw, ellipse},
  function/.style={draw, rectangle}]
  \matrix (b) [matrix of nodes,column sep=1ex,text height=7pt,text depth=2pt] {
  Tim
  &wurde
  &von
  &den
  &Hunden
  &erschrekt
  &,die
  &laut
  &bellten \\
  };
  \node[function] (19) at (b-1-1 |- 0,9) {SB};
  \node[function] (29) at (b-1-2 |- 0,9) {HD};
  \node[function] (35) at (b-1-3 |- 0,5) {AC};
  \node[function] (43) at (b-1-4 |- 0,3) {NK};
  \node[function] (53) at (b-1-5 |- 0,3) {NK};
  \node[function] (67) at (b-1-6 |- 0,7) {HD};
  \node[function] (71) at (b-1-7 |- 0,1) {SB};
  \node[function] (81) at (b-1-8 |- 0,1) {MO};
  \node[function] (91) at (b-1-9 |- 0,1) {HD};
  \node[phrase] (S2) at ($(71.base)!0.5!(91.base) + (0,1)$) {S};
  \node[function] (R3) at ($(S2.base) + (0,1)$) {RC};
  \node[phrase] (N4) at ($(43.base)!0.3!(R3.base) + (0,1)$) {NP};
  \node[function] (N5) at ($(N4.base) + (0,1)$) {NK};
  \node[phrase] (P6) at ($(35.base)!0.5!(N5.base) + (0,1)$) {PP};
  \node[function] (S7) at ($(P6.base) + (0,1)$) {SBP};
  \node[phrase] (V8) at ($(S7.base)!0.5!(67.base) + (0,1)$) {VP};
  \node[function] (O9) at ($(V8.base) + (0,1)$) {OC};
  \node[phrase] (S10) at ($(19.base)!0.5!(O9.base) + (0,1)$) {S};
  \draw (b-1-1) -- (19) -- +(0,0.5) -| (S10);
  \draw (b-1-2) -- (29) -- +(0,0.5);
  \draw (b-1-3) -- (35) -- +(0,0.5) -| (P6) -- (S7) -- +(0,0.5) -| (V8)
  -- (O9) -- +(0,0.5) -| (S10);
  \draw (b-1-4) -- (43) -- +(0,0.5) -| (N4) -- (N5) -- +(0,0.5) -|
  (P6);
  \draw (b-1-5) -- (53) -- +(0,0.5);
  \draw (b-1-7) -- (71) -- +(0,0.5) -| (S2) -- (R3) -- +(0,0.5) -| (N4);
  \draw[white,double=black,line width=3pt,double distance=0.4pt,
    shorten >=0.2pt] (b-1-6) -- (67); \draw (67) -- +(0,0.5) -| (V8);
  \draw (b-1-8) -- (81) -- +(0,0.5);
  \draw (b-1-9) -- (91) -- +(0,0.5) -| (S2);
\end{tikzpicture}

\end{document}

我习惯于\matrix均匀地放置单词,并调整列间距以避免在图表中进一步重叠。然后,其他节点相对于矩阵条目放置,参考节点的基点以保持一致性。

calc库允许我们使用诸如表示和($(A)!0.5!(B)$)中间点的表达式;该语法(不需要)找到 x 坐标为且 y 坐标为 的点。 (A)(B)(A |- B)calc(A)(B)

我将节点垂直放置在(0,n)n整数对应的级别上,并用以级别号结尾的名称标记它们;从节点出来的垂直线然后延伸到高度,(0,n+0.5)然后连接到水平条;这些水平条只需要从其左端和右端的节点绘制。最后,交叉线被“双倍”绘制,带有宽的白色背景,在它穿过的水平线上形成一个洞。我还将它缩短了一点,这样它就不会与节点的边界重叠。 0.4pt在这些情况下,已用作标准参考线宽。

答案2

forest使您可以将图表指定为树,同时仍将子树移动到所需位置。诀窍是反向操作。RC我们首先通过将其创建为 的兄弟节点来确保将其放置在我们想要的位置,而不是移动子树的位置HD。然后我们通过更改子树与其他节点的关系来“移动”子树:我们根据需要使其成为 的子节点NP

这样做可以确保节点的位置已设置子树被“移动”。本质上,这意味着它与其他节点的关系发生了变化,但它的位置没有改变:它在树结构方面移动,但在空间布局方面没有移动。因此,移动是在最后一刻完成的,就在使用钩子最终绘制树之前before drawing tree

节点phantom用于帮助确定VP节点相对于其子节点的间距,SBP并且HD

树也可以指定得更加紧凑,尤其是通过指定几个 TikZ 样式。

\documentclass[tikz,border=5pt,multi]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{forest}
\usetikzlibrary{shapes}

\begin{document}
\tikzset{
  phrase/.style={draw, ellipse},
  function/.style={draw, rectangle}
}
\begin{forest}
  for tree={
    font=\footnotesize,
    edge path={
      \noexpand\path [draw, \forestoption{edge}] (!u.parent anchor) -- +(0,-5pt) -| (.child anchor)\forestoption{edge label};
    },
    parent anchor=south,
    child anchor=north,
    if n children=0{tier=terminus}{},% all terminal nodes need to be aligned
  }
    [S, phrase,
      [SB, function,
        [Tim]
      ]
      [HD, function,
        [wurde]
      ]
      [OC, function,
        [VP, phrase,
          [SBP, function,
            [PP, phrase,
              [AC, function,
                [von]
              ]
              [NK, function,
              [NP, phrase, before drawing tree={append={rc}}% this moves the subtree in terms of the tree structure, but it is done very late so it doesn't change its spatial location
                [NK, function, tier=tier rc
                  [den]
                ]
                [NK, function,
                  [Hunden]
                ]
              ]
            ]
          ]
        ]
        [, phantom, calign with current]
        [HD, function,
          [erschreckt]
        ]
        [RC, function, name=rc, tier=tier rc% name the node so we can move it and fix the horizontal alignment using tier specification
          [S, phrase,
            [SB, function,
              [{,die}]
            ]
            [MO, function,
              [laut]
            ]
            [HD, function,
              [bellten.]
            ]
          ]
        ]
      ]
    ]
  ]
\end{forest}
\end{document}

无空间移动的结构

相关内容