2

I have tried searching for a solution everywhere however I either haven't been able to see it or it is not there.

I have a forest, I would like to add a label to each node such that 'Deadbeef' would be labelled 1, 'Something' would be labeled 1.1, 'else' 1.2 and then their children 1.1.1 etc.

I know I can do this with the \label command, however I am lazy and my tree grows so I don't want to keep numbering trivially.

\begin{forest}
for tree={
    grow'=0,
    align=center, 
    base=bottom
},
[Deadbeef
    [Something
        [Generic\\node]
        [Other\\ generic node]
        [That one\\there]        
    ]
    [Else
        [Client\\Side
            [Become\\data]
            [Bathe in\\data]
        ]
        [Server\\Side
            [One with\\data]
            [Meta\\data
                [Update\\main service]
                [Update\\database]
            ]
        ]
    ]
    [Kindof
        [You are\\very kind]
        [How much\\for the lot?]
        [Really not\\serious]
    ]
]
\end{forest}

enter image description hereenter image description here

My paintjob isn't great but I hope it portrays the idea I am trying to achieve. The ideal solution should take a tree of any size and label nodes accordingly incase I haven't made this clear.


Edit 1: The labels should go all the way to the nodes. I know about cfr's answer however the levels are specified manually. I don't know how many levels I will have for a tree so I would prefer for this to be done automatically.

  • Please provide compilable code! It makes life much easier. – cfr Jul 28 '18 at 22:00
  • You want them in the content or really as labels? – cfr Jul 28 '18 at 22:01
  • There are other answers which don't require manual specifications, though. – cfr Jul 28 '18 at 22:40
3

Please always provide compilable code. It greatly reduces uncertainties, increases the prospect of questions being answered (a) at all and (b) in ways which actually help their askers, is much more efficient, more helpful to new users and generally makes life much easier.

Guessing how to complete your code, I'm also not clear if you really mean labels or if you want to change the nodes' content. I'm assuming the latter as labels make little sense here, as far as I can tell. That is, I take the target to be something like this:

results/assumed target

If so:

