I want to draw the following diagram in TikZ:

tikz diagram

Currently I use the following code to do this:



\begin{tikzpicture}[>=latex',node distance = 2cm]
 \node (S1) {$S_1$};
 \node [left of = S1] (S2) {$S_2$};
 \node [above of = S2,node distance=1.04cm] (A) {$A$}; 
 \node [above of = S1,node distance=1.04cm] (B) {$B$};

 \node [below of = S2,node distance=1.04cm] (C) {$C$};
 \node [below of = S1,node distance=1.04cm] (D) {$D$};

 \draw [->,thick] (S1) to[bend left=40] node {} (S2);
 \draw [->,thick] (S2) to[bend left=40] node {} (S1);

 \draw [->,thick] (A) to[bend right=40] node {} (B);
 \draw [->,thick] (D) to[bend right=40] node {} (C);



However you will notice that I am using an absolute distance (1.04cm) to make sure that the curves intersect at the mid points. If I change the node distance, the absolute distance must be manually adjusted each time by trial and error. Is there anyway to draw such a diagram using TikZ without using the absolute distance so that when I change the node distance the curves adjust automatically?

3 Answers 3


You may try out following approach. Despite it also uses some magic constants, but having worked them out once (well, I did it for you :)), you don't need to alter them anymore. \coeffx and \coeffy are already gracefully set for you, it is left to adjust \nodedistancex and \nodedistancey as you wish.



\def \coeffx{0.29}
\def \coeffy{0.91}
\def \nodedistancex{4cm}
\def \nodedistancey{1cm}
\def \offsetx{\nodedistancex*\coeffx}
\def \offsety{\nodedistancey*\coeffy}


\begin{tikzpicture}[>=latex', node distance=\nodedistancey and \nodedistancex]
 \node (S1) {$S_1$};
 \node[left=of S1] (S2) {$S_2$};
 \node[above=of S2] (A) {$A$}; 
 \node[above=of S1] (B) {$B$};
 \node[below=of S2] (C) {$C$};
 \node[below=of S1] (D) {$D$};

 \draw[->,thick] (S1) .. controls +(-\offsetx,\offsety) and +(\offsetx,\offsety) .. (S2);
 \draw[->,thick] (S2) .. controls +(\offsetx,-\offsety) and +(-\offsetx,-\offsety) .. (S1);
 \draw[->,thick] (A) .. controls +(\offsetx,-\offsety) and +(-\offsetx,-\offsety) .. (B);
 \draw[->,thick] (D) .. controls +(-\offsetx,\offsety) and +(\offsetx,\offsety) .. (C);


enter image description hereenter image description here


One solution is as follows. On purpose, I added rows to the diagram, so that you can see one of the benefits of the loops. The output is


The code is (I hope it is self-explanatory) :






\matrix[matrix of math nodes,column sep=2cm,row sep = 1cm] (m) {

\foreach \k in {1,...,\rows}{
    \coordinate (c\k) at ($(m-\k-1)!0.5!(m-\k-2)$);

\foreach \k [count=\kprev] in {2,...,\rows}{

    \ifodd \k

    \coordinate (c) at ($(c\kprev)!0.5!(c\k)$);
    \draw[dir] (m-\kprev-1) to[out=-45,in=180] (c) to[out=0,in=225] (m-\kprev-2);
    \draw[dir] (m-\k-1) to[out=45,in=180] (c) to[out=0,in=135] (m-\k-2);



Edit : fixed the code to correct for the arrows

  • Nice solution, Frederic! Commented May 5, 2011 at 3:32
  • I like this one. The point is that you know that you want the curves to intersect and you know where those intersections should be - indeed, it's easier for you to see that than it is for the computer! So you tell the computer exactly where to put the curves. Commented May 5, 2011 at 6:59

you can add a dot in the middle of the path between A and S1 then draw the two arcs by that point



\begin{tikzpicture}[>=latex',node distance = 2cm]
 \node (S1) {$S_1$};
 \node [left of = S1] (S2) {$S_2$};
 \node [above of = S2,node distance=1.5cm] (A) {$A$}; 
 \node [above of = S1,node distance=1.5cm] (B) {$B$};

 \node [below of = S2,node distance=1.3cm] (C) {$C$};
 \node [below of = S1,node distance=1.3cm] (D) {$D$};

\path(A) -- (S1)coordinate[pos=0.5](inter1);
\path(C) -- (S1)coordinate[pos=0.5](inter2);
 \draw [->,thick] (S1) to[out=135,in=0] (inter1) to [out=180,in=45] (S2);
 \draw [->,thick] (S2) to[out=-45,in=180] (inter2) to [out=0,in=-135] (S1);
 \draw [->,thick] (A) to[out=-45,in=180] (inter1) to [out=0,in=-135]  (B);
 \draw [->,thick] (D)  to[out=135,in=0] (inter2) to [out=180,in=45] (C);




You must log in to answer this question.

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