2

I want to grow a tree that has some nodes empty/missing so that the lines directly connect:

\begin{tikzpicture}
    \coordinate
    child {
      child {node {pAp} edge from parent node[left] {x}}
      child {node {aaa} edge from parent node[left] {d}}
      child {node {AAA} edge from parent node[right] {y}}
    edge from parent node[left] {z}}
    child {node {} edge from parent node[right] {w}};
  \end{tikzpicture}

The problem is that the position of "z" and "w" is not horizontally aligned because tikz treats the edge to an empty child as longer and lowers the position of the node. I tried to play with options such as "parent anchor" and "child anchor" but I just didn't manage to make it work. I could place the node manually but that would be very bothering when editing the tree.

3 Answers 3

3

You can change the empty node to a coordinate:

enter image description here

\begin{tikzpicture}
    \coordinate
    child {
      child {node {pAp} edge from parent node[left] {x}}
      child {node {aaa} edge from parent node[left] {d}}
      child {node {AAA} edge from parent node[right] {y}}
    edge from parent node[left] {z}}
    child {coordinate edge from parent node[right] {w}};
  \end{tikzpicture}
4
  • This works well when the node following "z" and "w" are both empty. It turns out when the "z" node is empty and the "w" node is not, then specifying "[anchor = north]" for the node following "w" fixes the issue.
    – HRSE
    Commented Dec 31, 2022 at 2:50
  • If the "w" and/or "z" text has descenders like "pqgy" or ascenders like "Abkl" one needs to add [font = \vphantom{Ag}] after \begin{tikzpicture} to really match the text at the baseline. It also improves the positioning of all the other text (pAp, aaa, AAA match and x, d, y match, respectively at their baseline)
    – HRSE
    Commented Dec 31, 2022 at 13:59
  • I tried adding [text depth = 0] in various places and did not see how it improves any positioning. Where is it supposed to go?
    – HRSE
    Commented Dec 31, 2022 at 14:29
  • 1
    @HRSE: You could add text depth=0 to the node options for the node with the descender, (edge from parent node[right, text depth=0] {g}) or you could add it as an option to the whole tikzpicture. It won't work for ascenders though. You could use text height=1.5ex the same way for ascenders.
    – Sandy G
    Commented Dec 31, 2022 at 14:37
1

With forest:

\documentclass[margin=3mm]{standalone}
\usepackage{forest}

\begin{document}
\begin{forest}
for tree={
    inner xsep=1pt,
% tree
             l sep = 12mm,
       text height = 1.5ex, text depth = 0.3ex,
if level = 1{s sep = 2mm}{s sep = 12mm},   
        },
%% edge labels
/tikz/ELS/.style = {% Edge Label Style
                    pos=0.5, node font=\scriptsize, text height=1.5ex, text depth=0.3ex,
                    anchor=#1},
EL/.style = {if n=1{edge label={node[ELS=east]{$#1$}}}
                   {edge label={node[ELS=west]{$#1$}}}
            }
[,coordinate 
    [,coordinate, EL=z
        [pAp, EL=x]
        [aaa, EL=d]
        [AAA, EL=y]
    ]
    [, coordinate, EL=w]
]
  \end{forest}
  \end{document}

enter image description here

5
  • 1
    I think you want [, coordinate, EL=w]. Otherwise the z and w labels won't be horizontally aligned (which was OP's request).
    – Sandy G
    Commented Dec 30, 2022 at 17:56
  • @SandyG, you are right. Corrected.
    – Zarko
    Commented Dec 30, 2022 at 18:54
  • This produces the nicest result (notice the placement of x, d, and y is also consistent now). I accepted the other answer because it seems like a larger deviation from the initial code and requires a bunch of hard coded distances.
    – HRSE
    Commented Dec 31, 2022 at 2:53
  • @HRSE, no distance is hard coded. All are deliberately selected. Proposed solution also works without `\for tree˙ option settings, but result than is not so nice (actually it is awful).
    – Zarko
    Commented Dec 31, 2022 at 3:58
  • "Hard coded" is probably the wrong term. "Have to be manually configured for a result that isn't awful" is more precise. I wouldn't like to have to do this whenever I want to draw a tree. On the upside: the result respects proper baseline positions.
    – HRSE
    Commented Dec 31, 2022 at 13:51
0

I just want to add this possibility because this is what I ended up using.

\begin{tikzpicture}
  [font=\vphantom{Ag}]
  \coordinate
  child {
    child {node {pAp} edge from parent node[left] {x}}
    child {node {aaa} edge from parent node[left] {d}}
    child {node {AAA} edge from parent node[right] {y}}
  edge from parent node[left] {z}}
  child {node[anchor=north]{} edge from parent node[right] {w}};
\end{tikzpicture}

The advantage is that text is matched by baseline and that text can also be added at some but not all nodes on the same level (for example, after "w"). There may be further tweaks possible for trees with more levels as this solution would not work if there are further branches after the node following "w".

You must log in to answer this question.

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