Forest: Customized edge between parent and grandchildren, when the child node is missing

I don't know what the extended version of the question was as the question now is an answer rather than a question.

For this reason, my aim was to do two things:

  • answer the non-extended question;

  • reproduce the result in the extended answer-question.

Basically, I want to propose something much simpler, which does not require drawing anything in, doesn't require a variant on the forked edges style (though it does use a wrapper around the original version of the style) and let's you specify the missing nodes as just empty nodes.

In addition, the assignment of tiers is automated and the use of relative anchors makes the code a bit more flexible.

The wrapper style is called, very boringly, my tree and is defined thus:

\forestset{
  my tree/.style={
    forked edges,

Note that forked edges should not be within the scope of for tree. Either use forked edge within that scope or, as here, keep forked edges outside it.

    for tree={
      grow'=0,
      draw,
      text width=10mm,
      minimum height=5mm,
      text centered,
      tier/.option=level,

This automates the levels, since the level completely determines the desired tier.

    },
    delay={
      where content={}{content=\phantom{X},draw=none, child anchor=children}{}

If you want to miss a node, leave the node empty. This code will then add a phantom X (to save messing around trying to figure out the right height to give it - apparently the other nodes exceed the 5mm minimum). The node will have the standard assigned width, but won't be drawn. Changing the child anchor, however, has the effect of making it look as if no node is there. Essentially, this runs the branch from the parent all the way through the centre of the node, which is just what would happen if you had a coordinate on the far side, rather than a regular width node.

In some cases, you need a coordinate, but here, it's easier not to go that route. If you really want true coordinates rather than look-alikes, I would just move the coordinate later in before drawing tree.

    },
  },
}

That's it.

Now, we can write

\begin{forest}
  my tree
    [A
      [B1
       [
          [D1
            [E1]
            [E2]
          ]
          [D2
            [E3]
            [E4]          
          ]
       ]
      ]
      [B2
        [C2
          [D3
            [E5]
            [E6]          
          ]
          [D4
            [E7]
            [E8]          
          ]
        ]
      ]
    ]
\end{forest}
\begin{forest}
  my tree,
    [A
      [B1
        [
          [D1
            [E1]
            [E2]
          ]
          [D2
            [E3]
            [E4]
          ]
          [D3
            [E5]
            [E6]
          ]
        ]
        [                        
          [D4
            [E7]
            [E8]
          ]
          [
            [E9]
            [E10]
          ]                                   
        ]                                     
      ]
      [B2
        [C3
          [D6
            [E11]
            [E12]
          ]
          [D7
            [E13]
            [E14]
          ]
        ]
      ]
    ]
\end{forest}

to produce

result with simplified code

\documentclass[12pt,border=10pt]{standalone}
\usepackage[edges]{forest}
\forestset{
  my tree/.style={
    forked edges,
    for tree={
      grow'=0,
      draw,
      text width=10mm,
      minimum height=5mm,
      text centered,
      tier/.option=level,
    },
    delay={
      where content={}{content=\phantom{X},draw=none, child anchor=children}{}
    },
  },
}
\begin{document}
\begin{forest}
  my tree
    [A
      [B1
       [
          [D1
            [E1]
            [E2]
          ]
          [D2
            [E3]
            [E4]          
          ]
       ]
      ]
      [B2
        [C2
          [D3
            [E5]
            [E6]          
          ]
          [D4
            [E7]
            [E8]          
          ]
        ]
      ]
    ]
\end{forest}
\begin{forest}
  my tree,
    [A
      [B1
        [
          [D1
            [E1]
            [E2]
          ]
          [D2
            [E3]
            [E4]
          ]
          [D3
            [E5]
            [E6]
          ]
        ]
        [                        
          [D4
            [E7]
            [E8]
          ]
          [
            [E9]
            [E10]
          ]                                   
        ]                                     
      ]
      [B2
        [C3
          [D6
            [E11]
            [E12]
          ]
          [D7
            [E13]
            [E14]
          ]
        ]
      ]
    ]
\end{forest}
\end{document}

I am not a forest expert but I could look up the definition of the forked edges in the forest manual and use it to define a "new" version in which the distance of the fork to the children (rather than parent) is fixed. EDIT: Moved the my forked edges out of for tree, big thanks to @cfr!

\documentclass[12pt,crop=true,border=1cm]{standalone}
\usepackage[edges]{forest}
%\usetikzlibrary{calc}
\forestset{
  declare dimen={my fork sep}{0.5em},
  my forked edge'/.style={
    edge={rotate/.option=!parent.grow},
    edge path'={let \noexpand\p1=($(.child anchor)-(!u.parent anchor)$) in 
    (!u.parent anchor) -- ++(\noexpand\x1-\forestoption{my fork sep},0) |- (.child anchor)},
  },
  my forked edge/.style={
    on invalid={fake}{!parent.parent anchor=children},
    child anchor=parent,
    my forked edge',
  },
  my forked edges/.style={for nodewalk={#1}{my forked edge}},
  my forked edges/.default=tree,
}
\begin{document}

\begin{forest}
my forked edges,
  for tree={
    grow'=0,
    draw,
    my fork sep=8pt,
    text width=10mm,
    minimum height=5mm,
    parent anchor=east,
    child anchor=west,
    text centered,
  }
    [A,tier=level1
      [B1,tier=level2,name=B1
%        [C1 would be here, but it is missing
          [D1,tier=level4,name=D1
            [E1,tier=level5]
            [E2,tier=level5]
          ]
          [D2,tier=level4,name=D2
            [E3,tier=level5]
            [E4,tier=level5]          
          ]
%        ]
      ]
      [B2,tier=level2
        [C2,tier=level3
          [D3,tier=level4
            [E5,tier=level5]
            [E6,tier=level5]          
          ]
          [D4,tier=level4
            [E7,tier=level5]
            [E8,tier=level5]          
          ]
        ]
      ]
    ]
\end{forest}
\end{document}

enter image description here

Tags:

Forest