4

I am using tikz to draw a graph. Basically I have a source (node (s)) and a sink (node (t)) that I want to connect with multiple parallel paths, which have multiple links in series.

I find that this solution places my nodes nicely, connects them correctly, but not smoothly,

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{arrows,decorations.pathmorphing,backgrounds,positioning,fit,petri,shapes.geometric,patterns,calc}

\begin{document}

\begin{tikzpicture}[vertex/.style={circle, draw}]

\node[vertex, minimum size=1cm] (s) at (0,0) {};
\node[vertex, minimum size=1cm] (t) at (12,0) {};

\foreach \r in {0,...,3} {
    \foreach \x in {1,...,4} {
        \path (s) to[out=20*\r, in=180-20*\r] node[vertex, pos=\x/5] (\r\x) {} (t); }}
% the nodes I am trying to link

\foreach \r in {0,...,3} {
    \draw[->] (s) -- (\r1);
    \draw[->] (\r4) -- (t);
    \foreach \x [count=\xi] in {2,...,4} {
        \draw[->] (\r\xi) -- (\r\x); }}
%the linkage is good, but does not curve nicely

\end{document}
\end{tikzpicture}

I would like the links to curve in the same manner that the path from (s) to (t) which traverse the nodes, with an arrow pointing at each node. I plotted in red the bending I would like to achieve with the linkage.Desired curves vs achieved curves so far

Cryme
  • 761

2 Answers2

8

Instead of placing nodes along the path, I used the decorations.markings library to place on this path (length 1) at positions 0.2; 0.4; 0.6 and 0.8 two arrows > and Circle.

mark=between positions 0.2 and 1 step 0.2
with { 
        \draw[arrows = -{>Circle[open,length=8pt,width=8pt,fill=white]}] (0pt,0pt) -- (.1pt,0pt);
        }

The last arrows are placed by tracing the main paths that are traced with a single foreach loop.

\foreach \r [remember =\r as \lastr initially 0]in {0,...,3} {
        \path[draw,postaction={decorate},->] (s) to[out=20*\r, in=180-20*\r,->] 
        (t); 
        } 

Thus it is no longer necessary to have a double foreach loop.

screenshot

\documentclass[border=5mm,tikz]{standalone}

%\usepackage{tikz}
\usetikzlibrary{arrows,decorations.pathmorphing,backgrounds,positioning,fit,petri,shapes.geometric,patterns,calc}
\usetikzlibrary{decorations.markings,arrows.meta}

\begin{document}

\begin{tikzpicture}[vertex/.style={circle, draw},decoration={markings,
mark=between positions 0.2 and 1 step 0.2
with { 
        \draw[arrows = -{>Circle[open,length=8pt,width=8pt,fill=white]}] (0pt,0pt) -- (.1pt,0pt);
        }
       } 
]

\node[vertex, minimum size=1cm] (s) at (0,0) {};
\node[vertex, minimum size=1cm] (t) at (12,0) {};

\foreach \r [remember =\r as \lastr initially 0]in {0,...,3} {
        \path[draw,postaction={decorate},->] (s) to[out=20*\r, in=180-20*\r,->] 
        (t); 
        }       

\end{tikzpicture}
\end{document}
AndréC
  • 24,137
3

