4

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.. )

2
  • Could you complete your code so that it is a compilable document? That makes it easier for people to help (they can just cut-and-paste your code and get working right away). The manual for forest has lots of examples but if you click on the {forest} tag at the bottom of your question, you can also find all the questions tagged that way here. Or you can search for forest to find answers to questions which use it but may not be tagged with it, too. The TiKZ manual explains how to use things like style.
    – cfr
    Oct 24, 2014 at 10:56
  • Which \vdots node do you want to replace?
    – cfr
    Oct 24, 2014 at 10:59

2 Answers 2

10

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.

3
  • Your answer includes mine so I've deleted it. And thank you for the example with forest options, now I understand them a little bit better.
    – Ignasi
    Oct 24, 2014 at 15:59
  • @Ignasi Your answer was posted while I was working on mine and since mine included additional stuff, I hope that it was not inappropriate to post it.
    – cfr
    Oct 24, 2014 at 18:40
  • 1
    No problem at all. I think you did it correctly.
    – Ignasi
    Oct 25, 2014 at 7:06
3

Inspired by cfr's answer, I am now using the following (circles for ordinary nodes, triangles for conceptual subtrees) :

\documentclass{article}
\usepackage{tikz, forest}
\usetikzlibrary{shapes.geometric}
\forestset{%
  default preamble={
    for tree={
      circle,
      draw,
      inner sep=0pt,
      minimum size=.5cm,
      font=\scriptsize,
      edge=->,
      anchor=north
    }
  },
  ssarbre/.style={isosceles triangle,
                  draw,
                  shape border rotate=90,
                  minimum size=.7cm,
                  child anchor=apex,
                  anchor=apex}
}
\begin{document}
\begin{forest}
[$x$ [$y$ [$A$,ssarbre] [$z$ [$B$,ssarbre] [$C$,ssarbre] ] ] [$D$,ssarbre] ]
\end{forest}
\end{document}

and obtain

Result of code

1
  • You don't actually need this with the current version of Forest. You can just say triangle (as you always could for circle).
    – cfr
    Dec 19, 2017 at 22:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .