# TikZ - Forest - Decorations and alignment

I would like to add extra informations in a tree build with forest. I can do the following tree but the symbols are not vertically aligned... There is a similar problem with my arrows.

Here is the uggly code I use where the problem comes from the fact that I just add the symbols in the leafs of the tree...

\documentclass{article}
\usepackage[utf8x]{inputenc}
\usepackage{ucs}
\usepackage{wasysym}
\usepackage{amssymb}
\usepackage{forest}
\useforestlibrary{linguistics}

\begin{document}
\pagestyle{empty}

\begin{forest}
for tree = {
sn edges,
grow'=0,
l=2.5cm,
s sep=0.2cm,
anchor=west,
child anchor=west}
[
[O
[R
[T $\longrightarrow$ ORT \quad $\newmoon$]
]
[T
[R $\longrightarrow$ OTR \quad $\newmoon$]
]
]
[R
[O
[T $\longrightarrow$ ROT \quad $\blacksquare$ \quad $\blacktriangle$]
]
[T
[O $\longrightarrow$ RTO \quad $\blacktriangle$]
]
]
[T
[O
[R $\longrightarrow$ TOR]
]
[R
[O $\longrightarrow$ TRO]
]
]
]
\end{forest}

\end{document}


How to add my decorations such that they become aligned vertically ?

Here is a variant where the arrows are drawn by the forest package. The additional symbols are added by using tikz directly to draw extra nodes in a distance of 1cm (or whatever the optional parameter says).

\documentclass{article}
\usepackage{wasysym,amssymb}
\usepackage{forest}
\useforestlibrary{linguistics}
\begin{document}

