1

These days I'm typesetting a lot of trees (in the graph-theoretic sense) using pst-jtree, which is essentially a collection of macros over pstricks. So, I might have the following.

\jtree
   \! = {A}! .
   \! = <left>[xunit=5em]{B}!b ^<right>[xunit=5em]{E}!c .
   \!b = : {m} {C} : {n} {D} : {o} {p} .
   \!c = : {q} {F} : {r} {G} : {s} {t} .
\endjtree

enter image description here

These are the easy cases. Sometimes I need to draw a vertex between nodes that are some distance apart. I usually do it with \nccurve, which is neat in the sense that I can use @ labels (or alternatively \rnode) to define the start-end points of a Bezier curve, and then manipulate it with angleA, angleB, and ncurv.

\jtree
   \! = {A}! .
   \! = <left>[xunit=5em]{B}!b ^<right>[xunit=5em]{E}!c .
   \!b = : {m} {C} : {n} {D}@D !d .
   \!c = : {q} {F} : {r} {G} : {s} {t}@t .
   \!d = <left>{o} .
\endjtree
\nccurve[angleA=-45,angleB=90,ncurvA=1.2,ncurvB=1.6]{-}{D:b}{t:t}

enter image description here

However, when trees get to a certain level of complexity, I want to have more control over my curves than I can get with \nccurve (for example, with \nccurve sometimes I have to choose between a curve that crosses over node labels (ugh) or one that has really tight and long arcs (ugh again)).

To me, the obvious solution is to use tikz to define a set of n points and then have it draw a smoothed curve over it.

\begin{tikzpicture}
   \draw plot [smooth,tension=1] coordinates { (0,0) (1,1) (2,-2) (3,0)};
\end{tikzpicture}

enter image description here

However, I don't know how to combine these two strategies. The main problem is that (as far as I know) \draw requires me to define (x,y) coordinates, rather than referring to @ or \rnode labels. Is there a way around this? Specifically, I want to be able to write something like

\begin{tikzpicture}
    \draw plot [smooth,tension=1] coordinates { (D:b) (1,1) (2,-2) (t:t)};
\end{tikzpicture}

The idea being that (0,0) is set to the bottom of the D label, (t:t) is set whatever (x,y) coordinate relative to (0,0), and then (1,1) and (2,-2) are set relative to (0,0), as usual.

  • The first step would be to switch from pstricks to tikz-qtree. Then you might be able to use tikz coordinates from the tree. – John Kormylo Oct 8 '15 at 15:17
  • Or forest. If you are typesetting complex trees, forest is more powerful than tikz-qtree, as I understand it. Both give you the full power of TikZ but forest allows you to manipulate the tree in various ways, to use relative nodes names and node walks etc. – cfr Oct 9 '15 at 1:47
2

If you use forest, you can draw the curve by specifying it as part of the tree. Here, I use the current node's parent anchor ((.parent anchor)) as a value for shift so that the coordinates for the plot can be specified relative to that anchor. I then use the child anchor of a named node, t ((t.child anchor)) to specify the end point for the curve.

\documentclass[tikz,border=20pt]{standalone}
\usepackage{forest}
\begin{document}
\newlength\myex
\settoheight{\myex}{X}
\begin{forest}
  for tree={
    parent anchor=south,
    child anchor=north,
    anchor=mid,
    text height=\myex,
    tier/.wrap pgfmath arg={tier #1}{level()},
    s sep+=15pt,
  }
  [A
    [B
      [m]
      [C
        [n]
        [D, tikz={
          \draw [shift=(.parent anchor)] plot [smooth,tension=1] coordinates { (0,0) +(1.25,-.5) +(2.5,1) (t.child anchor)};
        }
          [o]
          [,phantom]
        ]
      ]
    ]
    [E
      [q]
      [F
        [r]
        [G
          [s]
          [t, name=t]
        ]
      ]
    ]
  ]
\end{forest}
\end{document}

plotted curve in <code>forest</code> tree

The manual for forest is good but a little intense at times. A brief introduction can be found in the second part of my answer to a related question. This explains how to specify a tree using the bracket notation and introduces some basic features of the package.

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.