# Parameterizing TikZ Figure

I have this code that generates the process gantt chart:

\usetikzlibrary{shadows,arrows,positioning}
\begin{tikzpicture}[scale=0.75, transform shape]
\tikzset{every node/.style={minimum height=2em},
}

\node [draw, proc, minimum width=3em] (p2) {P2};
\node [draw, proc, minimum width=3em, right=0em of p2.east, anchor=west] (p3) {P3};
\node [draw, proc, minimum width=24em, right=0em of p3.east, anchor=west] (p1) {P1};

\node [below=of p2.west] {0}  edge [draw] (p2.west);
\node [below=of p2.east] {3} edge [draw] (p2.east);
\node [below=of p3.east] {6} edge [draw] (p3.east);
\node [below=of p1.east] {30} edge [draw] (p1.east);
\end{tikzpicture}


The output:

I can see a pattern over here and I can imagine passing the parameters (e.g. p2/3,p3/3,p1/24) to some command that uses some kind of for loop to automatically generate the code. Unfortunately, my TikZ/LaTeX skills are way below that. Can anyone help me get started with automating this?

-
Are you aware of the pgfgantt package? –  Marc van Dongen Feb 16 '12 at 8:29
I'm not actually looking for a gantt chart. Thanks for that tip, by the way. That might come in handy. The fig I'm trying to create is a simpler timing diagram. –  recluze Feb 16 '12 at 9:53
Perhaps this doesn't quite fit, but for timing diagrams there is tikz-timing. –  qubyte Feb 17 '12 at 10:51
@recluze: if any of the answers given below do what you need, please consider accepting them. Else, please tell us why they don't. –  romeovs Feb 17 '12 at 20:27

Try this:

\newcommand{\gantt}[1]{

\newcounter{ganttnum}
\setcounter{ganttnum}{0}

\foreach \i/\j in {#1}{
\draw (\theganttnum em,0)node [proc, minimum width=\j em, anchor=south west] (\i) {\i};
\draw (\theganttnum em,0) -- ++(0,-0.5) node[below]{\theganttnum};
}
\draw (\theganttnum em,0) -- ++(0,-0.5) node[below]{\theganttnum};
}

\begin{tikzpicture}[scale=0.75,transform shape]
\gantt{P2/3,P3/3,P1/24}
\end{tikzpicture}

\begin{tikzpicture}[scale=0.75,transform shape]
\gantt{A1/3,A2/10,A3/14,A5/3,A4/3}
\end{tikzpicture}


It creates a newcommand that takes 1 parameter, which should be a comma seperated list of the form P1/3,P2/5,P3/12. Every item has two parts: the node name (before / and the width of the node after the /).

This allows you to add an arbitrary number of nodes, with arbitrary names and widths.

A bit of explanation to the code:

Tikz' \foreach can take multiples for looping over eg. A/1, B/2, ... this comes in handy to keep the names and widths of the nodes togheter while looping over them.

I first let a counter gantt be set to 0. Each step in the loop adds the width of the node that gets added in that step be added to this counter, so the counter can be used to determine where the next node should be.

-
Thanks for this but the problem is that Ps are hard-coded. I want them to be "flexible". –  recluze Feb 16 '12 at 9:47
@recluze: Okay, modified the code for more flexibility. lthoug this doesn't allow for a different number of nodes. I'll look into the for loop thing and post something up quick. –  romeovs Feb 16 '12 at 11:27
@recluze the new code should do it. –  romeovs Feb 16 '12 at 11:41
That works perfectly. Exactly what I was looking for. The key was to use absolute placement, I think instead of right keys. –  recluze Feb 18 '12 at 3:23
@romeovs \newcounter{ganttnum} inside the macro is not very good ! –  Alain Matthes May 8 '12 at 15:00

\documentclass[border=3mm]{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[scale=0.75, transform shape]
\tikzset{every node/.style={minimum height=2em},
}

\node [draw, proc, minimum width=3em] (p2) {P2};

\foreach \i/\j/\k in {3/2/3,1/3/24}
\node [draw, proc, minimum width=\k em, right=0em of p\j.east, anchor=west] (p\i) {P\i};

\node [below=of p2.west] {0}  edge [draw] (p2.west);
\foreach \i/\j in {2/3,3/6,1/30}
\node [below=of p\i.east] {\j} edge [draw] (p\i.east);
\end{tikzpicture}
\end{document}


An updated version. Same loop will draw nodes and labels and a counter will take care of initial position of nodes. Once loop finishes, 0 mark is drawn.

\documentclass[border=3mm]{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[scale=0.75, transform shape]
\tikzset{every node/.style={minimum height=2em},
}

\newcounter{pos}
\setcounter{pos}{0}

\foreach \process/\width in {2/3,3/3,1/24}
{
\node [draw, proc, minimum width=\width em,  anchor=west] (p\process) at (\thepos em,0) {P\process};

Thanks for the for loop. That helps a lot. I don't see why I have to pass both 3/2/3,1/3/24 and 2/3,3/6,1/30. Shouldn't it be possible to somehow calculate the second set of values from the first? –  recluze Feb 16 '12 at 10:04