5

I try to draw a picture that is supposed to explain the sentence

dass er das Lied wird haben singen müssen

that he the song will have sing must

The idea is to write down the sentence and have the tree from the code below that shows the dominance relations that is which verb dominates which other verb. Directly to the right of singen I want to have an additional node for müssen and to left of it one for haben and to the left of haben one for wird. The verbs that are in the trees should be connected to these nodes with arrows. Is this possible? I tried something (see code), but the new nodes do not come out at the same baseline as singen.

Maybe I have to redraw everything in some other way?

    \documentclass{article}

\usepackage{tikz-qtree}

\begin{document}

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

\end{document}

This is what it should look like:

enter image description here

3

3 Answers 3

6

A simple idea: typeset your sentence in a matrix of nodes. This kind of tikz object automatically assigns a name to each of its components. In the following example I named the matrix M, so the elements of the first (and only) row are named M-1-1, M-1-2 and so on. This makes easy to add more words on top of M-1-7 and make the connections:

\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}

Result

3

Hm, a tree doesn’t look right. What about chains?

We install two chains:

  1. Chain sentence goes to the right, sentence going base right,
  2. Chain verbs goes up, verbs going above.

On the sentence chain we simply place the parts daß er das Lied, wird, haben, singen, können, for items that have an Umlaut or an Eszett we assign a safe name without them (there are possible other solutions but those would make accessing those nodes harder). If we do not specify a \Name in the \foreach loop the \Item text will simply be used.

The horizontal node distance .3333em is set so that the nodes are placed as they would in a sentence, for this we also set the inner xsep and the outer xsep to zero. You can check this behavior by placing another node so that it overlaps with the sentence:

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

The vertical part of the node distance, 1.5\baselineskip, is chosen randomly, the inner ysep is half the default size. The outer ysep is also set to zero (we don’t have any drawn nodes).

The nodes of the vertical chain are automatically connected by the join option (which uses the every join style). The connections to the nodes in the sentence are also made in the second loop.

The special arc and line style makes sure that the arcs are the size of a quarter circle with the biggest possible radius. An optional arc and line maximum value can be assign, though.

If we set arc and line maximum to a very small value, say 6pt (the default for rounded corners) we can mimic a basic -| path with said rounded corners. No need for the calc library and the let … in stuff.
With arc and line maximum set to zero we get the basic -| path with sharp corners. Like above, we wouldn’t need calc and those calculations.

Personally, I prefer the blue variant with a small rounded corners radius.

Code

\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}

Output

enter image description here

1
  • This can be automated if needed with a syntax like \funnyTree{daß er das Lied !wird !haben ?singen !können} where ! marks the words that should placed above the ? word. Jul 4, 2013 at 1:04
3

If you \usetikzlibrary{positioning}, you can define nodes in terms of other nodes. Thus, if you define nodes inside of the tree, you can position nodes outside of the tree relative to the nodes inside of the tree. This means that you will have to play around with the spacing manually, but it does provide a solution. Here is an MWE that should work for you:

Update: As @Qrrbrbirlbel points out in the comments, the 'g' in 'singen' throws off the vertical alignment of the nodes, relative to one another. This has been fixed below by using base left and base right to align the nodes with one another.

\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}

enter image description here

1
  • If you use base left and base right the nodes will be correctly aligned vertically (the g in singen adds a depth which affects the vertical center of the node). Jul 4, 2013 at 1:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .