2

I would like to embed a tikzpicture in a forest node label:

\documentclass[
    ,crop=true
    ,varwidth=\maxdimen
    ]{standalone}

\usepackage{forest}

\begin{document}

\Forest{
    [A\tikz{\node[circle,draw,inner sep=.15ex]{1};} [B] [C]]
}

\end{document}

However, the \tikz part is simply ignored:

enter image description here

Instead the root node label should look like this:

enter image description here

I bet it's very easy to accomplish, but I just don't get it.

  • your MWE produces the desired result with my installation, maybe an upgrade will help. – Marijn Nov 20 '15 at 15:25
  • @Marijn: Yes, you're right! But rather a downgrade is necessary. It compiles as desired with old pdfTeX, Version 3.1415926-2.5-1.40.14 (TeX Live 2013/Debian). The wrong output is generated with the more recent pdfTeX, Version 3.14159265-2.6-1.40.16 (TeX Live 2015/Cygwin) and pdfTeX, Version 3.14159265-2.6-1.40.16 (TeX Live 2015/W32TeX). Not nice. – Timm Nov 20 '15 at 15:46
  • I doubt that the version of pdftex is the problem, it is more likely a problem with forest (or possibly tikz). – Torbjørn T. Nov 20 '15 at 18:04
  • 1
    Incidentally, I see the same behaviour with TL 2015. Would adding \usepackage{pifont} and using A\ding{172} be an option? – Torbjørn T. Nov 20 '15 at 18:10
  • @TorbjørnT.: Thanks for the workaround. Unfortunately, I need this for arbitrary numbers. So I switched back to a tikz-free solution: \newcommand{\circled}[1]{\textcircled{\raisebox{-0.8pt}{#1}}}. Still it's irritating that the recent TL 2015 seems to be broken here. – Timm Nov 20 '15 at 18:56
5

Nesting tikzpicture environments should be avoided. It guarantees unpredictability ;).

However, there is a straightforward way to do this using forest which provides a tikz key for adding annotations to nodes after the tree is drawn:

\documentclass[border=10pt,tikz]{standalone}
\usepackage{forest}
\usetikzlibrary{positioning}

\begin{document}

\Forest{
  [A, tikz={\node[circle, draw, inner sep=.15ex, right=0pt of .east]  {1};} [B] [C]]
}

\end{document}

annotated root

The advantage of this is that you can use relative node names. Here .east is the east anchor of the current node. We need to adjust the spacing to avoid having the nodes overlap. I've used positioning which is recommended, though you could do without it if you had to for some reason.

If you need the nodes closer, consider reducing or eliminating the inner sep:

\Forest{
  [A, tikz={\node[circle, draw, inner sep=0pt, right=0pt of .east]  {1};} [B] [C]]
}

adjusted separation

or using a negative value:

\Forest{
  [A, tikz={\node[circle, draw, inner sep=0pt, right=-2.5pt of .east]  {1};} [B] [C]]
}

further adjusted

EDIT

The only problem with the above solution is that it is rather tedious if required frequently and the circled numbers may overlap with sibling nodes if the numbers get large.

Moreover, it is also possible - and perhaps slightly simpler - to use forest's label option to create the circled number as a label for the node.

    label={[circle, draw, inner sep=.15ex, label distance=-2.5pt, anchor=west]east:<number to be circled>}

However, this is hardly less tedious to type. So, it would be convenient to create a style which allowed us to write, for example, circ=89 to label the node with a circled 89:

\forestset{
  circ/.style={
    label={[circle, draw, inner sep=.15ex, label distance=-2.5pt, anchor=west]east:#1}
  },
}

Now, we can write

\Forest
{
  [A, circ=3
    [B
      [D, circ=-4
    ]
  ]
    [C, circ=4499]
  ]
}

to produce

circled numbers with style

which is more convenient.

This works fine if the numbers are all on the border of the tree, but less well if they occur in between nodes within the tree:

problematic overlap

To solve this, we can increase the distance between the siblings for that particular node. We would like to do this automatically, but we only want to do it when necessary, so we add some conditional code to circ:

  circ/.style={
    label={[circle, draw, inner sep=.15ex, label distance=-2.5pt, anchor=west]east:#1},
    if level=0{}{
      if n'=1{}{
        if={equal(n_children("!u"),1)}{}{
            !u.s sep+/.pgfmath={width("#1")+.3ex+.8pt},
        }
      },
    },
  }

which produces this

corrected positioning

Complete code:

\documentclass[border=10pt,tikz]{standalone}
\usepackage{forest}
\forestset{
  circ/.style={
    label={[circle, draw, inner sep=.15ex, label distance=-2.5pt, anchor=west]east:#1},
    if level=0{}{
      if n'=1{}{
        if={equal(n_children("!u"),1)}{}{
            !u.s sep+/.pgfmath={width("#1")+.3ex+.8pt},
        }
      },
    },
  }
}
\begin{document}

\Forest
{
  [A, circ=3
    [B
      [D, circ=-4
        [E, circ=895]
        [F]
    ]
  ]
    [C, circ=4499]
  ]
}

\end{document}
  • Thanks, very instructive! Is there a way to do this with (3) instead of circle=3? – Timm Nov 22 '15 at 13:48
  • @Timm You could, I guess, process the contents of the node so that you parsed for the occurrence of the parentheses and then split that part of the content out into the label. However, you would have to do that for every node, I think, so it would slow things down for large trees or lots of trees, and it would be a much less standard and, probably, a more fragile way of doing it. Forest really uses the <key>=<value> syntax and working with that is probably a better solution. Only I wouldn't use circle because that's a standard TikZ shape - hence my use of circ. Is it really an issue? – cfr Nov 22 '15 at 14:20
  • Sorry, I should have written circ. As for (3), it's not really an issue. But it would look nicer: [A,(3) [B] [C]]. – Timm Nov 22 '15 at 15:13
  • I definitely don't think you could use [A,(3)... as you'd need to define a key like that. At most you could do [A (3) and then you have to process the content of the node. But I don't think it is a good idea for the reasons I gave above. – cfr Nov 22 '15 at 16:07
  • 1
    @towi Nesting tikzpicture environments should be avoided. It guarantees unpredictability ;). It doesn't matter whether you nest 1 inside 2 or 2 inside 1, nesting tikzpictures should be avoided. You can use a save box, as in the answer below. Or you can do the tree first and build a picture around it. – cfr Jun 9 '17 at 22:38
2

Another solution is to use saveboxes:

\documentclass[
    ,crop=true
    ,varwidth=\maxdimen
    ]{standalone}

\usepackage{forest}

\newsavebox{\tempbox}

\begin{document}

\savebox{\tempbox}{A\tikz{\node[circle,draw,inner sep=.15ex]{1};}}

\Forest{
    [\usebox{\tempbox} [B] [C]]
}

\end{document}

forrest

  • So you need a box for every label you are going to use within the tree? I know you can reuse the boxes for another tree, but if you need, say, 20 such nodes in a single tree, you'll need 20 boxes, won't you? – cfr Nov 22 '15 at 1:02
  • @cfr - Yes, but inside a \bgroup .... \egroup you can use up to 256 boxes (32k with etex). – John Kormylo Nov 22 '15 at 3:13
  • I was more thinking it would be a PITA to create them than that it would use up too many boxes ;). – cfr Nov 22 '15 at 3:28

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.