[Tex/LaTex] How to draw triangles as subtree with the forest package

forest

I want to draw a binary tree using the package forest and I want simplify a part of the tree, drawing a triangle. I want also put a label on this triangle, and the label should be contained in the triangle.

Here is my source:

\begin{forest}
for tree={l+=0.5cm, s sep+=1cm}
[$q_5$ [$q_8$ [$q_1$ [$\overline q_2$] [$\overline q_6$]] 
[$q_9$ [$q_3$ [$\vdots$] [$\vdots$]] [$q_5$ [$\vdots$, tria] [$\vdots$]] ] ]
[$q_3$ [$\overline q_2$] [$q_4$ [$\overline q_2$] [$\overline q_6$]] ]
]
\end{forest}

For example I want to replace the node $\vdots$ with a triangle and put a label on it.

Can you help me?

( I think this package has a nice syntax for drawing tree and the auto-positioning is awesome. So as my second question, where can I find some good template/tutorial for the forest package? I can't understand how style command works.. )

Best Answer

New Answer

Use this version if you have relatively recent versions of Forest and/or TikZ. The clash described below when using triangle no longer applies because

  1. Forest no longer defines triangle and nor do any of its libraries;
  2. shapes.geometric no longer defines triangle.

Hence, attempting to use triangle will not work at all, but not because there are two competing definitions. The problem now is that there is no definition at all. However, you can use isosceles triangle to define a new triangle option.

I've also updated the definition of tria for the polygon case and tried to make triangle work somewhat sensibly if there are siblings. It is no longer necessary to insert empty nodes in this case, as they are inserted automatically.

Current result of triangle [left] and tria [right]:

<code>triangle</code> and <code>tria</code> update

Code:

\documentclass[border=5pt]{standalone}
\usepackage{forest}
\usetikzlibrary{shapes.geometric}
\begin{document}
\forestset{
  tria/.style={
    node format={
      \noexpand\node [
      draw,
      shape=regular polygon,
      regular polygon sides=3,
      inner sep=0pt,
      outer sep=0pt,
      \forestoption{node options},
      anchor=\forestoption{anchor}
      ]
      (\forestoption{name}) {\foresteoption{content format}};
    },
    child anchor=parent,
  },
  triangle/.style={
    isosceles triangle, isosceles triangle apex angle=45, child anchor=parent, shape border uses incircle, shape border rotate=90, draw,
    delay={
      if={
        >O_> {!u.n children}{1}
      }{
        replace by/.process={ Ow {id} {[, coordinate, tier=##1, append, l'=0pt]}},
        for siblings={tier/.option=id},
        no edge,
      }{},
    },
  },
}%
\begin{forest}
  for tree={l'+=0.5cm, s sep'+=1cm, math content}
  [q_5 [q_8 [q_1 [\overline q_2] [\overline q_6]]
  [q_9 [q_3 [\vdots] [\vdots]] [q_5 [\vdots, triangle] [\vdots]] ] ]
  [q_3 [\overline q_2] [q_4 [\overline q_2] [\overline q_6]] ]
  ]
\end{forest}
\begin{forest}
  for tree={l'+=0.5cm, s sep'+=1cm, math content}
  [q_5 [q_8 [q_1 [\overline q_2] [\overline q_6]]
  [q_9 [q_3 [\vdots] [\vdots]] [q_5 [\vdots, tria] [\vdots]] ] ]
  [q_3 [\overline q_2] [q_4 [\overline q_2] [\overline q_6]] ]
  ]
\end{forest}
\end{document}

Original Answer

Use this version if you have older versions of Forest and TikZ and, for some reason, you cannot update.

Normally, you could specify the shape by just passing the shape's name as an option to the node. For example, this works with ellipse as shown on page 27 of the manual:

\documentclass[tikz, border=5pt]{standalone}
\usepackage{forest}
\begin{document}
  \pgfkeys{/forest,
    tria/.append style={ellipse, draw},
  }
  \begin{forest}
    for tree={l+=0.5cm, s sep+=1cm}
    [$q_5$ [$q_8$ [$q_1$ [$\overline q_2$] [$\overline q_6$]]
    [$q_9$ [$q_3$ [$\vdots$] [$\vdots$]] [$q_5$ [$\vdots$, tria] [$\vdots$]] ] ]
    [$q_3$ [$\overline q_2$] [$q_4$ [$\overline q_2$] [$\overline q_6$]] ]
    ]
  \end{forest}
\end{document}

simple ellipse

However, triangle is interpreted specially by forest as specifying a triangular edge path from parent to child:

triangle is interpreted specially

I came up with two possibilities for a triangular node shape. The first is the same as Ignasi's solution: use the shapes.geometric library. My version draws the edge to the triangle's apex, however, rather than to the middle of the side. The second is to use forest's triangular edges with an empty node.

Possibility 1

\documentclass[tikz, border=5pt]{standalone}
\usetikzlibrary{shapes.geometric}
\usepackage{forest}
\begin{document}
  \pgfkeys{/forest,
    tria/.style={
      node format={
        \noexpand\node [
          draw,
          shape=regular polygon,
          regular polygon sides=3,
          inner sep=0pt,
          outer sep=0pt,
          \forestoption{node options},
          anchor=\forestoption{anchor}
         ]
        (\forestoption{name}) {\foresteoption{content format}};
      },
      child anchor=north,
      edge path={
        \noexpand\path[\forestoption{edge}]
          (!u.parent anchor) --
          (.child anchor)\forestoption{edge label};
      },
    },
  }
  \begin{forest}
    for tree={l+=0.5cm, s sep+=1cm}
    [$q_5$ [$q_8$ [$q_1$ [$\overline q_2$] [$\overline q_6$]]
    [$q_9$ [$q_3$ [$\vdots$] [$\vdots$]] [$q_5$ [$\vdots$, tria] [$\vdots$]] ] ]
    [$q_3$ [$\overline q_2$] [$q_4$ [$\overline q_2$] [$\overline q_6$]] ]
    ]
  \end{forest}
\end{document}

regular polygon option

Possibility 2

\documentclass[tikz, border=5pt]{standalone}
\usetikzlibrary{shapes.geometric}
\usepackage{forest}
\begin{document}
  \begin{forest}
    for tree={l+=0.5cm, s sep+=1cm}
    [$q_5$ [$q_8$ [$q_1$ [$\overline q_2$] [$\overline q_6$]]
    [$q_9$ [$q_3$ [$\vdots$] [$\vdots$]] [$q_5$ [, [, label={$\vdots$}, triangle]] [$\vdots$]] ] ]
    [$q_3$ [$\overline q_2$] [$q_4$ [$\overline q_2$] [$\overline q_6$]] ]
    ]
  \end{forest}
\end{document}

triangular edge option

Note that the second solution will not work well with a sibling - hence the use of two empty nodes. However, it does look somewhat neater to me. On the other hand, I'm not sure how well it will work in practice whereas the polygon solution should be relatively resilient.

Related Question