\newcommand\symb[2][1cm]{\draw () ++(#1,0) node{#2};}
\begin{forest}
for tree = {sn edges, grow'=0, l=2.5cm, s sep=0.2cm, anchor=west, child anchor=west}
[ [O [R [T [ORT,edge=->] {\symb{$\newmoon$}}]]
[T [R [OTR,edge=->] {\symb{$\newmoon$}}]]
]
[R [O [T [ROT,edge=->] {\symb{$\blacksquare$}\symb[2cm]{$\blacktriangle$}}]]
[T [O [RTO,edge=->] {\symb{$\blacktriangle$}}]]
]
[T [O [R [TOR,edge=->]]]
[R [O [TRO,edge=->]]]
]
]
\end{forest}

\end{document}

• Thanks a lot for draw and node. This does the job. For the arrows, the use of edge=-> produces arrows too long. So I have decided to use another draw and node pattern. – projetmbc Sep 13 '16 at 20:29
• I've cleaned up a bit here. You may like to do the same? – cfr Sep 14 '16 at 0:29

I would integrate the arrows into the tree, also, but since all and only terminus nodes get arrows, I would add them programmatically.

Originally, I suggested adding the symbols using Forest's label option. For convenience, I used a style symb for this which also wrapped its value in $...$ to save repeating them in every case.

However, this causes misalignment because the nodes in the final level are not of equal width. If the nodes are very similar in size and are predictable, you could just set text width=<some dimension> for these along with edge=->. However, a more elegant solution is to add the symbols themselves into separate nodes.

If we create a new Forest option symb, we can then add this into a node after the tree is parsed, but before the nodes are typeset. I've used anchor=parent but you could obviously use something else, if preferred. The advantage of this is partly that custom Forest options are a neat trick, but mostly that it is more flexible than label and, unlike labels, Forest will keep track of these nodes and the space they require in the usual way.

\documentclass[border=10pt,multi,tikz,dvipsnames]{standalone}
\usepackage{wasysym,amssymb}
\usepackage{forest}
\useforestlibrary{linguistics}
\forestset{%
declare toks={symb}{},
symb tree/.style={%
for tree = {%
sn edges,
grow'=0,
l=2.5cm,
s sep=0.2cm,
anchor=parent,
if n children=0{%
edge=->,
}{},
},
before typesetting nodes={%
where n children=0{%
append/.wrap pgfmath arg={[$##1$, no edge, grow'=0, anchor=parent, l=0em]}{symb()},
}{},
},
},
}
\begin{document}
\begin{forest}
symb tree,
[
[O
[R
[T [ORT, symb=\newmoon]
]
]
[T
[R [OTR, symb=\newmoon]
]
]
]
[R
[O
]
]
[T
[O [RTO, symb=\blacktriangle]
]
]
]
[T
[O
[R [TOR]
]
]
[R
[O [TRO]
]
]
]
]
\end{forest}
\end{document}


# EDIT

In another question, you asked about encircling groups of nodes. I thought it might be helpful to demonstrate some options for extending the example above to do this.

The code below shades behind the node groups as well as circling them, using the backgrounds library.

We amend the contents of \forestset{} as follows.

We first add a couple of other custom options. One is a boolean (on or off - defaults to off). We use this to track where the symbols are. The other tracks a colour for circling nodes, red by default.

  declare boolean={symb here}{0},
declare toks={circle colour}{red},


Then we amend the symb tree style slightly. We change the code in before typesetting nodes to add a symb here marker to the nodes containing the symbols.

          append/.wrap pgfmath arg={[$##1$, no edge, grow'=0, anchor=parent, l=0em, symb here]}{symb()},


We also define a custom nodewalk step which picks out the nodes with the symb here marker. This will let us encircle all and only the symbol nodes, should we wish to do so.

  define long step={symb tree symbs}{}{fake=root, filter={tree}{symb_here} },


Now for a style to circle the symbols. It takes one optional argument for the colour.

  circle symbols/.style={%
before drawing tree={%
!r.tikz+={%
\scoped[on background layer]{\node [circle me, #1, fit to=symb tree symbs] {};}
},
},
},


Here's one for encircling the subtree of the current node, again with an optional colour argument.

  circle subtree/.style={%
before drawing tree={%
tikz+={%
\scoped[on background layer]{\node [circle me, #1, fit to=tree] {};}
},
},
},


Now we want a generic circle fit to style for encircling other stuff. This needs an argument: the stuff to be encircled. So the colour can't be set as an argument here. However, we can still change the colour using circle colour=<colour>, if we don't want the default.

  circle fit to/.style={%
before drawing tree={%
tikz+={%
\scoped[on background layer]{\node [circle me, fit to={#1}] {};}
},
},
},


This is a TikZ style for the circling nodes. It uses the circle colour to draw and fill, but the filling is only 10% opaque.

  /tikz/circle me/.style={%
draw=\forestoption{circle colour}, fill=\forestoption{circle colour}, inner sep=0pt, rounded corners, thick, fill opacity=.10, draw opacity=1,
},


Now, we can use these styles and options to decorate our tree from above.

\begin{forest}
symb tree,


We want to encircle all the symbols using blue.

  circle symbols=blue,
[


We'd like all of O's descendants to be circled in magenta.

    [O, circle fit to=descendants, circle colour=magenta
[R
[T [ORT, symb=\newmoon]
]
]
[T
[R [OTR, symb=\newmoon]
]
]
]


We'd like all the nodes in R's subtree which are three levels below R to be circled in the default colour.

    [R, circle fit to={relative level=3}
[O


We'd like T, T's grand-parent and the grand-parent's second child to be highlighted in blue!50!cyan. Obviously, this will also capture T's parent and the child of the second child, just because of the shape of a rectangular node.

        [T, circle fit to={c,uu,2}, circle colour=blue!50!cyan [ROT, symb=\blacksquare \quad \blacktriangle]
]
]
[T
[O [RTO, symb=\blacktriangle]
]
]
]


T's subtree should be highlighted in green!75!black.

    [T, circle subtree=green!75!black,
[O
[R [TOR]
]
]
[R
[O [TRO]
]
]
]
]
\end{forest}


Our tree then looks as follows.

Complete code:

\documentclass[border=10pt,multi,tikz,dvipsnames]{standalone}
\usepackage{wasysym,amssymb}
\usepackage{forest}
\useforestlibrary{linguistics}
\usetikzlibrary{backgrounds}
\makeatletter
\forestset{%
declare toks={symb}{},
declare boolean={symb here}{0},
declare toks={circle colour}{red},
symb tree/.style={%
for tree = {%
sn edges,
grow'=0,
l=2.5cm,
s sep=0.2cm,
anchor=parent,
if n children=0{%
edge=->,
}{},
},
before typesetting nodes={%
where n children=0{%
if symb={}{}{%
append/.wrap pgfmath arg={[$##1$, no edge, grow'=0, anchor=parent, l=0em, symb here]}{symb()},
},
}{},
},
},
define long step={symb tree symbs}{}{fake=root, filter={tree}{symb_here} },
circle symbols/.style={%
before drawing tree={%
!r.tikz+={%
\scoped[on background layer]{\node [circle me, #1, fit to=symb tree symbs] {};}
},
},
},
circle subtree/.style={%
before drawing tree={%
tikz+={%
\scoped[on background layer]{\node [circle me, #1, fit to=tree] {};}
},
},
},
circle fit to/.style={%
before drawing tree={%
tikz+={%
\scoped[on background layer]{\node [circle me, fit to={#1}] {};}
},
},
},
/tikz/circle me/.style={%
draw=\forestoption{circle colour}, fill=\forestoption{circle colour}, inner sep=0pt, rounded corners, thick, fill opacity=.10, draw opacity=1,
},
}
\makeatother
\begin{document}
\begin{forest}
symb tree,
circle symbols=blue,
[
[O, circle fit to=descendants, circle colour=magenta
[R
[T [ORT, symb=\newmoon]
]
]
[T
[R [OTR, symb=\newmoon]
]
]
]
[R, circle fit to={relative level=3}
[O
[T, circle fit to={c,uu,2}, circle colour=blue!50!cyan [ROT, symb=\blacksquare \quad \blacktriangle]
]
]
[T
[O [RTO, symb=\blacktriangle]
]
]
]
[T, circle subtree=green!75!black,
[O
[R [TOR]
]
]
[R
[O [TRO]
]
]
]
]
\end{forest}
\end{document}

• It seems that there is a alignment problem with the filled discus. – projetmbc Sep 13 '16 at 22:06
• Thalles for the update of your answer. – projetmbc Sep 14 '16 at 11:56
• @projetmbc Please see edit above. – cfr Sep 15 '16 at 23:05