6

Does somebody help me to draw the following tree in TikZ (with different colors at leaves)? I have no idea how to draw particularly the horizontal line crossing the edges.

Thank you. Bestenter image description here

My code is here:

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usepackage{tikz-qtree}

\begin{document}

\begin{tikzpicture}[
    nodes={draw,rectangle,rounded corners=.8ex}, ->, 
    level distance=2cm, growth parent anchor=south
]

\Tree 
[.\node(p0){move-stack(p1a,q)}; 
    \edge node[draw=none,auto=right]{recursive-move(p1a,p1b,c11,c12)}; 
    [.\node(p1){move-topmost-container(p1a,p1b)}; 
        \edge node[draw=none,auto=right]{take-and-put(...)}; 
        \node(p3){take(crane1,l1a,c11,c12,p1a)};
        \node(p4){put(crane1,l1b,c11,pallet,p1b)};
    ]
    [.\node(p2){move-stack(p1a,p1b)}; 
        \edge node[draw=none,auto=right]{recursive-move(p1a,p1b,c12,pallet)}; 
        [.\node(p5){move-topmost-container(p1a,p1b)};
            \edge node[draw=none,auto=right]{take-and-put(...)}; 
            \node(p7){take(crane1,l1a,c11,c12,p1a)};
            \node(p8){put(crane1,l1b,c11,pallet,p1b)};
        ]
        [.\node(p6){move-stack(p1a,p1b)}; ] 
    ] 
]

\end{tikzpicture}

\end{document}

enter image description here

  • welcome to tex.ae! what you try so far? horizontal line is relative simple to add (just name nodes and draw them as \draw[->] ([yshift=...] <node name>) -- ..., but wrote your tree from scratch is not fun ..:-) – Zarko Jul 30 '18 at 10:01
4

solution with forest:

\documentclass[border=10pt]{standalone}
\usepackage[edges]{forest}
\usetikzlibrary{shadows}

