6

I have to draw pictures like the following a lot:

enter image description here

I want to use tikz-qtree, since I have a lot of trees and this package simplifies things considerably. Right now I use the following code, since it is not possible to have nodes in nodes and tikz-qtree makes the tree elements nodes. So I use the grid code from How can I show coordinates by grid in TikZ automatically? and draw lines from absolute positions to other absolute positions. This is time consuming, it never looks right, and I have to redo it when the font size changes. Is there a better way to do this?

\documentclass{minimal}

\usepackage{tikz-qtree}
\tikzset{every roof node/.append style={inner sep=0.1pt,text height=2ex,text depth=0.3ex}}

\newcommand{\sliste}[1]{%
\mbox{%
$\left\langle\mbox{\scshape #1}\right\rangle$}%
}


\begin{document}

\begin{tikzpicture}
\tikzset{level 1+/.style={level distance=3\baselineskip}}
\tikzset{frontier/.style={distance from root=12\baselineskip}}
%\draw (-3,-5) to[grid with coordinates] (4,0);
\Tree[.S
        [.{V \sliste{ S$\!/\!/$V }} 
          [.V liest$_k$ ] ]
        [.{S$\!/\!/$V}
           [.NP Jens ]
           [.{V$'$$\!/\!/$V}
             [.NP \edge[roof]; {das Buch} ]
             [.{V$\!/\!/$V} \_$_k$ ] ] ] ]
\draw[semithick,<->,color=green] (3.1,-3.9) ..controls +(south east:.5) and +(south west:.5)..(2.7,-3.9);
\draw[semithick,<->,color=green] (3.5,-3.7) ..controls +(east:.5) and +(east:.5)..(2.8,-2.5);
\draw[semithick,<->,color=green] (2.8,-2.3) ..controls +(east:.5) and +(east:.5)..(1.7,-1.1);
\draw[semithick,<->,color=green] (1.5,-0.9) ..controls +(north:.5) and +(north:.5)..(-0.8,-0.9);
\draw[semithick,<->,color=green] (-0.7,-1.1) ..controls +(south east:.2) and +(north east:.5)..(-1.0,-2.4);
\end{tikzpicture}



\end{document}

Edit:

I followed the suggestion and used tikzmark and \subnode:

\documentclass{minimal}


\usepackage{tikz-grid}


\usepackage{tikz-qtree}
\tikzset{every roof node/.append style={inner sep=0.1pt,text height=2ex,text depth=0.3ex}}

\usetikzlibrary{tikzmark}

\newcommand{\sliste}[1]{%
\mbox{%
$\left\langle\mbox{\scshape #1}\right\rangle$}%
}


\begin{document}

\begin{tikzpicture}
\tikzset{level 1+/.style={level distance=3\baselineskip}}
\tikzset{frontier/.style={distance from root=12\baselineskip}}
\Tree[.S
        [.{V \sliste{ S$/\!/$\subnode{vcomp}{V} }} 
          [.{\subnode{vliest}{V}} liest$_k$ ] ]
        [.{S$/\!/$\subnode{vs}{V}}
           [.NP Jens ]
           [.{V$'$$\!/\!/$\subnode{vbar}{V}}
             [.NP \edge[roof]; {das Buch} ]
             [.{\subnode{vzero}{V}$\!/\!/$\subnode{vdsl}{V}} \_$_k$ ] ] ] ]
\draw[semithick,<->,color=green] (vcomp.east) ..controls +(south east:.2) and +(north east:.5)..(vliest.east);
\end{tikzpicture}



\end{document}

The result is funny: It works if I use pdflatex and have no AUX file. As soon as there is an AUX file, the code produces two pages or the arrows are distributed over the page. Hm.

Edit 2:

I followed Allen Mun's suggestion and worked further on similar examples:

\documentclass{minimal}


\usepackage{tikz-grid}


\usepackage{tikz-qtree}
\tikzset{every roof node/.append style={inner sep=0.1pt,text height=2ex,text depth=0.3ex}}

\usetikzlibrary{tikzmark}

\newcommand{\sliste}[1]{%
\mbox{%
$\left\langle\mbox{\scshape #1}\right\rangle$}%
}

\newcommand{\trace}{\raisebox{0.2ex}{\_}\rule{0cm}{0.7em}}

\begin{document}

\begin{tikzpicture}[
level 1+/.style={level distance=3\baselineskip},
frontier/.style={distance from root=15\baselineskip},
connect/.style={semithick,<->,color=green}]
\Tree[.S
        [.\node (NP) {NP}; \edge[roof]; {das Buch} ]
        [.\node (S/NP) {S/NP};
          [.{V \sliste{ S/$\!$/V }} 
            [.V liest$_k$ ] ]
           [.\node (S//V/NP) {S$/\!/$V/NP};
             [.\node (NP/NP) {NP/NP}; \trace{} ]
             [.{V$'$$\!/\!/$V}
               [.NP Jens ]
               [.{V$\!/\!/$V} \_$_k$ ] ] ] ] ] ]
\draw[connect] (NP/NP) [bend right] to (S//V/NP.south east);
\draw[connect] (S//V/NP.north east) [bend right] to (S/NP.east);
\draw[connect] (S/NP.north east) [bend right] to (NP);
\end{tikzpicture}


\end{document}

Second figure with other information to be shared

The intention of this figure is to show that the NP information is shared. So here it would be great to be able to connect to the NP nodes directly.

1
  • 1
    Does the forest package qualify as a “better way to do this”? You can give nodes in tikz-qtree names if you use the usual \node (<name>) {<text>}; syntax. For referencing only letters of one node, you may be able to use \subnode from the tikzmark library/package. – Qrrbrbirlbel Dec 13 '13 at 15:37
4

Even with forest which can do a lot of things automatically, a certain amount of manual tweaking is needed. There is just no way for it to know what the content of the node means. However, forest does allow you to integrate the loops into the tree which may be attractive in some cases.

For example:

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{tikzmark, arrows.meta, bending}
\usepackage{forest}

\begin{document}

  \tikzset{
    connect/.style={{Stealth[bend]}-{Stealth[bend]}, draw=green, shorten <=-3pt, shorten >=-3pt}
  }
  \newlength\txtht
  \settoheight\txtht{B}
  \begin{forest}
    for tree={
      parent anchor=south,
      child anchor=north,
      if n children=0{tier=t, text height=\txtht}{},
    },
    [S
      [NP, tikz={\draw [connect] (.north east) [bend left] to ([xshift=-10pt]np1.north east);}
        [das Buch, triangle]
      ]
      [S/NP, name=np1, tikz={\draw [connect] (.east) [bend left] to ([xshift=-10pt]np2.north east);}
        [V (S//V), tikz={\draw [connect] ([xshift=-10pt].south east) [bend left] to (v1.north east);}
          [V, name=v1
            [liest$_k$]
          ]
        ]
        [S//V/NP, name=np2
          [NP/NP, tikz={\draw [connect] (.east) [bend right] to ([xshift=-10pt]np2.south east);}
            [-]
          ]
          [V$'$//V, tikz={\draw [connect] (.east) [bend left] to ([xshift=-5pt]v2.north east);}
            [NP
              [Jens]
            ]
            [V//V, name=v2, tikz={\draw [connect] ([xshift=5pt].south west) [out=-105, in=-75] to ([xshift=-5pt].south east);}
              [${}_{-k}$]
            ]
          ]
        ]
      ]
    ]
  \end{forest}

\end{document}

<code>forest</code> connections

8

There's no need to be so complicated. Any tikz-qtree node label can be an explicit TikZ \node command, so you can name your nodes without too much extra work. I've also used a simpler syntax for the arrows, so that you don't need to specify controls (and which I think makes the arrows a little nicer too.) There's no need for subnodes even for the smaller arrows, since they can be shortened with the shorten key (as in the V//V arrow in the example.)

As Qrrbrbirlbel notes, using the forest package makes this slightly easier, since it allows you to simply specify a label for any node without using an explicit \node command, but otherwise the basic procedure is the same.

\documentclass{article}

\usepackage{tikz-qtree}
\tikzset{every roof node/.append style={inner sep=0.1pt,text height=2ex,text depth=0.3ex}}

\newcommand{\sliste}[1]{%
\mbox{%
$\left\langle\mbox{\scshape #1}\right\rangle$}%
}


\begin{document}


\begin{tikzpicture}[
level 1+/.style={level distance=3\baselineskip},
frontier/.style={distance from root=12\baselineskip},
connect/.style={semithick,<->,color=green}]
\Tree[.S
        [.\node (V1) {V \sliste{ S$\!/\!/$V }}; 
          [.\node(V){V}; liest$_k$ ] ]
        [.\node (S/V) {S$\!/\!/$V};
           [.NP Jens ]
           [.\node(V'V) {V$'$$\!/\!/$V};
             [.NP \edge[roof]; {das Buch} ]
             [.\node(V/V) {V$\!/\!/$V}; \_$_k$ ] ] ] ]
\draw[connect,shorten >=.5em,shorten <=.5em] (V/V.south east) [bend left] to (V/V.south west) ;
\draw[connect] (V/V.north east) [bend right] to (V'V.east);
\draw[connect] (V'V.north east) [bend right] to (S/V.east);
\draw[connect,shorten <=.5em] (S/V.north east) to [bend right] (V1) ;
\draw[connect] (V1) to [bend left] (V);
\end{tikzpicture}




\end{document}

output of code

3
  • Thanks, it does look better than what I had, but it is not exactly what I was looking for. What should be connected with arrows are the Vs behind the //. In the leftmost branch you connected the S in the mother node with the V in the daughter. The V in S//V is connected to the S to the right, rather than to the V, following the S. To fix this, I would have to shift the node by hand, right? And this would involve manual labor and be font dependent, wouldn't it? – Stefan Müller Dec 15 '13 at 11:21
  • @StefanMüller To the extent that you can just use anchors such as .north east to position the arrows I think you can still achieve what you want. Does the updated version work better? I've also changed the shorten parameters to use em, which is font dependent, and therefore should adjust with font changes better. Also, surely the arrows are just conventional, so if readers understand their purpose, is the fact that they are not perfectly aligned critical? – Alan Munn Dec 15 '13 at 12:45
  • OK. Thanks! The line going from V to V1 should end under the V following the // and the lines going downward from S/V to V'V and from V'V to V/V should end over the Vs. Is this possible? Insisting on this seems to be snobbish, but the picture is about information being shared and it is just this V behind the // that is shared and I want this to be reflected in the picture. – Stefan Müller Dec 15 '13 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.