Добавление узлов за пределами дерева и рисование стрелок к ним с помощью tikz-qtree и tikz

Добавление узлов за пределами дерева и рисование стрелок к ним с помощью tikz-qtree и tikz

Я пытаюсь нарисовать рисунок, который должен объяснить предложение.

das er das Lied wird haben singen müssen

что он песню придется петь должен

Идея состоит в том, чтобы записать предложение и получить дерево из кода ниже, которое показывает отношения доминирования, то есть какой глагол доминирует над каким другим глаголом. Прямо справа от singen я хочу иметь дополнительный узел для müssen, слева от него один для haben и слева от haben один для wird. Глаголы, которые находятся в деревьях, должны быть связаны с этими узлами стрелками. Возможно ли это? Я пробовал кое-что (см. код), но новые узлы не выходят на той же базовой линии, что и singen.

Может быть, мне придется все перерисовать как-то по-другому?

    \documentclass{article}

\usepackage{tikz-qtree}

\begin{document}

\begin{tikzpicture}
\Tree [.wird
          [.haben
              [.muessen singen ] ] ] \node[anchor=east]{muessen}; 
\end{tikzpicture}

\end{document}

Вот как это должно выглядеть:

введите описание изображения здесь

решение1

Простая идея: наберите предложение в matrix of nodes. Этот тип объекта tikz автоматически присваивает имя каждому из его компонентов. В следующем примере я назвал матрицу M, поэтому элементы первой (и единственной) строки называются M-1-1, M-1-2и так далее. Это позволяет легко добавлять больше слов поверх M-1-7и устанавливать связи:

\usetikzlibrary{matrix, positioning}
\begin{tikzpicture}[shorten >=1mm]
\matrix[name=M, matrix of nodes, inner sep=0pt, column sep=1ex]{
  dass & er & das & Lied & wird & haben & singen & m\"ussen \\
};

