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 wish to draw a complex work flow using tikz 2.0 because I tried to update the tikz to 2.1, there are many problems. The work work flow is described as follows: enter image description here I have tried to draw it by locating the rectangles using coordinator, however it is very hard to make it precise, is there any simpler and better way? Thanks! the code I tried is

    \documentclass{minimal}
\usepackage{tikz}
\usepackage{pgf}
\usetikzlibrary{arrows,automata} 
\usetikzlibrary{shapes}
\begin{document}


\begin{tikzpicture}
\draw (-4,-4) rectangle (4,4);
\draw (-0.5,0)  rectangle (-3,-3);
\draw (0.5,0)   rectangle (3,-3);
\draw (-1,0)    rectangle (-2,-1);

\end{tikzpicture}

\end{document}
share|improve this question
add comment

2 Answers

up vote 8 down vote accepted

Disclaimer

Just after writing this whole answer, I read Alain Matthes' one and realized that the question was about tikz 2.0. I overlooked this requirement so my answer is probably not useful for the OP. But I decided to leave here anyway because it illustrates some techniques which can be useful to other readers.

Original answer

You should use positioning library in order to get rid of absolute coordinates, and fit library to draw nodes around other nodes. Let's build your example step by step:

First, nodes a, b, c, and d can be positioned relatively each other the following way:

\documentclass{standalone}
\usetikzlibrary{positioning,fit,shapes.geometric,calc}
\usepackage{tikz}
\begin{document}

\tikzset{
  my box/.style = {draw, minimum width = 3em, minimum height=1.5em},
}
\begin{tikzpicture}[node distance=5mm]
\node[my box]             (a) {a};
\node[my box, below=of a] (b) {b};
\draw[->] (a) -- (b);

\node[my box, right=1cm of a] (c) {c};
\node[my box, below=of c]     (d) {d};
\draw[->] (c) -- (d);

\end{tikzpicture}
\end{document}

abcd

Then you can use fit to draw the rectangles around these:

\node[draw, fit=(a) (b)] (ab) {};
\node[draw, fit=(c) (d)] (cd) {};

fit

Now, you can add the diamond and connections to (ab) and (cd). To position the diamond properly centered, I use an auxiliar coordinate (aux) interpolated between (ab) and (cd):

\coordinate (aux) at ($(ab.north)!.5!(cd.north)$);
\node[draw, diamond, above=of aux] (diamond) {};
\draw[->] (diamond) -| (ab);
\draw[->] (diamond) -| (cd);

diamond

Now, using fit again, we draw the box around all of this. But there is a problem, since I presume you want that box of the same size than the one which contains e and f (to be drawn later). A workaround can be to give it a minimum height, and use the same amount for both boxes. This minimum height is found by trial and error, and this is why I don't like very much this part...

\node[draw, fit=(diamond) (ab) (cd), minimum height=3.5cm] (left part) {};

left part

Finally, using the same techniques again, you can position nodes e and f relative to c, and fit a box of a minimum height around them. In order to get a proper alignment of the right box with the left one, I had to insert a "invisible" diamond on top of e:

\node[my box, right=2cm of c, label=90:hl] (e) {e};
\node[my box, below=of e]     (f) {f};
\node[diamond, above=of e] (diamond aux) {};
\node[draw, fit=(diamond aux) (f), minimum height=3.5cm] (right part) {};

left-and-right

Finally, the last diamond is added using the same technique than for the first one:

\coordinate (aux) at ($(left part.south)!.5!(right part.south)$);
\node[draw, diamond, below=of aux] (cross diamond) {};
\draw (cross diamond.north) -- (cross diamond.south)
      (cross diamond.west) -- (cross diamond.east);
\draw[->, shorten >=1pt] (left part) |- (cross diamond);
\draw[->, shorten >=1pt] (right part) |- (cross diamond);

This completes the figure (and after it, the complete code):

complete

The code

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,fit,shapes.geometric,calc}
\begin{document}
\tikzset{
my box/.style = {draw, minimum width = 3em, minimum height=1.5em},
}

\begin{tikzpicture}[node distance=5mm]
\node[my box]             (a) {a};
\node[my box, below=of a] (b) {b};
\draw[->] (a) -- (b);

