4

I would like to modify this MWE so that the edge connecting the two nodes is a straight line with a break that allows the edge connect to (b.north west) with a 135° angle. The other end of the edge connect to (a.south west) exiting to the right. The result should be like the lines connecting the nodes of this question, but I don't want to use the same package.

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}

\begin{document}
\begin{tikzpicture}
\node (a) {a};
\node (b) [right of=a, below of=a, xshift=2cm] {b};
\draw (a.south west)  to [in=135, out=0] (b.north west);
\end{tikzpicture}
\end{document}

How do I do it?

3
  • Why don't you want to use forest? It is very, very good. You can do it, probably, using one of the other tree packages or even just manually. But why make it difficult when somebody else already invented wheels and is providing them to all who want them for free?
    – cfr
    Jan 7, 2016 at 23:26
  • Is forest only used for creating tree graph? In that case, I can't use it since I need to picture a more complicated graph.
    – Nicola
    Jan 8, 2016 at 8:06
  • Well, it depends. Yes, it draws trees. However, you can also draw stuff in addition to the tree, including stuff you specify within the tree or after the tree using regular TikZ. And sometimes you can fake non-tree graphs, too, when that's more convenient. Which isn't to say that it is suitable for your case as I don't know what your requirements are.
    – cfr
    Jan 8, 2016 at 21:43

3 Answers 3

2

forest is much easier, but you can do everything manually if you prefer:

\documentclass[border=5pt, multi, tikz]{standalone}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
  \node (a) {a};
  \node (b) [right of=a, below of=a, xshift=2cm] {b};
  \draw (a.south west) -- (a.south west -| {$(b.north west) + (135:10mm)$}) --   (b.north west);
\end{tikzpicture}
\end{document}

non-forest connections

5
  • That's a better solution. However, consider that in b the node shape is a diamond, as in \node (b) [draw, diamond, right of=a, below of=a, xshift=0.5cm] {b}; (add also \usetikzlibrary{calc,shapes.geometric} )The slope of the edge seems a bit off, it doesn't seem to touch the side of the diamond perpendicularly, isn't it? Also, it changes if I put 5mm in place of 10mm. How can I fix it?
    – Nicola
    Jan 8, 2016 at 8:31
  • I can fix with \draw (a.south west) -- (a.south west -| {$(b) + (135:10mm)$}) --(b.north west); i.e. using b and not b. north west to evaluate the coordinates in $...$
    – Nicola
    Jan 8, 2016 at 8:43
  • That will take the angle from the default anchor for the node b. It just depends where you want the 135 measured from. You said the north west, so that's what I used. If you want something different, obviously you can change it accordingly.
    – cfr
    Jan 8, 2016 at 21:39
  • Now that I understand better how calc works, I see that to get a line perpendicular to the north west side of the diamond, the correct line is \draw (a.south west) -- (a.south west -| {$(b) + (180:10mm)$}) --(b.north west);
    – Nicola
    Jan 8, 2016 at 22:30
  • There are simpler ways, but yes, that would work. But that is not what you asked how to do in this question, is it?
    – cfr
    Jan 8, 2016 at 22:40
2

One can also borrow the code of -| operator. I should call it -\ but then I need to hack the parser of TikZ. (\tikz@lineto, line 2699 of tikz.code.tex)

Notice that there are three changes in the definition of \tikz@@hv@lineto. The third corresponds to -| between explicit coordinates. The first two correspond to the node case.

Notice also that I did nothing about \tikz@timer. Thus pos=.5, midway, or their family is not going to work properly.

\documentclass[tikz,border=9]{standalone}

\makeatletter