This is based on this code. It allows one to draw the connections without shifting the nodes while bending the arrows.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,bending,decorations.markings} 
\tikzset{% inspired by https://tex.stackexchange.com/a/316050/121799
    arc arrow/.style args={%
    to pos #1 with length #2 and offset #3}{
    decoration={
        markings,
         mark=at position 0 with {\pgfextra{%
         \pgfmathsetmacro{\tmpArrowTime}{#2/(\pgfdecoratedpathlength)}
         \pgfmathsetmacro{\tmpArrowOffset}{#3/(\pgfdecoratedpathlength)}
         \xdef\tmpArrowTime{\tmpArrowTime}
         \xdef\tmpArrowOffset{\tmpArrowOffset}}},
        mark=at position {#1-\tmpArrowTime-\tmpArrowOffset} with {\coordinate(@1);},
        mark=at position {#1-2*\tmpArrowTime/3-\tmpArrowOffset} with {\coordinate(@2);},
        mark=at position {#1-\tmpArrowTime/3-\tmpArrowOffset} with {\coordinate(@3);},
        mark=at position {#1-\tmpArrowOffset} with {\coordinate(@4);
        \draw[-{Stealth[length=#2,bend]}]       
        (@1) .. controls (@2) and (@3) .. (@4);},
        },
     postaction=decorate,
     }
}


\begin{document}
\begin{tikzpicture}[vertex/.style={circle, draw},
insert vertices/.style={postaction={decorate,decoration={markings,
mark={between positions 0.2 and 0.8 step 0.2
with { 
        \node[vertex,fill=white](#1\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}){};
        }
       }}}},my arrow/.style={arc arrow=to pos #1 with length 2mm and offset 4pt} 
]

\node[vertex, minimum size=1cm] (s) at (0,0) {};
\node[vertex, minimum size=1cm] (t) at (12,0) {};

\foreach \r [remember =\r as \lastr initially 0]in {0,...,3} {
 \path[draw,insert vertices=\r,-{Stealth[bend,length=2mm]},
 my arrow/.list={1/5,2/5,3/5,4/5}] (s) to[out=20*\r, in=180-20*\r,->] 
        (t); 
}       
\end{tikzpicture}
\end{document}

enter image description here

On the other the solution by AndréC (which is in red), moves the circles away from the postions 0.2,0.4,....

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,bending,decorations.markings} 
\tikzset{% inspired by https://tex.stackexchange.com/a/316050/121799
    arc arrow/.style args={%
    to pos #1 with length #2 and offset #3}{
    decoration={
        markings,
         mark=at position 0 with {\pgfextra{%
         \pgfmathsetmacro{\tmpArrowTime}{#2/(\pgfdecoratedpathlength)}
         \pgfmathsetmacro{\tmpArrowOffset}{#3/(\pgfdecoratedpathlength)}
         \xdef\tmpArrowTime{\tmpArrowTime}
         \xdef\tmpArrowOffset{\tmpArrowOffset}}},
        mark=at position {#1-\tmpArrowTime-\tmpArrowOffset} with {\coordinate(@1);},
        mark=at position {#1-2*\tmpArrowTime/3-\tmpArrowOffset} with {\coordinate(@2);},
        mark=at position {#1-\tmpArrowTime/3-\tmpArrowOffset} with {\coordinate(@3);},
        mark=at position {#1-\tmpArrowOffset} with {\coordinate(@4);
        \draw[-{Stealth[length=#2,bend]}]       
        (@1) .. controls (@2) and (@3) .. (@4);},
        },
     postaction=decorate,
     }
}


\begin{document}
\begin{tikzpicture}[vertex/.style={circle, draw},
insert vertices/.style={postaction={decorate,decoration={markings,
mark={between positions 0.2 and 0.8 step 0.2
with { 
        \node[vertex,fill=white](#1\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}){};
        }
       }}}},my arrow/.style={arc arrow=to pos #1 with length 2mm and offset 4pt} 
]

\node[vertex, minimum size=1cm] (s) at (0,0) {};
\node[vertex, minimum size=1cm] (t) at (12,0) {};

\foreach \r [remember =\r as \lastr initially 0]in {0,...,3} {
 \path[draw,insert vertices=\r,-{Stealth[bend,length=2mm]},
 my arrow/.list={1/5,2/5,3/5,4/5}] (s) to[out=20*\r, in=180-20*\r,->] 
        (t); 
}       
\begin{scope}[red,opacity=0.8,vertex/.style={circle, draw},decoration={markings,
mark=between positions 0.2 and 1 step 0.2
with { 
        \draw[arrows = -{>Circle[open,length=8pt,width=8pt,fill=white]}] (0pt,0pt) -- (.1pt,0pt);
        }
       } 
]

\node[vertex, minimum size=1cm] (s) at (0,0) {};
\node[vertex, minimum size=1cm] (t) at (12,0) {};

\foreach \r [remember =\r as \lastr initially 0]in {0,...,3} {
        \path[draw,postaction={decorate},->] (s) to[out=20*\r, in=180-20*\r,->] 
        (t); 
        }       
\end{scope}
\end{tikzpicture}
\end{document}

enter image description here

OLDER ANSWER: The syntax you may be looking may be

to[bend left=<angle>]

\documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[vertex/.style={circle, draw}]

\node[vertex, minimum size=1cm] (s) at (0,0) {};
\node[vertex, minimum size=1cm] (t) at (12,0) {};

\foreach \r in {0,...,3} {
    \foreach \x in {1,...,4} {
        \path (s) to[out=20*\r, in=180-20*\r] node[vertex, pos=\x/5] (\r\x) {} (t); }}
% the nodes I am trying to link

\foreach \r in {0,...,3} {
    \draw[-stealth] (s) to[bend left={\r*30/pow(\r+1,2)}]  (\r1);
    \draw[-stealth] (\r4) to[bend left={\r*30/pow(\r+1,2)}]  (t);
    \foreach \x [count=\xi] in {2,...,4} {
        \draw[-stealth] (\r\xi) to[bend left={\r*20/pow(\r+1,3/2)}] (\r\x); }}
%the linkage is good, but does not curve nicely
\end{tikzpicture}

\end{document}

enter image description here

  • 1
    Thank you, surprisingly this method almost works! I wouldn't have betted on fixing the bending angle. However, it's slightly off, so I'd go with the solution of AndréC. – Cryme Jul 10 '19 at 21:55
  • @OlivierMassicot OK, I added a version with decorations.markings in which the circles are nodes whose style is controlled by your vertex style, and not displaced. (In AndréC's code the centers of the circles are not at positions 1/5,2/5,..., but the right end of those is there.) Also this code places named nodes, which you can use later (which is what you thought to want). –  Jul 10 '19 at 22:02