5

I was trying to figure out how you might get forest to label the nodes in a diagram such as the one featured in this question automatically. So, the idea is that:

  • level 0: content of node should be prefixed with O. i.e. if the content specified is P0, then the node should be typeset with the content O. P0;
  • level 1: content should be prefixed with O.n where n is the number of the child e.g. if the nodes at the first level are specified as P1 and P3, then they should be typeset as O.1 P1 and O.2 P3;
  • level 2: content should be prefixed with O.n.m where n is the child number of the parent and m is the child number of the node e.g. if P1 has a child P2 then the latter should appear as O.1.1 P2 and if P3 has a child P4 then the latter should be typeset as O.2.1 P4.

Level 0 is no problem. I can do that using content={O. #1}. I can also get the relevant labels constructed and included in the nodes for levels 1 and 2. However, what I cannot figure out is how to get this added to the content of each node exactly once. Whatever I do, I either end up without the prefix or with a garbled or empty prefix or with multiple copies of the correct prefix.

This is the closest I've got, I think:

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

\forestset{
  tree node/.style = {align=center, inner sep=2pt, rounded corners = 2pt, text centered, font=\sffamily, rectangle, draw=black},
}
\begin{forest}
  for tree={
    parent anchor=south,
    child anchor=north,
    tree node,
    l sep+=5pt,
    edge path={
      \noexpand\path [-{Stealth[]}, \forestoption{edge}, thick]
        (!u.parent anchor) -- +(0,-5pt) -| (.child anchor)\forestoption{edge label};
    },
  },
  set node label/.style={
    content/.wrap 2 pgfmath args={O.##1 ##2}{n()}{content()},
  },
  set node super label/.style={
    content/.wrap 3 pgfmath args={O.##1.##2 ##3}{n("!u")}{n()}{content()},
  },
  before typesetting nodes={
    for tree={
      where level=0{
        content={O. #1},
      }{
        where level=1{
          set node label,
        }{
          where level=2{
            set node super label,
          }{
          },
        },
      },
    },
  }
  [P0
    [P1
      [P2
      ]
    ]
    [P3
      [P4
      ]
    ]
  ]
  ;
\end{forest}
\end{document}

This constructs the prefixes correctly but it adds them too often to the nodes!

too many labels!

I've also tried storing the original content in a macro and then using that in the specification of content. However, in that case, I just lose the original contents altogether.

4

Replace all the wheres by ifs.

where is defined as where/.style n args={3}{for tree={if={#1}{#2}{#3}}}, so it implicitely contains a for tree loop.

  • Bugger. Thank you very much! [First comment was not directed at you - only the second!] ;) Much appreciated. – cfr Dec 21 '14 at 20:51
  • Here's the example which prompted this question, in case you are interested. (No particular reason you should be, of course.) – cfr Dec 21 '14 at 22:15

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.