\begin{forest}
  for tree={
    grow'=0,
    align=center, 
    base=bottom
  },
  before typesetting nodes={
    for tree breadth-first={
      if level=0{temptoksa=1}{
        temptoksa/.option=n,
        for nodewalk={
          while nodewalk valid={u}{u,+temptoksa=.,if level=0{+temptoksa=1}{+temptoksa/.option=n}}
        }{},
      },
      content/.process={ROw2{temptoksa}{content}{#1 #2}}
    }
  }
  [Deadbeef
    [Something
      [Generic\\node]
      [Other\\ generic node]
      [That one\\there]        
    ]
    [Else
      [Client\\Side
        [Become\\data]
        [Bathe in\\data]
      ]
      [Server\\Side
        [One with\\data]
        [Meta\\data
          [Update\\main service]
          [Update\\database]
        ]
      ]
    ]
    [Kindof
      [You are\\very kind]
      [How much\\for the lot?]
      [Really not\\serious]
    ]
  ]
\end{forest}

Incidentally, the tree does not look very clear to me, because the edges often end randomly in relation to their children. I would probably go for something more like this:

  for tree={
    grow'=0,
    align=center, 
    font=\sffamily,
  },
  forked edges,
  align middle children,

in the tree's preamble, where align middle children is from a custom library and defined as follows:

\forestset{
  align middle child/.style={
    before typesetting nodes={
      if={
        > Ow+P {n children}{isodd(##1)}
      }{
        calign child/.process={
          Ow+n {n children}{(##1+1)/2}
        },
        calign=child edge,
      }{},
    },
  },
  align middle children/.style={
    for tree={align middle child},
  },
}

alternative

But that's a matter of taste, of course.

Complete code:

\documentclass[border=10pt]{standalone}
\usepackage[edges]{forest}
\forestset{
  align middle child/.style={
    before typesetting nodes={
      if={
        > Ow+P {n children}{isodd(##1)}
      }{
        calign child/.process={
          Ow+n {n children}{(##1+1)/2}
        },
        calign=child edge,
      }{},
    },
  },
  align middle children/.style={
    for tree={align middle child},
  },
}
\begin{document}
\begin{forest}
  for tree={
    grow'=0,
    align=center, 
    base=bottom
  },
  before typesetting nodes={
    for tree breadth-first={
      if level=0{temptoksa=1}{
        temptoksa/.option=n,
        for nodewalk={
          while nodewalk valid={u}{u,+temptoksa=.,if level=0{+temptoksa=1}{+temptoksa/.option=n}}
        }{},
      },
      content/.process={ROw2{temptoksa}{content}{#1 #2}}
    }
  }
  [Deadbeef
    [Something
      [Generic\\node]
      [Other\\ generic node]
      [That one\\there]        
    ]
    [Else
      [Client\\Side
        [Become\\data]
        [Bathe in\\data]
      ]
      [Server\\Side
        [One with\\data]
        [Meta\\data
          [Update\\main service]
          [Update\\database]
        ]
      ]
    ]
    [Kindof
      [You are\\very kind]
      [How much\\for the lot?]
      [Really not\\serious]
    ]
  ]
\end{forest}
\begin{forest}
  for tree={
    grow'=0,
    align=center, 
    font=\sffamily,
  },
  forked edges,
  align middle children,
  before typesetting nodes={
    for tree breadth-first={
      if level=0{temptoksa=1}{
        temptoksa/.option=n,
        for nodewalk={
          while nodewalk valid={u}{u,+temptoksa=.,if level=0{+temptoksa=1}{+temptoksa/.option=n}}
        }{},
      },
      content/.process={ROw2{temptoksa}{content}{#1 #2}}
    }
  }
  [Deadbeef
    [Something
      [Generic\\node]
      [Other\\ generic node]
      [That one\\there]        
    ]
    [Else
      [Client\\Side
        [Become\\data]
        [Bathe in\\data]
      ]
      [Server\\Side
        [One with\\data]
        [Meta\\data
          [Update\\main service]
          [Update\\database]
        ]
      ]
    ]
    [Kindof
      [You are\\very kind]
      [How much\\for the lot?]
      [Really not\\serious]
    ]
  ]
\end{forest}
\end{document}
  • I can't compile your last code. I get Illegal parameter number in definition of \pgf@temp. <to be read again> 1 l.63 \end{forest} – Ali Caglayan Jul 30 '18 at 10:52
  • I have no clue what this means. If it helps I am doing this on overleaf. – Ali Caglayan Jul 30 '18 at 10:52
  • @AliCaglayan That's odd. It works fine here. Do you get that error with precisely this code in a new document? Or do you get it when you add the code to an existing document? What version of Forest does Overleaf have? – cfr Jul 30 '18 at 12:56
  • @AliCaglayan Overleaf has an old version of Forest (v. 2.0.3), whereas I have what I think is the current version (v. 2.1.5). There were some bugs, so it might be that, and there are some new features, so it could be that. – cfr Jul 30 '18 at 13:06
  • 1
    On my TeXLive 2018 distribution the code compiles like a charm and precisely reproduces the screen shot. – user121799 Jul 30 '18 at 13:35
3

This is almost entirely stolen from @cfr's nice answer, and I will be happy to retract my post if @cfr posts an answer. I'm sure @cfr will also be able to avoid the ugly \addone. So this is just in case ....

\documentclass[border=3.14mm]{standalone}
\usepackage[edges]{forest}
\newcommand{\addone}[1]{\pgfmathtruncatemacro{\tmp}{#1+1}\tmp}
\begin{document}

\begin{forest}
set root label/.style={
    content/.wrap 2 pgfmath args={\addone{##1}. ##2}{n()}{content()},
  },
set node label/.style={
    content/.wrap 3 pgfmath args={\addone{##1}.##2 ##3}{n("!r")}{n()}{content()},
  },
set node super label/.style={
    content/.wrap 4 pgfmath args={\addone{##1}.##2.##3  ##4}{n("!rr")}{n("!u")}{n()}{content()},
  },
before typesetting nodes={
    for tree={
      if level=0{
        set root label,
      }{
        if level=1{
          set node label,
        }{
          if level=2{
            set node super label,
          }{
          },
        },
      },
    },
  },
for tree={
    grow'=0,
    align=center, 
    base=bottom
},
[Deadbeef
    [Something
        [Generic\\node]
        [Other\\ generic node]
        [That one\\there]        
    ]
    [Else
        [Client\\Side
            [Become\\data]
            [Bathe in\\data]
        ]
        [Server\\Side
            [One with\\data]
            [Meta\\data
                [Update\\main service]
                [Update\\database]
            ]
        ]
    ]
    [Kindof
        [You are\\very kind]
        [How much\\for the lot?]
        [Really not\\serious]
    ]
]
\end{forest}
\end{document}

enter image description here

  • See I was hoping I wouldn't have to specify each level. Is there a way to automatically number them, all the way to the leaves? Specifying labels for each level seems like it could be recursed. I'll edit the original question to make this clearer. – Ali Caglayan Jul 28 '18 at 13:49
  • If you are stuck with version 1 of Forest, this is probably not an unreasonable approach because it is much harder to store results of walks recursively (at least for me), you're stuck with pgfmath and the variety of pre-defined multi-step nodewalk steps available is significantly more limited. (You can defined new steps, but fewer are there out-of-the-box.) At least, I guess that's why I might have answered the earlier question that way. (Or maybe I just couldn't figure out something more flexible at the time.) – cfr Jul 28 '18 at 22:39
  • But I think current Forest makes it at least rather more straightforward to avoid some of the limitations you and @AliCaglayan mention. – cfr Jul 28 '18 at 22:39
  • @cfr I agree and already upvoted your nice answer... ;-) – user121799 Jul 29 '18 at 4:29
  • I upvoted yours, too, for the record, as I didn't want you to delete it. If anybody has version 1 and can't update, this might well be useful. – cfr Jul 29 '18 at 17:51

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.