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.

1 Answer 1

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.

2
  • Bugger. Thank you very much! [First comment was not directed at you - only the second!] ;) Much appreciated.
    – cfr
    Dec 21, 2014 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, 2014 at 22:15

You must log in to answer this question.

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