\node[my box, right=1cm of a] (c) {c};
\node[my box, below=of c]     (d) {d};
\draw[->] (c) -- (d);

\node[draw, fit=(a) (b)] (ab) {};
\node[draw, fit=(c) (d)] (cd) {};

\coordinate (aux) at ($(ab.north)!.5!(cd.north)$);
\node[draw, diamond, above=of aux] (diamond) {};
\draw[->] (diamond) -| (ab);
\draw[->] (diamond) -| (cd);

\node[draw, fit=(diamond) (ab) (cd), minimum height=3.5cm] (left part) {};

\node[my box, right=2cm of c, label=90:hl] (e) {e};
\node[my box, below=of e]     (f) {f};
\node[diamond, above=of e] (diamond aux) {};
\node[draw, fit=(diamond aux) (f), minimum height=3.5cm] (right part) {};

\coordinate (aux) at ($(left part.south)!.5!(right part.south)$);

\node[draw, diamond, below=of aux] (cross diamond) {};
\draw (cross diamond.north) -- (cross diamond.south)
      (cross diamond.west) -- (cross diamond.east);
\draw[->, shorten >=1pt] (left part) |- (cross diamond);
\draw[->, shorten >=1pt] (right part) |- (cross diamond);

\end{tikzpicture}
\end{document}
share|improve this answer
    
thanks, it helps a lot, anther question, how to move the labe h1 at the top of the rectangle? it seems very near to the box –  sweetyBaby Feb 14 '13 at 9:23
    
@sweetyBaby You can move the label=90:hl option to the node diamond aux, which is an invisible node at top of e. –  JLDiaz Feb 14 '13 at 9:27
    
@sweetyBaby or, for fine grained positioning you can remove the option label=90:hl and manually place the text below the top border of the rectangle, with \node[below=2mm of right part.north] {hl}; –  JLDiaz Feb 14 '13 at 9:29
    
thanks, if I want to add label "test" besides the arrow that connects box "a" and "b", I tried "\draw[->] (a) -- (b){test};" but it doesn't work –  sweetyBaby Feb 14 '13 at 11:17
    
@sweetyBaby you can only typeset text inside a node (or a label option which is a shortcut for a node). But you can add nodes to a line. You have to specify the position inside the line (eg: midway) and the position of the text with respect the line (eg: left). In summary: \draw[->] (a)--(b) node[midway, left] {test}; –  JLDiaz Feb 14 '13 at 16:12
add comment

It's not easy to work with pgf 2.0 because I forgot a lot of things. It's possible to use the calc library with pgf 2.00 but here I used an old method to build the picture. If this code works for you, You can get a better code with some helps.

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{arrows,fit,shapes} 
\begin{document}


\begin{tikzpicture}
\tikzstyle{rec}=[draw,minimum width = 1cm,minimum height=.75cm,outer sep=6pt]  
\node[rec] (a) at (0,0) {a};
\node[rec] (b) at ([yshift=-2cm]a) {b}; 
\node[rec] (c) at ([xshift=3cm]a) {c};
\node[rec] (d) at ([yshift=-2cm]c) {d};
\coordinate (x) at ([xshift=-0.25cm,yshift=+0.25cm] a.north west);
\coordinate (y) at ([xshift=+0.25cm,yshift=-0.25cm] b.south east);
\coordinate (u) at ([xshift=-0.25cm,yshift=+0.25cm] c.north west);
\coordinate (v) at ([xshift=+0.25cm,yshift=-0.25cm] d.south east);

\coordinate (xx) at ([xshift=-1.25cm,yshift=+2.25cm] a.north west);
\coordinate (yy) at ([xshift=+1.25cm,yshift=-1.25cm] d.south east);
\node [draw,fit=(x)(y)] (rec1){};
\node [draw,fit=(u)(v)] (rec2){};

\node [draw,fit=(xx)(yy)] (rec3){};
\draw[->] (a) -- (b);
\draw[->] (c) -- (d);

\path (rec1.north) -- (rec2.north) node[shape=diamond,minimum size=.75cm,pos=.5,yshift=1cm,draw](dia)  {} ;
\draw[<-] (rec1) |- (dia);
\draw[<-] (rec2) |- (dia);
\end{tikzpicture}

\end{document} 

enter image description here

share|improve this answer
add comment

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.