6

Take the following code:

\documentclass{article}
\usepackage{forest, amsmath}
\begin{document}
    \begin{forest} for tree = {parent anchor = south, child anchor = north, s sep = 0em}
        [, phantom
            [a]
            [r]
            [c]
            [h]
            [i]
            [p]
            [$\stackrel{*}{\text{e}}$
                [$\stackrel{*}{\text{H}}$]
            ]
            [l]
            [a
                [L]
            ]
            [g]
            [o]
        ]
    \end{forest}
\end{document}

enter image description here

It creates an association line between the two starred elements, and between a and L. In order to get the stars above the characters, I had to go into math mode (which bugs me, but that is the recommended way).

But the star gives the H extra height, and so the character L is aligned with the top of the H + * combination. It obviously can't look like that.

A simple fix is to add a phantom star above the L as well, with $\stackrel{\phantom{*}}{\text{L}}$. I get this:

enter image description here

This looks much better, but now the line from the a to the L is too short. It should be just as close to the north edge of the L as the other line is to the north edge of the *.

I assume the proper way to go about this is to manually give the length of the arrow (or arrows). How can I do that? Or is there a better solution?

Sverre
  • 20,729

3 Answers3

8

There are two parameters l and l sep. Parameter l tries to keep the reference points of the child nodes a the same vertical distance, whereas l sep ensures a minimal distance between the parent and child node. The H with star has a large height, therefore, it is moved down because of l sep.

In this case, it is probably enough to set l sep to zero (assuming there are not nodes with an exceptional large height).

The following example also uses a different method to put the star on top of a letter to avoid the extra height that is added by the method with \stackrel.

\documentclass{article}
\usepackage{forest}

\newcommand*{\starontop}[1]{%
  \begingroup
    \renewcommand*{\arraystretch}{0}%
    \begin{tabular}[b]{@{}c@{}}\scriptsize*\\#1\end{tabular}%
  \endgroup
}

\begin{document}
    \begin{forest} for tree = {l sep=0pt}
        [, phantom
            [a]
            [r]
            [c]
            [h]
            [i]
            [p]
            [\starontop{e}
                [\starontop{H}]
            ]
            [l]
            [a
                [L]
            ]
            [g]
            [o]
        ]
    \end{forest}
\end{document}

Result

Heiko Oberdiek
  • 271,626
  • You could just use the align option and wrap the content to add the asterisk. This way you could use a style rather than needing a wrapper of any kind. – cfr Sep 03 '17 at 01:34
  • @cfr (a) the star has a smaller size, (b) a two-line entry has the height of two table rows with too much space between the components and above and below the composite symbol unless \renewcommand*{\arraystretch}{0} as in \starontop is used. – Heiko Oberdiek Sep 03 '17 at 05:28
  • (a) isn't a problem as there's no reason you can't keep the size change. But you're right that (b) probably does make the macro approach easier. You could do it slightly more elegantly as a style, but it probably isn't worth the trouble unless you need to use this over and over. (And elegance is clearly partly a matter of taste, so you may well consider your approach more elegant than the alternative.) – cfr Sep 03 '17 at 13:21
4

The simplest fix (assuming there are no hidden complications in your real tree) is probably to put all nodes in a level in a single tier and to anchor all nodes using mid.

aligned nodes

\documentclass[border=10pt]{standalone}
\usepackage[linguistics]{forest}
\usepackage{amsmath}
\begin{document}
\begin{forest}
  for tree={%
    s sep'=0em,
    tier/.option=level,
    anchor=mid,
  },
  [, phantom
    [a]
    [r]
    [c]
    [h]
    [i]
    [p]
    [$\stackrel{*}{\text{e}}$
      [$\stackrel{*}{\text{H}}$]
    ]
    [l]
    [a
      [L]
    ]
    [g]
    [o]
  ]
\end{forest}
\end{document}
cfr
  • 198,882
  • I get the same result by just adding tier/.option = level to my code. What does the anchor = mid do (I see no difference with it), and similarly the [linguistics] option of forest? – Sverre Sep 03 '17 at 13:07
  • @Sverre With linguistics, you don't need to keep setting parent anchor=children, child anchor=parent. Moreover, you get various other defaults and linguistics-friendly options. For example, sn edges is default. anchor=mid doesn't make a difference here, but it will if you have node contents of different depths (as opposed to different heights). – cfr Sep 03 '17 at 13:23
  • What does s sep'=0em do that's different from s sep=0em? I see no difference in my output. – Sverre Sep 17 '17 at 14:23
  • 1
    @Sverre It is faster. The ' uses a TeX assignment. Otherwise, it use PGF maths, which is very slow. For a single instance, the difference will obviously be negligible, but negligible differences add up in surprising ways. The output will be identical. – cfr Sep 17 '17 at 17:30
2

Try using l sep:

\documentclass{article}
\usepackage{forest, amsmath}
\begin{document}
    \begin{forest} for tree = {parent anchor = south, child anchor = north, s sep = 0em, }
        [, phantom
            [a]
            [r]
            [c]
            [h]
            [i]
            [p]
            [$\stackrel{*}{\text{e}}$
                [$\stackrel{*}{\text{H}}$]
            ]
            [l]
            [a,for tree={l sep= 0.62cm}
               [L]
            ]
            [g]
            [o]
        ]
    \end{forest}
\end{document}

Result:

enter image description here

Edit

The problem is that in g's child (if one or more) you have to redefine l sep. And after that... o needs different l sep too. But then it works for more than one children too:

\documentclass{article}
\usepackage{forest, amsmath}
\begin{document}
    \begin{forest} for tree = { parent anchor = south, child anchor = north,s sep = 0em,}
        [,phantom
            [a]
            [r]
            [c]
            [h]
            [i]
            [p]
            [$\stackrel{*}{\text{e}}$
                [$\stackrel{*}{\text{H}}$]
            ]
            [l]
            [a,for tree={l sep= 0.66cm}
               [L] [M]
            ]
            [g,for tree={l sep= 0.60cm}
             [G] [F]
            ]
            [o]
            [m,for tree={l sep= 0.66cm}
            [S][J]]
        ]
    \end{forest}
\end{document}
koleygr
  • 20,105