1

I would like to draw a tree, with one of its node being a "super-node", which hides a sub-tree of some original tree. Here is the code:

\begin{tikzpicture}
\node [circle,draw] {A}
    child { node [circle,draw] {B} }
    child { node [circle,draw] {C}
     child { node [circle,draw] {E}}
     child { node [circle,draw] {F}} 
    };

\node [xshift=6cm,circle,draw] {A}
    child { node [circle,draw] {B} }
    child { node [circle,draw,fill=gray!20] {
        \scriptsize
        \begin{tikzpicture}
            \node [circle,draw] {C}
                child { node [circle,draw] {E}}
                child { node [circle,draw] {F}};
        \end{tikzpicture}
    } };
\end{tikzpicture}

The result is that the super-node is "center-aligned", and hides the whole tree. I would like the super-node C's top-left corner to be at the same height as node B. Bad result

  • Please can you complete your code so it can be compiled? Note that you should never nest tikzpictures. Well, very nearly almost never. It occasionally works but should be expected to break and is unsupported. – cfr Dec 4 '16 at 14:20
4

A circle will not work well for the enclosing node because, even if the sub-tree is relatively small and compact, accommodating it will grossly distort the containing tree. I would recommend using some other shape for the enclosing grey node e.g. a rectangle, a triangle or similar.

I would also recommend using Forest in part because it is a tree and 'trees mean forests' where I'm concerned, but partly because the kind of manipulation you want to do is relatively straightforward in Forest and much more difficult otherwise. This is because Forest constructs trees in cycles, which allows you to assemble the sub-tree and then append it to a new node, later adjusting the placement and drawing the enclosing node. Moreover, all this can be wrapped in a style for automatic handling.

The basic idea is to do this when the style is used:

  • replace the current node by a new node with phantom content;
  • append the original node, with sub-tree, to the new node;
  • adjust the distance between the new and original node to match the inner ysep;
  • omit drawing an edge from either parent to new node or new node to original node;
  • fit a node around the original node and sub-tree, drawing and filling it behind everything else;
  • add an edge back explicitly from the parent to the fitted node.

This also uses the backgrounds and fit libraries.

Sample results:

sample 1

sample 2

\documentclass[tikz,border=10pt]{standalone}
\usepackage{forest}
\usetikzlibrary{backgrounds,fit}
\forestset{%
  circle subtree/.style={%
    before typesetting nodes={%
      no edge,
      before computing xy={/pgf/inner ysep/.get=\savedinnerysep, l'=\savedinnerysep},
      replace by/.wrap pgfmath arg={%
        [\phantom{##1}, circle, append, fit=rectangle, no edge,
          before drawing tree={%
            tikz+={%
              \begin{scope}[on background layer]
                \node (n) [draw, fill=gray!25, inner sep=\savedinnerysep, rounded corners, fit=(!1) (!L) (!F)] {} ;
                \path [draw, \forestoption{edge}] (!u.parent anchor) -- (n.north -| !1.child anchor)\forestoption{edge label};
              \end{scope}
            },
          },
        ]
      }{content()}
    },
  },
}
\begin{document}
\begin{forest}
  for tree={
    circle,
    draw,
  }
  [A
    [B]
    [C, circle subtree
      [E]
      [F]
    ]
  ]
\end{forest}
\begin{forest}
  for tree={
    circle,
    draw,
  }
  [A
    [B]
    [C, circle subtree
      [E [G][H][I]]
      [F]
      [J]
    ]
  ]
\end{forest}
\end{document}

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.