Draw Transition Tree for Stack
It is most unwise to next tikzpicture environments. Since a forest environment is simply a wrapper for a tikzpicture, it is therefore most unwise to put forest environments inside \node{} within tikzpictures.
It is, however, possible to put everything within a single forest environment.
First, though, a variation on Bordaigorl's alternative solution, which just tidies up the style a bit and automatises things a bit more.
This changes the circles style to add the $...$ wrapper automatically, together with a \strut for more even circle sizes, and automatically sets the width of each node to be sufficiently large to accommodate the widest node in the tree. This avoids needing to fiddle with the value of text width to get the sizing right.
I've also specified the mid anchor so that nodes are aligned on the baseline, which is probably what you want.
I then define a new style, colour me=<colour> which colours all node borders, contents and edges in the specified colour for the current node's sub-tree. This means that unless you later change the colouring, the current node and all its descendants will be coloured in the specified way.
\documentclass{article} \usepackage{forest} % Code from Bordaigorl's answer at https://tex.stackexchange.com/a/320421/, based on Alan Munn's answer at https://tex.stackexchange.com/a/320316/, based on René G's question at https://tex.stackexchange.com/q/320312/ \begin{document} \forestset{% declare dimen register=circles width, circles width'=0pt, circles/.style={% for tree={% circle, draw, text centered, edge=->, anchor=mid, delay={% content/.wrap value=\strut$##1$, } }, before typesetting nodes={% circles width/.max={width("\foresteoption{content}")}{tree}, delay={% for tree={% text width/.register=circles width, }, }, }, }, colour me/.style={% for tree={% +edge=#1, text=#1, draw=#1, }, }, } % \scalebox{.5}{% \begin{forest} circles [+ [\times, colour me=red [C_0] [x] ] [\log [+ [x] [C_1] ] ] ] \end{forest} % \raisebox{2cm}{$\longrightarrow$\quad} % \begin{forest} circles [+ [\sin, colour me=red [x] ] [\log [+ [x] [C_1] ] ] ] \end{forest}% } \end{document}
Getting a bit more complex, we can include both trees inside a single forest environment by using a phantom root.
To avoid complications with the phantom, we adjust the changes made to the content of nodes by circles:
delay={% if={strequal(content(),"")&&(level()==0)}{}{% content/.wrap value=\strut$##1$, } } This won't change anything if the root has content, but if the root has no content, it won't try to alter it.
We can then write our trees as follows
\begin{forest} circles [, phantom, for children={fit=band} [+ [\times, colour me=red [C_0] [x] ] [\log [+ [x] [C_1] ] ] ] % \raisebox{2cm}{$\longrightarrow$\quad} [+ [\sin, colour me=red [x] ] [\log [+ [x] [C_1] ] ] ] ] \end{forest}
Obviously we need to put the arrow back in. We can use the calc and fit TikZ libraries to good effect here, modifying our phantom root node a bit:
[, phantom, for children={fit=band}, s sep+=5mm, before drawing tree={% tikz+={% \node (a) [inner sep=0pt, fit=(!1) (!1L) (!1F)] {}; \node (b) [inner sep=0pt, fit=(!l) (!lL) (!lF)] {}; \node [anchor=center] at ($(a.east)!1/2!(b.west)$) {$\longrightarrow\quad$}; }, }, to produce
which is better. However, it is a bit of a pain to have to do it this way.
It would be nicer if we didn't need to specify the phantom root explicitly and if we could just add the arrow by specifying say, the node the arrow should be drawn from (or to).
We'll deal with the arrows first by adding the following to \forestset:
declare boolean={made room}{0}, arrow to/.style={% for parent={% if made room={}{% for children={fit=band}, s sep+=5mm, made room, }, }, before drawing tree={% tikz+={% \node (a) [inner sep=0pt, fit=() (!L) (!F)] {}; \node (b) [inner sep=0pt, fit=(!#1) (!#1L) (!#1F)] {}; \node [anchor=center] at ($(a.east)!1/2!(b.west)$) {$\longrightarrow\quad$}; }, }, }, arrow to/.default=n, This allows us to specify our phantom root simply with
[, phantom and we can create the arrow by adding our style to the first child
[+, arrow to This will use n by default, for the next child. If we wanted something else, we could specify it. (I'm not sure what else would make sense, but who knows?)
If you need arrows in the other direction, obviously you could add an arrow from style along similar lines.
We add
arrow symbol/.store in=\myarrowsymbol, arrow symbol=\longrightarrow, so that we can use myarrowsymbol in the node rather than hard-coding \longrightarrow\quad. We can then add
, arrow symbol=\longrightarrow\quad to the first child to add the spacing adjustment relevant for this particular case.
Doing away with the need to specifying the phantom root is a bit more involved. The easiest approach is probably to use the environ package to define a new environment as follows.
\environbodyname\circlestreebody \bracketset{action character=@} \NewEnviron{circlestree}{% \forest circles [, phantom @\circlestreebody] \endforest } We can then write our tree simply as
\begin{circlestree} [+, arrow to, arrow symbol=\longrightarrow\quad [\times, colour me=red [C_0] [x] ] [\log [+ [x] [C_1] ] ] ] [+ [\sin, colour me=red [x] ] [\log [+ [x] [C_1] ] ] ] \end{circlestree} to produce the output shown above.
The 4 tree case then becomes
\begin{circlestree} [+ [\times, colour me=red [C_0] [x] ] [C_1] ] [+, arrow to [\sin, colour me=red [x] ] [C_1] ] [+ [\sin, colour me=red [x] ] [C_1] ] [+ [\times, colour me=red [C_0] [x] ] [C_1] ] \end{circlestree} and produces
I'm not sure what spacing you want, but you can tweak the s sep+ as you wish, of course.
Complete code:
\documentclass[border=10pt,multi,tikz]{standalone} \usepackage{forest} \usetikzlibrary{calc,fit} \environbodyname\circlestreebody \bracketset{action character=@} \NewEnviron{circlestree}{% \forest circles [, phantom @\circlestreebody] \endforest } % Code from Bordaigorl's answer at https://tex.stackexchange.com/a/320421/, based on Alan Munn's answer at https://tex.stackexchange.com/a/320316/, based on René G's question at https://tex.stackexchange.com/q/320312/ \begin{document} \forestset{% declare dimen register=circles width, circles width'=0pt, declare boolean={made room}{0}, circles/.style={% for tree={% circle, draw, text centered, edge=->, anchor=mid, delay={% if={strequal(content(),"")&&(level()==0)}{}{% content/.wrap value=\strut$##1$, } } }, before typesetting nodes={% circles width/.max={width("\foresteoption{content}")}{tree}, delay={% for tree={% text width/.register=circles width, }, }, }, }, colour me/.style={% for tree={% +edge=#1, text=#1, draw=#1, }, }, arrow to/.style={% for parent={% if made room={}{% for children={fit=band}, s sep+=5mm, made room, }, }, before drawing tree={% tikz+={% \node (a) [inner sep=0pt, fit=() (!L) (!F)] {}; \node (b) [inner sep=0pt, fit=(!#1) (!#1L) (!#1F)] {}; \node [anchor=center] at ($(a.east)!1/2!(b.west)$) {$\myarrowsymbol$}; }, }, }, arrow to/.default=n, arrow symbol/.store in=\myarrowsymbol, arrow symbol=\longrightarrow, } \begin{circlestree} [+, arrow to, arrow symbol=\longrightarrow\quad [\times, colour me=red [C_0] [x] ] [\log [+ [x] [C_1] ] ] ] [+ [\sin, colour me=red [x] ] [\log [+ [x] [C_1] ] ] ] \end{circlestree} \begin{circlestree} [+ [\times, colour me=red [C_0] [x] ] [C_1] ] [+, arrow to [\sin, colour me=red [x] ] [C_1] ] [+ [\sin, colour me=red [x] ] [C_1] ] [+ [\times, colour me=red [C_0] [x] ] [C_1] ] \end{circlestree} \end{document} Source: https://tex.stackexchange.com/questions/320312/tree-then-arrow-then-tree
0 Response to "Draw Transition Tree for Stack"
Post a Comment