3

Related: Problem with "append after command" and "insert path", but I did not understand how to apply the solutions there in my case.

I'm defining a simple tikz style which uses append after command:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,fit}
\begin{document}
\begin{tikzpicture}[
  fit after/.style={
    append after command={%
      node[draw, inner sep=0pt, fit=(\tikzlastnode)] {}
    }
  }
  ]
  \node[fit after] {A};%%%% WORKS
  \node {B} child { node[fit after] {C} }; %%%% FAILS
\end{tikzpicture}
\end{document}

On the first node (A), it works fine and draws a rectangle around it.

On the C node, however, I get the following error message:

Package pgf Error: No shape named  is known.

The \tikzlastnode isn't at fault, as even hardcoding the name of the node still fails in the child case.

Is the child path operation messing with append after command? Is there a workaround?

Context: I am trying to make a triangle fit whole subtree command, which draws a triangle that fits around all the nodes in the subtree.

  • I would definitely use Forest for this. – cfr Jun 9 '16 at 22:34
  • @cfr: Could you expand on what features of the forest package you would use in this case? Do you mean that append after command would work better with forest? I skimmed over the documentation, but nothing stroke me. Thanks! – Georges Dupéron Jun 9 '16 at 22:50
  • See below for an example. Forest parses the tree in cycles. This means that you can collect up the list of nodes in the subtree after the entire tree is specified and then use that list as the argument for fit. I doubt append after command would work straightforwardly because it would probably conflict with Forest's own functions. But the point is that you don't really need it with Forest. (I'm not entirely sure how it would work in your example either, but I accept that you had something in mind. :-) ) – cfr Jun 9 '16 at 23:29
3

If forest is an option, it is reasonably straightforward to define a fit whole subtree style. I don't recommend a triangular shape. Although I experimented a bit, this inevitably looked very ugly. However, fit whole subtree can be passed whatever options you wish to style the node. By default, it draws a rectangle in red.

Note that multiple uses of fit whole subtree, including nested uses, work fine.

\documentclass[tikz,border=10pt,multi]{standalone}
\usepackage{forest}
\usetikzlibrary{fit}
\begin{document}
\newcommand*\makenodename[1]{(#1)}
\forestset{
  declare toks={fit these}{},
  fit whole subtree/.style={
    delay={
      temptoksa=,
      for tree={%
        temptoksa+/.wrap pgfmath arg={ (##1)}{name()},
      },
      fit these/.register=temptoksa,
      delay={
        tikz+={
          \node [draw=red, fit=\foresteoption{fit these}, inner sep=0pt, #1] {};
        },
      },
    },
  },
}
\begin{forest}
  for tree={
    fit=band,
    child anchor=parent,
    parent anchor=children,
  }
  [A
    [B
      [C, fit whole subtree
        [D]
        [E
          [X]
          [Y
            [Z]
          ]
        ]
        [F]
        [G]
      ]
      [H
        [I
          [J]
          [K]
          [L]
        ]
      ]
    ]
    [M, fit whole subtree={thick, draw=blue, rounded corners}
      [N
        [O
          [R]
        ]
        [P]
        [Q]
      ]
      [S, fit whole subtree={green, densely dashed, rounded corners}
        [T]
        [U]
        [V]
        [W]
      ]
    ]
  ]
\end{forest}
\end{document}

nested fitted subtrees

  • 1
    I had to upgrade to the latest version of Forest (/.register was introduced in v2.0) and install elocalloc from CTAN. Works great after that! – Georges Dupéron Jun 10 '16 at 8:46
  • 1
    Yes, it does need version 2. You could do this with the earlier version but you'd probably need to use TeX and fiddle with adding the nodes to a macro. Upgrading is definitely the way to go! – cfr Jun 10 '16 at 12:13

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.