\begin{document}
    \begin{forest}
    for tree={draw, rounded corners,
             fill = white,
       inner xsep = 1mm,
       inner ysep = 2mm,
                    drop shadow,
    % style of tree (edges, distances, direction)
             grow = south,
    parent anchor = south,
     child anchor = north,
             edge = {draw, semithick, -stealth},
        EL/.style = {edge label={node[midway, font=\small, inner sep=1pt, anchor=south east]{#1}},},
        FB/.style = {fill=blue!30},
            s sep = 3mm,        % sibling distance
            l sep = 12mm,       % level distance
              }
[{move-stack(p1a,q)}
    [{move-topmost-container(p1a,p1b)},             name=p1,
     EL={recursive-move(p1a,p1b,c11,c12)}
        [{take(crane1,l1a,c11,c12,p1a)},        FB, name=p3,
         EL={take-and-put(...)}
         ]
        [{put(crane1,l1b,c11,pallet,p1b)},      FB, name=p4
        ]
     ]
    [{move-stack(p1a,p1b)},                         name=p2,
        [{move-topmost-container(p1a,p1b)},         name=p5,
         EL={recursive-move(p1a,p1b,c12,pallet)}
            [{take(crane1,l1a,c11,c12,p1a)},    FB, name=p7,
             EL={take-and-put(...)}
             ]
            [{put(crane1,l1b,c11,pallet,p1b)},  FB, name=p8,
             ]
         ]
        [{move-stack(p1a,p1b)},                     name=p6,
         label=below:{do-nothing(p1a,p1b)}
        ]
    ]
]
\foreach \x [evaluate=\x as \y using int(\x-1)] in {2,4,6,8}
{
    \draw[gray, very thick, -stealth]
        ([shift={(-3mm,3mm)}] p\y.north) -- ([shift={(3mm,3mm)}] p\x.north);
}
\end{forest}

\end{document}

enter image description here

  • (+1) But it is very misleading to describe l sep and s sep as sibling and level distances. They are not. They are minimum distances, just as minimum width is a minimum size when talking about nodes. – cfr Jul 30 '18 at 23:35
  • @cfrm, you have right. comments deleted. – Zarko Jul 31 '18 at 7:35
  • Thank you all. I liked the approach to remove the space between the siblings :) – Vahid Mokhtari Jul 31 '18 at 12:30
  • 1
    @VahidMokhtari, instead saying "thank you" here is more preferred to vote good answer (by clicking on up-pen at top left side of answer) and accept ones, which solve your problem on the best way (by clicking on check mark, also at top left side of answer) – Zarko Jul 31 '18 at 12:51
7

To fill the background of a leaf, use \node [fill=<colour>] ... I made a style with that, so if you want to change the colour, just modify the style.

Zarko's suggestion for the arrows work fine, but you need to specify the anchor as well, so use e.g. \draw [->] ([yshift=3mm]p1.north) -- ([yshift=3mm]p2.north);. I used a \foreach loop to draw the arrows, which makes the code a bit shorter.

For the do-nothing, you can add a label to the node, i.e. \node [label={below:do-nothing(p1a,p1b)}] (p6){move-stack(p1a,p1b)};.

enter image description here

\documentclass[border=10pt]{standalone}
\usepackage{tikz-qtree}

\begin{document}

\begin{tikzpicture}[
    nodes={draw,rectangle,rounded corners=.8ex}, ->, 
    level distance=2cm, growth parent anchor=south,
    endleaf/.style={fill=blue!30}
]

\Tree 
[.\node(p0){move-stack(p1a,q)}; 
    \edge node[draw=none,auto=right]{recursive-move(p1a,p1b,c11,c12)}; 
    [.\node(p1){move-topmost-container(p1a,p1b)}; 
        \edge node[draw=none,auto=right]{take-and-put(...)}; 
        \node [endleaf] (p3){take(crane1,l1a,c11,c12,p1a)};
        \node [endleaf] (p4){put(crane1,l1b,c11,pallet,p1b)};
    ]
    [.\node(p2){move-stack(p1a,p1b)}; 
        \edge node[draw=none,auto=right]{recursive-move(p1a,p1b,c12,pallet)}; 
        [.\node(p5){move-topmost-container(p1a,p1b)};
            \edge node[draw=none,auto=right]{take-and-put(...)}; 
            \node [endleaf] (p7){take(crane1,l1a,c11,c12,p1a)};
            \node [endleaf] (p8){put(crane1,l1b,c11,pallet,p1b)}; 
        ]
        [.\node [label={below:do-nothing(p1a,p1b)}] (p6){move-stack(p1a,p1b)}; ] 
    ] 
]

\foreach [evaluate={\y=int(\x-1)}] \x in {2,4,6,8}
    \draw [-latex] ([yshift=3mm]p\y.north) -- ([yshift=3mm]p\x.north);
\end{tikzpicture}

\end{document}
  • Many thanks for your help. Have you also an idea to add "do-nothing(p1a,p1b)" below the most right-bottom node (as in my sample figure)? I don't know how to add that text! – Vahid Mokhtari Jul 30 '18 at 11:36
  • @VahidMokhtari Hadn't noticed that one, see updated answer. – Torbjørn T. Jul 30 '18 at 11:44
5

This is shamelessly based on Zarko's answer and is, basically, a more automated form of that solution, with slightly more flexible and streamlined code.

    parent anchor=children,
    child anchor=parent,

Where possible, my code uses anchors which are sensitive to the direction of the tree's growth. This is especially useful when specifying the code for the horizontal arrows, but good practice generally as it makes for greater flexibility.

  where n children=0{fill=blue!50!gray!25}{fill=white},

This saves having to apply the colour manually to each node which needs it. Since all those nodes are leaves and no leaves aren't coloured, it makes sense to use this feature to have Forest determine which ones to fill with blue and which with white.

  where={>O_={n}{1}}{tikz+={\draw [thick, shorten >=-10pt, shorten <=-10pt, -{Triangle[width=6pt,length=6pt]}] ([yshift=10pt].-children) -- ([yshift=10pt]!s.-children); }}{}

This code draws the horizontal arrows, without relying on the manual addition of name to each node. Every first child has a sibling and every such pair has an arrow above, but no other cases need arrows, so we use a node's being the first to decide whether or not to draw the arrow.

([yshift=10pt].-children) -- ([yshift=10pt]!s.-children)

This specifies the path from 10pt above the anchor .-children of the current node to 10pt above the anchor .-children of its sibling (!s). Again, .-children depends on the direction of growth of three tree.

I've also used arrows from arrows.meta as arrows such as -stealth are considered deprecated and do not support the new, more flexible and consistent syntax.

output

Complete code;

% addaswyd o ateb Zarko: https://tex.stackexchange.com/a/443859/
\documentclass[border=10pt]{standalone}
\usepackage{forest}
\usetikzlibrary{shadows,arrows.meta}
\begin{document}
\begin{forest}
  for tree={draw,
    rounded corners=.8ex,
    drop shadow,
    parent anchor=children,
    child anchor=parent,
    font=\sffamily,
    edge+={draw, semithick, -{Triangle[width=4pt,length=4pt]}},
    EL/.style={edge label={node[midway, font=\small\sffamily, anchor=south east, inner sep=1pt]{#1}},},
    FB/.style={fill=blue!30},
    l sep*=3,   
  },
  where n children=0{fill=blue!50!gray!25}{fill=white},
  where={>O_={n}{1}}{tikz+={\draw [thick, shorten >=-10pt, shorten <=-10pt, -{Triangle[width=6pt,length=6pt]}] ([yshift=10pt].-children) -- ([yshift=10pt]!s.-children); }}{}
  [{move-stack(p1a,q)}
    [{move-topmost-container(p1a,p1b)}, EL={recursive-move(p1a,p1b,c11,c12)}
      [{take(crane1,l1a,c11,c12,p1a)}, EL={take-and-put(...)}
      ]
      [{put(crane1,l1b,c11,pallet,p1b)},       
      ]
    ]
    [{move-stack(p1a,p1b)},                         
      [{move-topmost-container(p1a,p1b)}, EL={recursive-move(p1a,p1b,c12,pallet)}
        [{take(crane1,l1a,c11,c12,p1a)}, EL={take-and-put(...)}
        ]
        [{put(crane1,l1b,c11,pallet,p1b)},   
        ]
      ]
      [{move-stack(p1a,p1b)}, label={[font=\small\sffamily]below:{do-nothing(p1a,p1b)}}
      ]
    ]
  ]
\end{forest}
\end{document}

@cfr: Please feel free to remove the following. I just verified that your code works fine and could not resist to cast some shadows (as the groundhog day was too long ago ;-). -marmot

\documentclass[border=10pt]{standalone}
\usepackage{forest}
\usetikzlibrary{shadows.blur,arrows.meta}
\tikzset{
 shadowed/.style={%
 preaction={transform canvas={shift={(0,-2pt)}},draw=gray,very thick,draw opacity=.2},
 preaction={transform canvas={shift={(0,-3pt)}},draw=gray,very thick,draw opacity=.1},
 preaction={transform canvas={shift={(0,-4pt)}},draw=gray,very thick,draw opacity=.05},
 },
}
\begin{document}
\begin{forest}
  for tree={draw,
    rounded corners=.8ex,
    blur shadow,
    parent anchor=children,
    child anchor=parent,
    font=\sffamily,
    edge={shadowed, semithick, -{Triangle[width=4pt,length=4pt]}},
    EL/.style={edge label={node[midway, font=\small\sffamily, anchor=south east, inner sep=1pt]{#1}},},
    FB/.style={fill=blue!30},
    l sep*=3,   
  },
  where n children=0{fill=blue!50!gray!25}{fill=white},
  where={>O_={n}{1}}{tikz+={\draw [shadowed,thick, shorten >=-10pt, shorten <=-10pt, -{Triangle[width=6pt,length=6pt]}] ([yshift=10pt].-children) -- ([yshift=10pt]!s.-children); }}{}
  [{move-stack(p1a,q)}
    [{move-topmost-container(p1a,p1b)}, EL={recursive-move(p1a,p1b,c11,c12)}
      [{take(crane1,l1a,c11,c12,p1a)}, EL={take-and-put(...)}
      ]
      [{put(crane1,l1b,c11,pallet,p1b)},       
      ]
    ]
    [{move-stack(p1a,p1b)},                         
      [{move-topmost-container(p1a,p1b)}, EL={recursive-move(p1a,p1b,c12,pallet)}
        [{take(crane1,l1a,c11,c12,p1a)}, EL={take-and-put(...)}
        ]
        [{put(crane1,l1b,c11,pallet,p1b)},   
        ]
      ]
      [{move-stack(p1a,p1b)},fill=white,label={[font=\small\sffamily]below:{do-nothing(p1a,p1b)}}
      ]
    ]
  ]
\end{forest}
\end{document}

enter image description here

  • +1 as usual. Maybe with shadows.blur and shadowed from this answer it might come even closer to the OP's screen shot. – user121799 Jul 31 '18 at 3:53
  • 1
    Note in the OPs image the move-stack node on the right is not coloured. – Torbjørn T. Jul 31 '18 at 7:17
  • @marmot Thanks for your help and your approach, however the code doesn't compile completely. – Vahid Mokhtari Jul 31 '18 at 12:26
  • 1
    @VahidMokhtari You need to update your installation of TeX. You have rather an old version of Forest. – cfr Aug 1 '18 at 17:27
  • 1
    The error mentioned by @VahidMokhtari is just due to outdated software and not a result of the code here. (Well, it is a result in the sense that the code here uses current Forest, but there's no error in the code, as it were.) – cfr Aug 1 '18 at 23:40

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.