\node [anchor=base, above=2em of M-1-7.base]  (mussen) {m\"ussen};
\node [anchor=base, above=2em of mussen.base] (haben)  {haben};
\node [anchor=base, above=2em of haben.base]  (wird)   {wird};
\draw[->] (wird)   to[out=180,in=90] (M-1-5);
\draw[->] (haben)  to[out=180,in=90] (M-1-6);
\draw[->] (mussen) to[out=0,in=90]   (M-1-8);
\draw (wird) --(haben) -- (mussen) -- (M-1-7);
\end{tikzpicture}

Результат

решение2

Хм, дерево выглядит не так. А как насчет цепей?

Мы устанавливаем две цепи:

  1. Цепь sentenceидет направо, sentence going base right,
  2. Цепь verbsидет вверх, verbs going above.

В sentenceцепочке мы просто размещаем части daß er das Lied, wird, haben, singen, könnenдля элементов, которые имеют умлаут или эсцет, мы назначаембезопасныйимя без них (возможны и другие решения, но они затруднят доступ к этим узлам). Если мы не укажем a \Nameв \foreachцикле, \Itemтекст будет просто использоваться.

Расстояние по горизонтали между узлами .3333emзадается так, чтобы узлы размещались так, как они размещались бы в предложении, для этого мы также устанавливаем inner xsepи outer xsepна ноль. Вы можете проверить это поведение, разместив другой узел так, чтобы он перекрывался с предложением:

\node[anchor=text] at (sentence-begin.text) {da\ss\space er das Lied wird haben singen k\"onnen};

Вертикальная часть node distance, 1.5\baselineskip, выбирается случайным образом, inner ysepсоставляет половину размера по умолчанию. outer ysepТакже установлен на ноль (у нас нет нарисованных узлов).

Узлы вертикальной цепочки автоматически соединяются опцией join(использующей every joinстиль). Соединения с узлами в предложении также производятся во втором цикле.

Специальный arc and lineстиль гарантирует, что дуги будут размером с четверть круга с максимально возможным радиусом. arc and line maximumОднако можно задать необязательное значение.

Если мы установим arc and line maximumочень маленькое значение, скажем 6pt(значение по умолчанию для rounded corners), мы можем имитировать базовый -|путь с указанными закругленными углами. Нет необходимости в calcбиблиотеке и let … inпрочем.
При arc and line maximumустановке на ноль мы получим базовый -|путь с острыми углами. Как и выше, нам не понадобятся calcи эти вычисления.

Лично мне больше нравится синий вариант с небольшим rounded cornersрадиусом.

Код

\documentclass[tikz,convert=false]{standalone}
\usetikzlibrary{chains,calc}
\tikzset{
  /pgf/arc and line maximum/.initial=+1000pt,
  arc and line/.style={
    to path={
      let
        \p{@end}=(\tikztotarget.north),
        \p{@aux1}=($(\tikztostart)-(\p{@end})$),
        \p{@start}=(node cs: name=\tikztostart, anchor={\x{@aux1} < 0pt ? +0 : +180}),
        \n{@aux2}={min(\pgfkeysvalueof{/pgf/arc and line maximum},abs(\x{@start}-\x{@end}),abs(\y{@start}-\y{@end})-.1pt))}
      in
      { [rounded corners=\n{@aux2}] -| (\tikztotarget) }
    }},
  special curve 0/.style={draw,->,arc and line},
  special curve 1/.style={
    special curve 0,
    arc and line maximum=+6pt},
  special curve 2/.style={
    special curve 0,
    arc and line maximum=+0pt},
  every sentence and verb node/.style={
    inner ysep=+.1667em,
    outer ysep=+0pt},
  sentence node/.style={
    every sentence and verb node,
    inner xsep=+0pt,
    outer xsep=+0pt,
    on chain=#1},
  sentence node/.default=sentence,
  verb node/.style={
    every sentence and verb node,
    on grid,
    text depth=+0pt,
    join,
    on chain=#1},
  verb node/.default=verbs
}
\begin{document}
\begin{tikzpicture}[
  node distance=1.5\baselineskip and width(" ")*1pt,
  start chain=sentence going base right,
  start chain=verbs going above,
  every join/.style={draw}
]
\foreach \Item/\Name in {da\ss\space er das Lied/dass,wird,haben,singen,k\"onnen/konnen}
  \node [sentence node, alias=s-\Name] {\Item};
\chainin[on chain=verbs] (s-singen);
\foreach \Item/\Name in {k\"onnen/konnen,haben,wird} {
  \node [verb node, alias=v-\Name] {\Item}
    edge[special curve 2,green] (s-\Name)
    edge[special curve 1,blue]  (s-\Name)
    edge[special curve 0]       (s-\Name);
}
\end{tikzpicture}
\end{document}

Выход

введите описание изображения здесь

решение3

Если вы \usetikzlibrary{positioning}, вы можете определить узлы в терминах других узлов. Таким образом, если вы определяете узлы внутри дерева, вы можете расположить узлы снаружи дерева относительно узлов внутри дерева. Это означает, что вам придется вручную поиграться с интервалом, но это дает решение. Вот MWE, который должен вам подойти:

Обновлять: Как отмечает @Qrrbrbirlbel в комментариях, «g» в «singen» нарушает вертикальное выравнивание узлов относительно друг друга. Это было исправлено ниже с помощью base leftи base rightдля выравнивания узлов друг относительно друга.

\documentclass{article}

\usepackage{qtree}
\usepackage{tikz}
\usepackage{tikz-qtree,tikz-qtree-compat}
\tikzset{every tree node/.style={align=center, anchor=north}}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}

\Tree [.\node(1){wird};
          [.\node(2){haben};
              [.\node(3){m\"{u}ssen}; \node(4){singen}; ] ] ]

\node(5)[base left=1.9cm of 4]{dass er das Lied};
\node(6)[base left=1.1cm of 4]{wird};
\node(7)[base left=.1cm of 4]{haben};
\node(8)[base right=.1cm of 4]{m\"{u}ssen};
\draw[->] (1)..controls +(west:1) and +(north:1)..(6);
\draw[->] (2)..controls +(west:1) and +(north:1)..(7);
\draw[->] (3)..controls +(east:1) and +(north:1)..(8);

\end{tikzpicture}

\end{document}

введите описание изображения здесь

Связанный контент