# Orthogonal path routing

TLDR; Is there a way I can specify a start and end point it it would route (hopefully orthogonally) around all nodes and other paths.

I'm converting a large number of visio flow charts to TikZ and keep running into one issue. Orthogonal* paths with more than one bend are hard to do. I'm also trying to keep the diagrams dynamic so any future changes can be made without tweaking the chart a bunch.

Now, I'm able to make these and keep them dynamic, but it seems much harder than it should be. Take the red line: that line required a minimum of 3 distinct points and to keep it dynamic, I ended up using 5! It would be nice if I could just specify a start and end point it it would route around all nodes and other paths.

*I'm using terminology from Omnigraffle, so what I mean is that any change in direction for the path is multiple of 90 degrees.

\documentclass{article}

\usepackage{tikz}
\usepackage[margin=0.5in]{geometry}
\pagestyle{empty}

\begin{document}

%\input{../tikz-setup.tex}
\usetikzlibrary{shapes, arrows, calc, positioning}

% Define block styles
\tikzstyle{state}   = [ rounded rectangle,
draw,
text centered,
minimum height=3em ,
minimum width = 6em,
inner sep = 5pt
]
\tikzstyle{test}    = [ diamond,
draw,
shape aspect=2,
inner sep = 0pt,
text width = 7em,
text centered
]
\tikzstyle{action}  = [ rectangle, draw,
text width=8em,
inner sep = 5pt,
minimum height=5em
]
\tikzstyle{data}    = [ trapezium,
draw,
trapezium left angle=60,
trapezium right angle=120pt,
minimum height = 6em,
text width = 5em
]
\tikzstyle{line}    = [ draw, -triangle 45 ]

\begin{center}
\begin{tikzpicture}[align = flush center, font = \small]
% Place nodes
\matrix [column sep = 2.5em, row sep = 2em] (mtrx)
{

\node [state] (a) {a}; &[1em]
\node (b) {}; \\

\node [action] (c) {c}; &
\node [action] (d) {d}; \\

\node [test] (e) {e}; &
\node [test] (f) {f}; \\

\node [action] (g) {g}; &
\node [action] (h) {h}; \\

\node [action] (i) {i};&
\node [action] (j) {j}; \\

&
\node [state] (k) {k}; \\
};

% Draw edges
\path [line] (a) -- (c);
\path [line] (c) -- (e);

\path [line] (e) -- node [right, near start] {Yes} (g);
\path [line] (e.east) -- node [above] {No} ( $(e.east)!0.3!(f.west)$ ) |- ( $(g)!0.45!(i)$ );

\path [line] (g) -- (i);

\path [line,red] let \p1=( $(a.south)!0.6!(b.south)$ ) in (i.south) -- +(0, -0.5) -| (\p1) -| (d.north);

\end{tikzpicture}
\end{center}
\end{document}


original image

-
If you provide a code snippet for your example/what you archieved so far nobody had to guess what you were able to do on your own. Do you know, for instance, about the |-/-| syntax? –  Qrrbrbirlbel Sep 10 '12 at 22:40
What is the context of dynamic here? Note that node avoidance etc. are non-trivial tasks and not possible with TikZ (yet). Also can you show us your 5 point code? I am almost sure that it can be reduced via relative positioning. –  percusse Sep 11 '12 at 0:20
I'm meaning dynamic is the sense that I'm using relative positions so I could write a book in one of the nodes and the lines would adjust accordingly. –  blitzvergnugen Sep 11 '12 at 12:52
Here's the 5 point line pulled out of the code \path [line,red] let \p1=( $(a.south)!0.6!(b.south)$ ) in (i.south) -- +(0, -0.5) -| (\p1) -| (d.north);. The let is cruft from an older attempt and unnecessary. –  blitzvergnugen Sep 11 '12 at 13:15
Would \draw[-triangle 45,red] (i.south) -- ++(0,-5mm) -| ([shift={(-5mm,5mm)}]d.north west) -| (d); be simple enough? –  percusse Sep 11 '12 at 14:13

if you often need this functionality, I recommend this to create a specific command, eg

\newcommand{\renvoi}[3][pos=0.5]{
\path (#2) -- (#3)coordinate[#1](mm);
\draw[-latex,green] (#2) --($(#2.south)+(0,-0.5)$)-| (mm) |- ($(#3.north)+(0,0.5)$)--(#3);
}


You'll be able to use almost all returns as in the example below

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{positioning}
\usepackage[margin=0.5in]{geometry}
\pagestyle{empty}

\newcommand{\renvoi}[3][pos=0.5]{
\path (#2) -- (#3)coordinate[#1](mm);
\draw[-latex,red] (#2) --($(#2.south)+(0,-0.5)$)-| (mm) |- ($(#3.north)+(0,0.5)$)--(#3);
}

\begin{document}

%\input{../tikz-setup.tex}
\usetikzlibrary{shapes, arrows, calc, positioning}

% Define block styles
\tikzstyle{state}   = [ rounded rectangle,
draw,
text centered,
minimum height=3em ,
minimum width = 6em,
inner sep = 5pt
]
\tikzstyle{test}    = [ diamond,
draw,
shape aspect=2,
inner sep = 0pt,
text width = 7em,
text centered
]
\tikzstyle{action}  = [ rectangle, draw,
text width=8em,
inner sep = 5pt,
minimum height=5em
]
\tikzstyle{data}    = [ trapezium,
draw,
trapezium left angle=60,
trapezium right angle=120pt,
minimum height = 6em,
text width = 5em
]
\tikzstyle{line}    = [ draw, -triangle 45 ]

\begin{center}
\begin{tikzpicture}[align = flush center, font = \small]
% Place nodes
\matrix [column sep = 2.5em, row sep = 2em] (mtrx)
{

\node [state] (a) {a}; &[1em]
\node (b) {}; \\

\node [action] (c) {c}; &
\node [action] (d) {d}; \\

\node [test] (e) {e}; &
\node [test] (f) {f}; \\

\node [action] (g) {g}; &
\node [action] (h) {h}; \\

\node [action] (i) {i};&
\node [action] (j) {j}; \\

&
\node [state] (k) {k}; \\
};

% Draw edges

\renvoi{i}{j}
\renvoi{e}{g}
\renvoi[left=3em of g]{e}{i}
\renvoi[pos=0.7]{f}{c}
\renvoi[right=3em of f]{f}{d}

\end{tikzpicture}
\end{center}
\end{document}


• in the middle of the two nodes \renvoi{i}{j} default
• \renvoi$pos=0.7${f}{c} the crossing point is 0.7 on the segment (f) (c)
• \renvoi[right=3em of f]{f}{d} the crossing point is to the right of 3em (positioning the library is required to use this option)