4

I want to connect a set of predefined nodes using a simple sintaxe like "\draw (SD00) -- (ED03);" using only the start and end nodes, instead of specifying a whole path through intermediate nodes. The only restriction is that the edges cannot cross over the coloured boxes region. Is there an algorithm embedded in Tikz that can calculate such a route automatically?

 \begin{tikzpicture}
\begin{scope}[xshift=0cm, yshift=-2cm]
  \node[draw, circle] at (0,0)(SD00) {0};
  \node[draw, circle] at (0,1)(SD01) {1};
  \node[draw, circle] at (0,2)(SD02) {2};  
  \node[draw, circle] at (0,3)(SD03) {3};
\end{scope}

\begin{scope}[xshift=7cm, yshift=2cm]
  \node[draw, circle] at (0,0)(ED00) {0};
  \node[draw, circle] at (0,-1)(ED01) {1};
  \node[draw, circle] at (0,-2)(ED02) {2};  
  \node[draw, circle] at (0,-3)(ED03) {3};
  \node[draw, circle] at (0,-4)(ED04) {4};
  \node[draw, circle] at (0,-5)(ED05) {5};  
  \node[draw, circle] at (0,-6)(ED06) {6};
\end{scope}

% forbidden areas
\draw[fill=red!20] (1.5,-3) rectangle ++(4,5) node[below left]{red};
\draw[fill=teal!20] (1.5,3.5) rectangle ++(4,3);
\draw[fill=teal!20] (-2,-5) rectangle ++(7.5,1);

% Connections
\draw[dashed] (SD00) -- (ED03); % simple direct path
\draw[red] (SD00)  -- ++(1,0) to[out=90, in=180] ++(1,5)  -- ++(3,0) to[out=0, in=180] (ED03); % piecewise path

\end{tikzpicture}

enter image description here

  • 6
    To the best of my knowledge the answer to " Is there an algorithm embedded in Tikz that can calculate such a route automatically?" is no. (This is not to say that there is no information on "edge routing" but AFAIK this will not allow you to construct a fully automatic solution here.) –  May 28 '20 at 21:05
  • wish i could insert google search into circuit --then putting - sign would avoid those colored areas – js bibra May 29 '20 at 00:29
  • If the best routes that avoid the forbidden region are preconfigured, what is the best way to select one using a short sintaxe e.g. \link SD00--ED03? – Anisio Braga May 29 '20 at 12:35
  • @AnisioBraga Check the to path key. If you do link/.style={to path={<preconfig path>}} you can use \tikztostart (= SD00) and \tikztotarget (= ED03) inside <preconfig path> and any path construction you need. That way you can do \draw (SD00) to[link] (ED03);. – Qrrbrbirlbel Jul 17 '22 at 15:25
  • @Qrrbrbirlbel you suggestion sounds interesting but I could not write a correct sintaxe. Could you give an example ie how to configure two paths using the example given ? – Anisio Braga Jul 29 '22 at 17:21

1 Answers1

5

If you know the pre-configured path of your connection, you can package this in a style that uses to path where you can access the start and the target node via the macros \tikztostart and \tikztotarget.

In this case, I have defined a key way around LR that takes an argument in the form of <name 1>:<name 2>. (This needs the rectangle to be actually nodes since it is much easier than to reference them here.)

Furthermore, there are three values defined in the PGFkey namespace /tikz/wayround which you can set via the /tikz/way around key. These values can be accessed inside the to path as well.

The path itself is in this case just a sequence of orthogonal lines using the --, |- and -| path operators as well as the calc libary's coordinate specification where ($(<c1>)!<ratio>!(<c2>)$) specifies the point that that lies <ratio>-way between the points <c1> and <c2>.

In this case, classified by the LR suffix, this is only a connection that works in the eastward directions. You can define similar styles for lines going from right to left and so on. (We could also package this in one style that does some calculations beforehand but that becomes just a math problem and not a TikZ problem.)

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{calc,fit}
\newcommand*\wayaroundset{\pgfqkeys{/tikz/wayaround}}
\newcommand*\wayaroundvalueof[1]{\pgfkeysvalueof{/tikz/wayaround/#1}}
\wayaroundset{
   start distance/.initial=1cm,
   target distance/.initial=1cm,
   distance/.style={start distance={#1}, target distance={#1}},
   ratio/.initial=.5}
\tikzset{
   rectangle points/.style={
     fit={#1}, inner sep=+0pt, outer sep=+0pt, shape=rectangle, node contents=},
   way around/.code=\wayaroundset{#1},
   way around LR/.style args={#1:#2}{
       to path={
           (\tikztostart) -- ++(0:\wayaroundvalueof{start distance})
                          |- ($(#1.south)!\wayaroundvalueof{ratio}!(#2.north)$)
                          -| ($(\tikztotarget)+(180:\wayaroundvalueof{target distance})$)
                          -- (\tikztotarget)}}}
\begin{document}
\begin{tikzpicture}
\path[xshift=0cm, yshift=-2cm] foreach \i in {0,...,3} { node[draw, circle] at (0, \i) (SD0\i) {\i} };
\path[xshift=7cm, yshift= 2cm] foreach \i in {0,...,6} { node[draw, circle] at (0,-\i) (ED0\i) {\i} };

% forbidden areas \node (forbid-a) [draw, fill=red!20, rectangle points={( 1.5,-3) (5.5, 2)}]; \node (forbid-b) [draw, fill=teal!20, rectangle points={( 1.5, 3.5)(5.5, 6.5)}]; \node (forbid-c) [draw, fill=teal!20, rectangle points={(-2, -5) (5.5,-4)}];

% Connections \tikzset{every path/.append style=ultra thick} \draw[blue] (SD00) to [way around LR=forbid-b:forbid-a] (ED03); \draw[green] (SD01) to [way around={distance=.75cm, ratio=.25}, way around LR=forbid-b:forbid-a] (ED04); \draw[red] (SD03) to [way around={start distance=.5cm}, way around LR=forbid-a:forbid-c] (ED06); \drawyellow to [way around={start distance=1.25cm, ratio=.25}, way around LR=forbid-a:forbid-c] (ED05); \end{tikzpicture} \end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821