\def\tikz@@hv@lineto#1{%
  \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
  \pgf@xc=\tikz@lastx% NEW LINE
  \pgf@yc=\tikz@lasty%
  \tikz@make@last@position{#1}%
  \edef\tikz@tangent{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\pgf@yc}}%
  \tikz@flush@moveto@toward{\pgfqpoint{\tikz@lastx}{\pgf@yc}}\pgf@x\pgf@yc%
  \iftikz@shapeborder%
    % ok, target is a shape. have to work now:
    {%
      %\pgf@process{\pgfpointshapeborder{\tikz@shapeborder@name}{\pgfqpoint{\tikz@lastx}{\pgf@yc}}}% Replace by the following
      \pgf@process{\pgfpointshapeborder{\tikz@shapeborder@name}{\pgfpoint{\tikz@lastx-sign(\tikz@lastx-\pgf@xc)*abs(\pgf@yc-\tikz@lasty)}{\pgf@yc}}} % NEW LINE
      \tikz@make@last@position{\pgfqpoint{\pgf@x}{\pgf@y}}%
      %\tikz@path@lineto{\pgfqpoint{\tikz@lastx}{\pgf@yc}}% Replace by the following
      \tikz@path@lineto{\pgfpoint{\tikz@lastx-sign(\tikz@lastx-\pgf@xc)*abs(\pgf@yc-\tikz@lasty)}{\pgf@yc}} % NEW LINE
      \tikz@path@lineto{\tikz@last@position}%
      \xdef\tikz@timer@end@temp{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}% move out of group
    }%
    \let\tikz@timer@end=\tikz@timer@end@temp%
    \edef\tikz@moveto@waiting{\tikz@shapeborder@name}%    
  \else%
    %\tikz@path@lineto{\pgfqpoint{\tikz@lastx}{\pgf@yc}}% Replace by the following
    \tikz@path@lineto{\pgfpoint{\tikz@lastx-sign(\tikz@lastx-\pgf@xc)*abs(\pgf@yc-\tikz@lasty)}{\pgf@yc}} % NEW LINE
    \tikz@path@lineto{\tikz@last@position}%
    \edef\tikz@timer@end{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}% move out of group
  \fi%
  \let\tikz@timer=\tikz@timer@hvline%
  \tikz@scan@next@command%
}

\begin{document}
    \begin{tikzpicture}
        \node(a){a};
        \node(b)[below right of=a, xshift=2cm]{b};
        \node(c)[below left of=a, xshift=-2cm]{c};
        \node(d)[above right of=a, xshift=2cm]{d};
        \node(e)[above left of=a, xshift=-2cm]{e};
        \draw(a.south east)-|(b.north west);
        \draw(a.south west)-|(c.north east);
        \draw(a.north east)-|(d.south west);
        \draw(a.north west)-|(e.south east);
    \end{tikzpicture}
    \begin{tikzpicture}
        \node(a){a};
        \node(b)[below right of=a, xshift=2cm]{b};
        \node(c)[below left of=a, xshift=-2cm]{c};
        \node(d)[above right of=a, xshift=2cm]{d};
        \node(e)[above left of=a, xshift=-2cm]{e};
        \draw(a)-|(b);
        \draw(a)-|(c);
        \draw(a)-|(d);
        \draw(a)-|(e);
    \end{tikzpicture}
\end{document}
3
  • Won't this work only if you want connections of this type for all -| connections? That is, you can't also use regular -| paths?
    – cfr
    Jan 8, 2016 at 21:40
  • 1
    @cfr I am saying that -| is a good start. One can then rename it as -/ or /-, and modify TikZ's "if-switcher". Now we can write \draw(A)--(B)-|(C)-/(D);
    – Symbol 1
    Jan 9, 2016 at 0:48
  • Oh, I see. OK. That makes sense. Certainly if you want a lot of these.
    – cfr
    Jan 9, 2016 at 0:55
1

You can cook up your own to path. Here mypath takes an argument as to how much of the path should be drawn as a straight before breaking. If set too high obviously it will over draw but in general should be OK.

\documentclass[tikz]{standalone}
\usetikzlibrary{calc,shapes.geometric,positioning}
\begin{document}
\begin{tikzpicture}[
  mypath/.style={
    to path={let \p1=($(\tikztostart)-(\tikztotarget)$),
                 \n1={atan2(\y1,\x1)},\n2 = {(\x1<0?1:2)}
                 in 
                 -- ($(\tikztostart)!#1!180*\n2-\n1:(\tikztotarget)$)
                 -- (\tikztotarget)\tikztonodes
          }
      }]

\node (a) {a};
\foreach \x[count=\xi] in {20,130,245,330}{
  \node[diamond,draw] (b-\xi) at (\x:3cm) {b};
  \draw (a.south west) to[mypath={min(0.5,rnd)}] (b-\xi);
}
\end{tikzpicture}
\end{document}

enter image description here

Also please have a look at Difference between "right of=" and "right=of" in PGF/TikZ to avoid the deprecated syntax.

You must log in to answer this question.

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