17

I want to connect nodes in the following way:

picture of LaTeX code

\documentclass{standalone}

\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\node (foo) at (0,0) {(0,0)};
\node (bar) at (5,3) {(5,3)};

\node (baz) at (0,-1) {(0,-1)};
\node (boo) at (5,1) {(5,1)};

% What I want to happen
\draw (foo) -- ++(3,3) -- (bar);
\draw (baz) -- ++(2,2) -- (boo);

% The kind of syntax I would like, but if there is a more
% 'correct' syntax I'm happy to use it
%\draw[**magic**] (foo) -- (bar);
%\draw[**magic**] (baz) -- (boo);

\end{tikzpicture}
\end{document}

I know there must be a solution with styles but my TikZ skills are currently insufficient to know how or where to look.

How can I connect nodes in the style above?

1
  • 2
    Kind of like a /- operator to parallel |-. – David Z Jan 24 '18 at 3:46
15

I adapted the code of Paul Gaborits answer to make it more general.

I used abs and sign to allow other use cases.

More generalized version:

With the option to[diagonal line] for a connection, first a diagonal (45°) and then a horizontal or vertical line is drawn. If the angle between start and end point is a multiple of 45°, only a single direct line is drawn.

Code:

\documentclass[tikz]{standalone}
\usetikzlibrary{calc}

\tikzset{
    diagonal line/.style={
        to path={
            let \p{start}=(\tikztostart),
                \p{target}=(\tikztotarget),
                \p{diff}=({\x{target}-\x{start}}, {\y{target}-\y{start}}),
                \p{absdiff}=({abs(\x{diff})}, {abs(\y{diff})}),
                \n{mindiff}={min(\x{absdiff}, \y{absdiff})},
                \p{inter}=(
                    {sign(\x{diff}) * \n{mindiff}},
                    {sign(\y{diff}) * \n{mindiff}}
                )
            in 
                \ifnum \ifdim\x{target}=\x{start} 1
                \else \ifdim\y{target}=\y{start} 1
                \else \ifdim\x{absdiff}=\y{absdiff} 1
                \else 0\fi\fi\fi=1 %primitive tex or condition
                    -- (\tikztotarget)
                \else
                    --++ (\p{inter}) -- (\tikztotarget)
                \fi
        },
    },
}

\begin{document}
    \begin{tikzpicture} 
        \foreach \d in {1,...,16} {
            \node (a\d) at ($(0,0)+(90-\d*22.5:12mm)$) {\footnotesize $a_{\d}$};
            \node (b\d) at ($(0,0)+(90-\d*22.5:35mm)$) {\footnotesize $b_{\d}$};
            \draw (a\d) to[diagonal line] (b\d);
        }
    \end{tikzpicture}
\end{document}

Result:

enter image description here

Older non-general version

Code:

\documentclass[tikz]{standalone}
\usetikzlibrary{calc}
\tikzset{
    special line/.style={
        to path={
            let \p{start}=(\tikztostart), \p{target}=(\tikztotarget),
            \p{inter}=({\x{start} + sign(\x{target}-\x{start}) * abs(\y{target}-\y{start})}, \y{target})
            in -- (\p{inter}) -- (\tikztotarget)
        },
    },
}

\begin{document}
    \begin{tikzpicture}
        \node (x) at (0,0) {(0,0)};
        \node (y1) at (5,2) {(5,2)};
        \node (y2) at (5,-2) {(5,-2)};
        \node (y3) at (-5,-2) {(-5,-2)};
        \node (y4) at (-5,2) {(-5,2)};
        
        \draw (x) to[special line] (y1);
        \draw (x) to[special line] (y2);
        \draw (x) to[special line] (y3);
        \draw (x) to[special line] (y4);
    \end{tikzpicture}
\end{document}

Result:

enter image description here

The result with Pauls or Ignasis code would be:

enter image description here

2
  • Fine solution! First you draw the diagonal part and then the non-diagonal part of the line. By swapping starting and ending points we get the reverse behavior. Is it possible to create a line type named /- or -/ as replacement of to[diagonal line] and also distinguish the two situations than I mention? Thanks again for this very useful solution. – vsantos Sep 21 '20 at 11:32
  • @vsantos That would be nice but seems to be difficult. You could remember this connection with first "diagonal" and then "line". One could make a second reversed style line diagonal. You could also rename the style, but the use of / or `\` within the style name seems to be difficult as that characters have a special meaning in the definition syntax. – dexteritas Sep 22 '20 at 10:37
11

Here is a solution using the calc TikZ library, a let operation and a to path style:

\documentclass[tikz]{standalone}
\usetikzlibrary{calc}
\tikzset{
  special line/.style={
    to path={
      let \p{start}=(\tikztostart), \p{target}=(\tikztotarget),
      \p{inter}=(\x{start}+\y{target}-\y{start},\y{target})
      in -- (\p{inter}) -- (\tikztotarget)
    },
  },
}

\begin{document}
\begin{tikzpicture}

  \node (foo) at (0,0) {(0,0)};
  \node (bar) at (5,3) {(5,3)};

  \node (baz) at (0,-1) {(0,-1)};
  \node (boo) at (5,1) {(5,1)};

  \draw (foo) to[special line] (bar);
  \draw (baz) to[special line] (boo);
\end{tikzpicture}
\end{document}

enter image description here

7

Not a style like in Paul's solution but a command:

\documentclass[tikz,border=2mm]{standalone} 
\usetikzlibrary{positioning,calc}

\newcommand{\connect}[3][]{%
\draw[#1] (#2) let \p1 = ($(#3)-(#2)$) in --++(\y1,\y1)--(#3); 
}

\begin{document}
\begin{tikzpicture}

\node (a) at (0,0) {A};
\node (b) at (5,3) {B};

\connect{a}{b}

\node (c) at (0,-1) {C};
\node (d) at (5,1) {D};

\connect{c}{d}
\connect[red]{a}{d}
\connect[dashed, blue]{c}{b}
\end{tikzpicture}
\end{document}

enter image description here

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.