2

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},
        proc/.style={draw=black, fill=blue!15, drop shadow},
      }

      \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:

Process Gantt Chart

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?

4
  • 3
    Are you aware of the pgfgantt package?
    – user10274
    Feb 16, 2012 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, 2012 at 9:53
  • Perhaps this doesn't quite fit, but for timing diagrams there is tikz-timing.
    – qubyte
    Feb 17, 2012 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, 2012 at 20:27

2 Answers 2

4

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};
         \addtocounter{ganttnum}{\j}
     }
     \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 /).

gantt, third try

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.

6
  • Thanks for this but the problem is that Ps are hard-coded. I want them to be "flexible".
    – recluze
    Feb 16, 2012 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, 2012 at 11:27
  • @recluze the new code should do it.
    – romeovs
    Feb 16, 2012 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, 2012 at 3:23
  • @romeovs \newcounter{ganttnum} inside the macro is not very good ! May 8, 2012 at 15:00
2

You can start with this code

\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shadows,arrows,positioning}

\begin{document}
\begin{tikzpicture}[scale=0.75, transform shape]
      \tikzset{every node/.style={minimum height=2em},
        proc/.style={draw=black, fill=blue!15, drop shadow},
      }

\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}
\usetikzlibrary{shadows,arrows,positioning}

\begin{document}
\begin{tikzpicture}[scale=0.75, transform shape]
      \tikzset{every node/.style={minimum height=2em},
        proc/.style={draw=black, fill=blue!15, drop shadow},
      }

\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};
    \addtocounter{pos}{\width}
    \node [below=of p\process.east] {\thepos} edge [draw] (p\process.east);
}
\node [below=of p2.west] {0} edge [draw] (p2.west);

\end{tikzpicture}

\end{document}
2
  • 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, 2012 at 10:04
  • @recluze I've updated the answer with a version which calculates values. It uses absolutes positions but I don't know to do it better now.
    – Ignasi
    Feb 17, 2012 at 10:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .