9

I was wondering if there is a way to avoid arrows crossing one another like they do in the figure below. It is the arrows going from "account", "pin", and "verify" I want to go around "log" so that there are no arrows crossing one another. The code is down below as well, thanks in advance!

enter image description here

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{automata,arrows}
\begin{document}
\begin{figure}
\hspace{-3cm}
\begin{tikzpicture}[
->,>=stealth',
shorten >=1pt,
auto,
node distance=5cm,
thick,
transform shape,
%main state/.style={}
%state/.style={font=\sffamily\Large\bfseries}
buffer/.style={rectangle,draw,minimum width=2cm,minimum height=1cm,align=center}
]
  \node[state,initial,accepting,minimum size=2cm] (1) {Idle};
  \node[state] (2) [right of=1] {Select Fuel};
  \node[state] (3) [right of=2] {Payment};
  \node[state] (4) [below right of=3] {Account};
  \node[state] (5) [below left of=4]{PIN};
  \node[state] (6) [below of=3]{Cash};
  \node[state] (7) [left of=5]{Verify};
  \node[state] (8) [left of=6]{Pump};
  \node[state] (9) [left of=8]{Log};
 % \node[buffer] (10) [left of=9]{buffer};
  \path[every node/.style={font=\sffamily\scriptsize}]
    (1) edge [bend left] node[above] {PressStar/} (2)
    (2) edge [bend left] node[above] {PressStar/} (3)
        edge [loop above] node[above] {Press2/FuelSelect95} (2)
        edge [loop left] node [below,yshift=-8pt] {Press1/FuelSelect92} (2)
        edge [loop right] node [below,yshift=-8pt] {Press3/FuelSelectOC} (2)
    (3) edge [bend left] node[right] {ChooseAcc/} (4)
        edge [bend left] node[left] {InstertCash/IncCash} (6)
    (4) edge [bend left] node[right] {NumberEnter6/StoreAccNo} (5)
        edge [bend left] node[right] {TimeOut15/} (1)
    (5) edge [bend left] node[below] {NumberEnter4/StorePIN} (7)
        edge [bend left] node[above,yshift=36pt,xshift=-28pt] {TimeOut15/} (1)
    (6) edge [loop below] node {InsertCash/IncCash} (6)
        edge [bend left] node { } (8)
    (7) edge [bend left] node[right] {NotVerified/} (1)
        edge [bend left] node[right,yshift=-5pt] {Verified/} (8)
    (8) edge [bend left] node {LeftOL,ReachMaxFuel,TimeOut15/} (9)
    (9) edge [bend left] node {PressStar/} (1);
\end{tikzpicture}
\end{figure}
\end{document}
  • 2
    Play with in and out angles instead of just using bend left and bend right. It's documented in section "70 To Path Library". – Ignasi May 5 '14 at 14:12
  • It's worth trying to write the graph in dot format and letting graphviz worry about node placement. You can then import it in your tex file and combine it with tikz using the dot2texi package (see this page for an example). – Anthony Labarre Oct 2 '15 at 14:58
6

Here's one possible solution using bend left=130,looseness=2; I also added a pgfinterruptboundingbox environment to avoid the bounding box to grow to be too large due to the looseness option:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{automata,arrows}
\begin{document}
\begin{figure}
\hspace{-3cm}
\begin{tikzpicture}[
->,>=stealth',
shorten >=1pt,
auto,
node distance=5cm,
thick,
transform shape,
%main state/.style={}
%state/.style={font=\sffamily\Large\bfseries}
buffer/.style={rectangle,draw,minimum width=2cm,minimum height=1cm,align=center}
]
  \node[state,initial,accepting,minimum size=2cm] (1) {Idle};
  \node[state] (2) [right of=1] {Select Fuel};
  \node[state] (3) [right of=2] {Payment};
  \node[state] (4) [below right of=3] {Account};
  \node[state] (5) [below left of=4]{PIN};
  \node[state] (6) [below of=3]{Cash};
  \node[state] (7) [left of=5]{Verify};
  \node[state] (8) [left of=6]{Pump};
  \node[state] (9) [left of=8]{Log};
 % \node[buffer] (10) [left of=9]{buffer};
  \begin{pgfinterruptboundingbox}
  \path[every node/.style={font=\sffamily\scriptsize}]
    (1) edge [bend left] node[above] {PressStar/} (2)
    (2) edge [bend left] node[above] {PressStar/} (3)
        edge [loop above] node[above] {Press2/FuelSelect95} (2)
        edge [loop left] node [below,yshift=-8pt] {Press1/FuelSelect92} (2)
        edge [loop right] node [below,yshift=-8pt] {Press3/FuelSelectOC} (2)
    (3) edge [bend left] node[right] {ChooseAcc/} (4)
        edge [bend left] node[left] {InstertCash/IncCash} (6)
    (4) edge [bend left] node[right] {NumberEnter6/StoreAccNo} (5)
        edge [bend left=130,looseness=2] node[right] {TimeOut15/} (1)
    (5) edge [bend left] node[below] {NumberEnter4/StorePIN} (7)
        edge [bend left] node[above,yshift=36pt,xshift=-28pt] {TimeOut15/} (1)
    (6) edge [loop below] node {InsertCash/IncCash} (6)
        edge [bend left] node { } (8)
    (7) edge [bend left] node[right] {NotVerified/} (1)
        edge [bend left] node[right,yshift=-5pt] {Verified/} (8)
    (8) edge [bend left] node {LeftOL,ReachMaxFuel,TimeOut15/} (9)
    (9) edge [bend left] node {PressStar/} (1);
  \end{pgfinterruptboundingbox}
\end{tikzpicture}
\end{figure}
\end{document}

enter image description here

An alternative would be to use out=300,in=220,looseness=2.

  • 1
    Adding overlay option to path has the same effect if you wish. Not so much of a shortcut though. – percusse May 5 '14 at 22:11
  • @percusse Ah, that's a good thing to know, thanks. – Gonzalo Medina May 5 '14 at 22:19
8

I tried to avoid crossing arrows, still some polishing on arrows to make them look like a circle arround.

enter image description here

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{automata,arrows,calc}
\begin{document}
\begin{figure}
\hspace{-4cm}
\begin{tikzpicture}[
->,>=stealth',
shorten >=1pt,
auto,
node distance=5cm,
thick,
transform shape,
%main state/.style={}
%state/.style={font=\sffamily\Large\bfseries}
buffer/.style={rectangle,draw,minimum width=2cm,minimum height=1cm,align=center}
]

\xdef\Rad{7}

  \node[state,initial,accepting,minimum size=2cm] (1) at (90:\Rad) {Idle};
  \node[state] (2) at (30:\Rad) {Select Fuel};
  \node[state] (3) at (-30:\Rad) {Payment};
  \node[state] (4) at (90:.5*\Rad) {Account};
  \node[state] (5) at (-30:.5*\Rad) {PIN};
  \node[state] (6) at (-90:\Rad){Cash};
  \node[state] (7) at (-150:.5*\Rad) {Verify};
  \node[state] (8) at (-150:\Rad){Pump};
  \node[state] (9) at (-210:\Rad) {Log};
 % \node[buffer] (10) [left of=9]{buffer};

 \tikzset{every node/.style={font=\sffamily\scriptsize}}
  \path[draw]
    (1) edge [bend left] node[above right,pos=.4] {PressStar/} (2)
    (2) edge [bend left] node[right] {PressStar/} (3)
        edge [loop above] node[above] {Press2/FuelSelect95} (2)
        edge [loop left] node [below,yshift=-8pt] {Press1/FuelSelect92} (2)
        edge [loop right] node [below,yshift=-8pt] {Press3/FuelSelectOC} (2)
    (3) %edge [bend left] node[right] {ChooseAcc/} (4)
        edge [bend left] node[left] {InstertCash/IncCash} (6)
    (4) to[out=-80] node[left,text width=1.5cm] {NumberEnter6/\\StoreAccNo} (5)
        %edge [bend left] node[right] {TimeOut15/} (1)
    (5) edge [bend left] node[below] {NumberEnter4/StorePIN} (7)
        %edge [bend left] node[above,yshift=36pt,xshift=-28pt] {TimeOut15/} (1)
    (6) edge [loop below] node {InsertCash/IncCash} (6)
        edge [bend left] node { } (8)
    (7) %edge [bend left] node[right] {NotVerified/} (1)
        edge [bend left] node[right,yshift=-5pt] {Verified/} (8)
    (8) edge [bend left] node[text width=1.3cm] {LeftOL,\\ReachMaxFuel,\\TimeOut15/} (9)
    (9) edge [bend left] node {PressStar/} (1);

\draw (4) to[in=-120,out=120] node[right] {TimeOut15/} (1) ;
\draw (7) to[in=210,out=120] node[pos=.3] {NotVerified/} (1) ;
\draw (5) to[in=220,out=180] node[pos=.55,left] {TimeOut15/} (1) ;
\draw (3) to[in=-60,out=100] node[right] {ChooseAcc/} (4) ;

\end{tikzpicture}
\end{figure}
\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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