Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I am trying to draw a randomized tree using TikZ, that is, I'm looking for a macro \randtree{NN}{x} that attaches a randomized tree of maximum depth x to a node named NN. The nodes need not be visible or marked, I just want the lines.

I did a bit of research on randomized TikZ pictures, but since I never really used randomization with TikZ before, most of the examples were so complicated that I didn't understand what was going on (e.g. referring to tikz picture again in the same latex document) plus, most randomization examples (at least the ones I found) just randomize the shape of individual lines, wheras I want entire node structures to be randomized. Here is a (non-random, non-automatic) example of what I'm hoping for:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{positioning}

\newcommand\mytree[1]{
\coordinate[above right=1cm and 1.0cm of #1] (r);
\coordinate[above right=2cm and 2.0cm of r] (rr);
\coordinate[above left =1cm and 0.5cm of r] (rl);
\coordinate[above right=1cm and 1.0cm of rl] (rlr);
\coordinate[above left =1cm and 0.5cm of rl] (rll);
\coordinate[above left =1cm and 1.0cm of #1] (l);
\coordinate[above left =1cm and 1.0cm of l] (ll);
\coordinate[above right=2cm and 0.5cm of l] (lr);
\coordinate[above left =1cm and 1.0cm of lr] (lrl);
\coordinate[above right=1cm and 0.2cm of lr] (lrr);
\coordinate[above left =1cm and 1.0cm of ll] (lll);
\coordinate[above right=1cm and 0.5cm of ll] (llr);
\coordinate[above left =1cm and 1.0cm of rlr] (rlrl);
\draw[black] (lll) -- (ll);
\draw[black] (ll) -- (l);
\draw[black] (l) -- (sv);
\draw[black] (sv) -- (r);
\draw[black] (r) -- (rr);
\draw[black] (r) -- (rl);
\draw[black] (l) -- (lr);
\draw[black] (rl) -- (rll);
\draw[black] (rl) -- (rlr);
\draw[black] (ll) -- (llr);
}

\begin{document}

\begin{tikzpicture}[node distance=1cm and 0.4cm]
\coordinate (sv);
\mytree{sv};
\end{tikzpicture}

\end{document}

It's not required that all branches have the same total height at the end, nor is the absolute number of nodes of any interest. I just want to specify the maximum number of nodes from trunk to leaf, and the total scale of the tree (approximate height and width, both values are allowed to float up or down). The tree should alway grow from bottom to top, but if that's also customizable, even the better.

A ready-made solution would be too much to ask, so I'll be happy with a simple example or pointers to the appropriate sections of the TikZ manual.

Edit

Following a request from one of the comments, I try to be more clear about what I'm trying to achieve. I'm trying to reproduce the following graphic: Illustration of event structure simulated by a showering and hadronization generator.

I managed to make most of it on my own, the only thing still missing is the (more-or-less) random decay diagrams on top of the pink blobs (circled in red). Since the precise structure of these things is not of particular importance, nor is the fact that they have arrow tips at their end, I thought that the easiest way to generate them was to create a randomized tree of given size and attach it to the TikZ nodes at the pink blobs.

In the meantime, I opened another question on the same subject, trying to build these decay-chain-structures manually (Drawing recursive randomized structures with TikZ). If you have a solution on how to do this using a tree construct (forest, tikz-qtree, ...), please answer to this question - if you know a way how to manually create these structures, please anwer the one linked above.

Edit 2

Since I got a nice answer and was able to plug everything together, I figured I might as well make the source code of my picture available to everyone. Enjoy!

Preparation

\usetikzlibrary{positioning,arrows,patterns}
\usetikzlibrary{decorations.pathmorphing}
\usetikzlibrary{decorations.markings}
\usetikzlibrary{decorations.shapes}

\def\pgfdecoratedcontourdistance{0pt}

\pgfkeys{/pgf/decoration/contour distance/.code={%
    \pgfmathparse{#1}%
    \let\pgfdecoratedcontourdistance=\pgfmathresult}%
}

\pgfdeclaredecoration{contour lineto}{start}
{
    \state{start}[next state=draw, width=0pt]{
        \pgfpathmoveto{\pgfpoint{0pt}{\pgfdecoratedcontourdistance}}%
    }
    \state{draw}[next state=draw, width=\pgfdecoratedinputsegmentlength]{       
        \pgfmathparse{-\pgfdecoratedcontourdistance*cot(-\pgfdecoratedangletonextinputsegment/2+90)}%
        \let\shorten=\pgfmathresult%
        \pgfpathlineto{\pgfpoint{\pgfdecoratedinputsegmentlength+\shorten}{\pgfdecoratedcontourdistance}}%  
    }
    \state{final}{
        \pgfpathlineto{\pgfpoint{\pgfdecoratedinputsegmentlength}{\pgfdecoratedcontourdistance}}%
    }   
}

\tikzset{
  photon/.style={decorate, decoration={snake}, draw=black},
  crossed/.style={draw=black, postaction={decorate},decoration={markings,mark=at position .5 with {\draw (-2pt,-2pt) -- (2pt,2pt);\draw (2pt,-2pt) -- (-2pt,2pt);}}},
  fermion/.style={draw=black, postaction={decorate},decoration={markings,mark=at position .55 with {\arrow{>}}}},
  weak/.style={dashed, draw=black},
  special/.style={decorate,decoration={shape backgrounds,shape=circle,shape size=0.5pt,shape sep=2pt}},
  gluon/.style={decorate, draw=black,decoration={coil,amplitude=4pt, segment length=5pt}} ,
  hadron/.style={
    draw=black,
    postaction={
        decoration={contour lineto, contour distance=-2pt},
        draw=black, decorate},
    postaction={
        decoration={contour lineto, contour distance=2pt}, 
        draw=black, decorate}
  },
  meson/.style={
    draw=none,
    postaction={
        decoration={contour lineto, contour distance=-1pt},
        draw=black,decorate},
    postaction={
        decoration={contour lineto, contour distance=1pt}, 
        draw=black, decorate},
  },
  vertex/.style={draw,shape=circle,fill=black,minimum size=3pt,inner sep=0pt},
  bbvertex/.style={draw,shape=circle,pattern=north east lines,very thin,minimum size=12pt,inner sep=0pt}
}

\newcommand{\generateShower}[1]{
  \scalebox{.3}{
    \pgfmathsetseed{#1}
    \begin{forest}
      random tree/.style n args={2}{% #1=max levels, #2=max children
        if={##1>0}{repeat={random(0,##2)}{append={[,random tree={##1-1}{##2}]}}}{},
        parent anchor=center, child anchor=center, grow=north},
      [,random tree={3}{3}]
    \end{forest}
  }
}

Actual picture

\begin{tikzpicture}[node distance=1cm and 0.4cm]
%% the bottom part
\coordinate[vertex] (sv);
\coordinate[vertex,   below      =1cm and 0.4cm of sv] (pv);
\coordinate[bbvertex, below left =1cm and 0.4cm of pv] (vl);
\coordinate[bbvertex, below right=1cm and 0.4cm of pv] (vr);
\coordinate[          below left =1cm and 0.4cm of vl] (il);
\coordinate[          below right=1cm and 0.4cm of vr] (ir);
\coordinate[          above left =1cm and 0.4cm of vl] (fl);
\coordinate[          above right=1cm and 0.4cm of vr] (fr);
\draw[hadron] (il) -- (vl);
\draw[meson]  (vl) -- (fl);
\draw[fermion](vl) -- (pv);
\draw[hadron] (ir) -- (vr);
\draw[meson]  (vr) -- (fr);
\draw[fermion](pv) -- (vr);
%% the connecting line
\draw[photon] (pv) -- (sv);
%% the top part
\coordinate[  vertex,above right=2cm and 2.0cm of sv] (r);
\coordinate[  vertex,above left =0.5cm and 0.7cm of r] (rl);
\coordinate[  vertex,above right=0.5cm and 1.0cm of rl] (rlr);
\coordinate[  vertex,above left =0.5cm and 1.0cm of rl] (rll);
\coordinate[  vertex,above left =1cm and 1.0cm of sv] (l);
\coordinate[  vertex,above left =1cm and 1.0cm of l] (ll);
\coordinate[  vertex,above right=2cm and 0.5cm of l] (lr);
\coordinate[bbvertex,above left =1cm and 1.0cm of lr] (lrl);
\coordinate[bbvertex,above right=1cm and 0.2cm of lr] (lrr);
\coordinate[bbvertex,above left =2cm and 2.0cm of ll] (lll);
\coordinate[  vertex,above right=1cm and 0.5cm of ll] (llr);
\coordinate[bbvertex,right=1cm of lrr] (rlrl);
\coordinate[bbvertex,right=2.5cm of rlrl] (rr);
%% tree-level fermion lines
\draw[fermion] (lll) -- (ll);
\draw[fermion] (ll) -- (l);
\draw[fermion] (l) -- (sv);
\draw[fermion] (sv) -- (r);
\draw[fermion] (r) -- (rr);
%% connection gluons
\draw[gluon] (r) -- (rl);
\draw[gluon] (l) -- (lr);
\draw[gluon] (rl) -- (rll);
\draw[gluon] (rl) -- (rlr);
\draw[gluon] (ll) -- (llr);
%% branch-level fermion lines
\draw[fermion] (rr) -- (rlr);
\draw[fermion] (rlr) -- (rlrl);
\draw[fermion] (rlrl) -- (rll);
\draw[fermion] (rll) -- (lrr);
\draw[fermion] (lrr) -- (lr);
\draw[fermion] (lr) -- (lrl);
\draw[fermion] (lr) -- (lrl);
\draw[fermion] (lrl) -- (llr);
\draw[fermion] (llr) -- (lll);
%% decay chains for bb vertices: rr, lrl, lrr, lll, rlrl
\node[yshift=-5.5pt,xshift=-1.5pt,anchor=south] at (lll.north) {\generateShower{33333}};
\node[yshift=-5.5pt,xshift=-3pt,anchor=south]   at (lrl.north) {\generateShower{25763}};
\node[yshift=-5.5pt,xshift=2pt,anchor=south]    at (lrr.north) {\generateShower{76924}};
\node[yshift=-5.5pt,xshift=-4pt,anchor=south]   at (rlrl.north){\generateShower{45678}};
\node[yshift=-5.5pt,xshift=-1.5pt,anchor=south] at (rr.north)  {\generateShower{14285}};
%% lhs braces
\draw [decorate,decoration={brace,amplitude=5pt}] (-5,-3.5) -- (-5,-1.5)    
node [black,midway,xshift=-0.8cm,left,text width=3cm,align=right] {parton\\distributions};
\draw [decorate,decoration={brace,amplitude=5pt}] (-5.5,-1.5) -- (-5.5,0.5) 
node [black,midway,xshift=-0.3cm,left,text width=3cm,align=right] {hard\\scattering};
\draw [decorate,decoration={brace,amplitude=5pt}] (-5,0.4) -- (-5,3.8)      
node [black,midway,xshift=-0.8cm,left,text width=3cm,align=right] {parton\\shower};
\draw [decorate,decoration={brace,amplitude=5pt}] (-5.5,3.7) -- (-5.5,4.7)  
node [black,midway,xshift=-0.3cm,left,text width=3cm,align=right] {hadronization};
\draw [decorate,decoration={brace,amplitude=5pt}] (-5,4.6) -- (-5,5.7)      
node [black,midway,xshift=-0.8cm,left,text width=3cm,align=right] {decay};
\end{tikzpicture}

Result

Schematic illustration of the basic structure of a events simulated with a
showering and hadronisation generator. The time
evolution of the event goes from bottom to top.

share|improve this question
2  
How about the example on the first page of the documentation of the forest package? –  Kevin C Aug 16 '13 at 15:42
    
this was already quite helpful, I was able to compile the following within a matter of minutes:\pgfmathsetseed{401} \begin{forest} random tree/.style n args={2}{ if={#1>0}{ repeat={random(0,#2)}{ append={ [,random tree={#1-1}{#2}] } } } {} }, [,random tree={4}{3}] \end{forest} I don't see yet how I can remove the white background of the nodes, invert the tree to grow upward or attach the root to an existing tikz node, but we'll see! –  carsten Aug 16 '13 at 16:00
add comment

1 Answer

up vote 6 down vote accepted

This is an example modified based on page 1 of the forest package documentation.

Note the default anchors of the forest package is not the center of a node, and thus there appear to be white spaces between edges. To fix this, set both parent anchor and child anchor to center, so that they can "connect" with each other. The grow key specifies the direction to which the tree should grow. Since you want it to grow upwards, grow=north would do the trick.

\documentclass[border=2pt]{standalone}

\usepackage{forest}

\begin{document}
\pgfmathsetseed{14285}
\begin{forest}
random tree/.style n args={2}{% #1=max levels, #2=max children
if={#1>0}{repeat={random(0,#2)}{append={[,random tree={#1-1}{#2}]}}}{},
  parent anchor=center, child anchor=center, grow=north},
[,random tree={4}{3}]
\end{forest}
\end{document}

enter image description here


Update: Attaching tree to another node

This is probably not the best way to attach a forest tree to another tikz node, but it's the only thing I can come up with that works.

The idea is to put the forest tree inside a node, and use node positioning commands to "attach" it to another node. The main imperfection is that you have to manually adjust the yshift and \scalebox parameters. (I've tried using inner sep=0pt and outer sep=0pt. But those screwed up the forest picture.)

\documentclass{standalone}
\usepackage{forest}

\begin{document}

\pgfmathsetseed{12987}

\begin{tikzpicture}
  \node(s)[circle,fill=red]{some node};
  \node[yshift=-5.5pt,anchor=south]at(s.north){
    \scalebox{.5}{
      \begin{forest}
        random tree/.style n args={2}{% #1=max levels, #2=max children
        if={#1>0}{repeat={random(0,#2)}{append={[,random tree={#1-1}{#2}]}}}{},
        parent anchor=center, child anchor=center, grow=north},
        [,random tree={3}{3}]
      \end{forest}
    }
  };
\end{tikzpicture}

\end{document}

enter image description here

share|improve this answer
    
Very nice! I'll mark this answer as accepted as soon as I found a way to attach the tree to an existing node in a tikz picture. By the way - how to I scale a forest-tree? I want these trees to be really tiny :-) –  carsten Aug 16 '13 at 16:20
1  
@carsten On the attachment problem see Qrrbrbirlbel's answer to this question: How to reflect duplicating a tree horizontally? –  Alan Munn Aug 16 '13 at 16:31
    
@ Alan Munn: It's not entirely clear to me how this works, since the answer uses tikz-qtree instead of forest, but do I gather correctly that scope-environment is the key part? –  carsten Aug 16 '13 at 16:38
1  
@carsten: forest doesn't seem to offer a scaling option... A work around is to put the forest environment into a scalebox: \scalebox{<factor>}{\begin{forest}...\end{forest}. Another way is to manually set the length of the edges: in the definition of random tree style, add l=<length>, which sets the length of each edge to the specified dimension. A drawback of the latter approach is that there is a minimum length below which the program will ignore the command. –  Kevin C Aug 17 '13 at 9:28
1  
@carsten: I'm not sure I understand what you mean by attaching the tree to an existing node. Did you mean that you have multiple random trees and you want to link them to a separate node? Maybe it'd be easier if you can show some hand-drawn picture of what the desired result looks like. Or perhaps ask a new question. –  Kevin C Aug 17 '13 at 9:31
show 4 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.