# tikz -- Snake like curves between straight lines

How do we draw a figure like this in tikz?

I am able to draw the straight lines, but these curves are too challenging -- how to draw them nice?

The minimal template is:

\begin{tikzpicture}
\draw[->] (0,0,0)--(0,8,0);
\draw[->] (4,0,0)--(4,8,0);
\end{tikzpicture}


• Very nice and good question for my opinion. Dec 17, 2018 at 21:33

That's a standard task for the knot library.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{knots,arrows.meta}
\begin{document}
\begin{tikzpicture}
\path (-0.5,6.5) coordinate (x1) (4.5,5) coordinate (x2)
(-0.5,3.5) coordinate (x3) (4.5,2.5) coordinate (x4);
\begin{knot}%[draft mode=crossings]
\strand[{Circle}-{Circle}] (0,0) -- (0,8);
\strand[{Circle}-{Circle}] (4,0) -- (4,8);
\strand[{Circle}-{Circle},looseness=0.5] (2,8) to[out=-90,in=90] (x1)
to[out=-90,in=90] (x2) to[out=-90,in=90] (x3)
to[out=-90,in=90] (x4) to[out=-90,in=90] (2,0);
\flipcrossings{2,4,6,8}
\end{knot}
\end{tikzpicture}
\end{document}


Or with the ordering as in your picture.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{knots,arrows.meta}
\begin{document}
\begin{tikzpicture}
\path (-0.5,6.5) coordinate (x1) (4.5,5) coordinate (x2)
(-0.5,3.5) coordinate (x3) (4.5,2.5) coordinate (x4);
\begin{knot}%[draft mode=crossings]
\strand[{Circle}-{Circle}] (0,0) -- (0,8);
\strand[{Circle}-{Circle}] (4,0) -- (4,8);
\strand[{Circle}-{Circle},looseness=0.5] (2,8) to[out=-90,in=90] (x1)
to[out=-90,in=90] (x2) to[out=-90,in=90] (x3)
to[out=-90,in=90] (x4) to[out=-90,in=90] (2,0);
\flipcrossings{2,3,5,8}
\end{knot}
\end{tikzpicture}
\end{document}


To find out which crossing has which number, uncomment [draft mode=crossings].

• You are superfast! :-) Dec 17, 2018 at 21:51
• Oh my god! I dont know this thing exist in tikz!!!! Thank you - (I was not aware and just posted another more technical question!) Dec 17, 2018 at 21:57
• Very interesting! Is the knot library documented anywhere? Dec 18, 2018 at 7:14
• @HafidBoukhoulda Yes, here.
– user121799
Dec 18, 2018 at 11:44
• @HafidBoukhoulda It is the library. There might be a package of the same name, which is not to be confused with the library. Another very useful (or even more useful) library by the same author which is not mentioned in the pgfmanual is tikzmark.
– user121799
Dec 18, 2018 at 18:39

Here's a version in plain Metapost featuring a useful idiom to find all the intersection points between two paths.

This is wrapped up in luamplib so compile it with lualatex (or work out how to adapt it for plain mpost).

\documentclass[border=5mm]{standalone}
\usepackage{luatex85}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
beginfig(1);
path s, t, a, b;
a = (down--up) scaled 164 shifted 72 left;
b = (down--up) scaled 164 shifted 72 right;
t = ((-36*4, 0) for x=-35 upto 36: .. (4x, 88 sind(10x)) endfor) rotated 90 reflectedabout(up, down);
s = point 0 of t shifted 20 down {up} .. {direction 2 of t} subpath (2,70) of t {direction 70 of t} .. point 72 of t shifted 20 up {up};

pickup pencircle scaled 1;

forsuffixes $=a, b, s: draw$;
fill fullcircle scaled 4 shifted point 0 of $; fill fullcircle scaled 4 shifted point infinity of$;
endfor

vardef over_and_under(expr a, b) =
save x, y, r, n, A, B, p;
path r; numeric n; picture A, B, p;
r := a;
n = 0;
forever:
r := r cutbefore b;
exitif length cuttings = 0;
r := subpath (epsilon, infinity) of r;
z[incr n] = point 0 of r;
endfor
A = image(draw a);
B = image(draw b);
for i=0 upto n:
if known z[i]:
unfill fullcircle scaled 10 shifted z[i];
p :=  if odd i: B else: A fi;
clip p to fullcircle scaled 10 shifted z[i];
draw p;
fi
endfor
enddef;

over_and_under(a, s);
over_and_under(b, s);

endfig;
\end{mplibcode}
\end{document}

• It is not the same ordering as in the OP's screenshot, though. You have (b=back, f=front) bfbfbfbf and the OP bffbfbbf reading from top to bottom along the curved path.
– user121799
Dec 19, 2018 at 0:26
• @marmot - that's true. I guess if I was doing lots of these it would be worth working out a way to specify the order. But I'm only trying to show what's possible with MP, not create a whole new notation. One of the great strengths of plain MP is that it is simple to create your own task-specific notations. Dec 19, 2018 at 9:46
• It's also possible that the OP intended it to be regularly over and under, but made a mistake... :-) Dec 19, 2018 at 9:48
• Sorry, don't get me wrong. But I could draw a blue dragon, arguing that the OP may secretly have wanted one. I guess a fair question would be: how much extra effort is it to achieve a custom ordering.
– user121799
Dec 22, 2018 at 9:30
• Thanks! +1 see unsolved tex.stackexchange.com/questions/466279/… Dec 27, 2018 at 4:50

Here is an attempt using the snake decoration from tikz library decorations.pathmorphing. The intersections library is used to calculate the crossovers locations. White circles are then drawn at intersection points.

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{intersections,decorations.pathmorphing}
\begin{document}

\begin{tikzpicture}[thick,rotate=90,xscale=.7,dot/.style={inner sep=1.5pt,fill,circle},cut/.style={inner sep=3pt,fill=white,circle}]

\draw[name path=curve,decorate, decoration={snake, segment length=2.96cm, amplitude=-2cm}] (0,0)node[dot]{} -- (9,0)node[dot]{};
\path[name path=la](-1, 1.5) -- (10, 1.5);
\path[name path=lb](-1,-1.5) -- (10,-1.5);

\path [name intersections={of=la and curve}];
\node[cut] at(intersection-1){} (intersection-4) node[cut]{} (intersection-2) node(2)[cut,fill=none]{} (intersection-3) node(3)[cut,fill=none]{};
\draw (-1,1.5) node[dot]{} -- (2) (2) -- (3) (3) -- (10,1.5) node[dot]{};

\path [name intersections={of=lb and curve}];
\node[cut] at(intersection-2){} (intersection-3) node[cut]{} (intersection-1) node(1)[cut,fill=none]{} (intersection-4) node(4)[cut,fill=none]{};
\draw (-1,-1.5) node[dot]{} -- (1) (1) -- (4) (4) -- (10,-1.5) node[dot]{};

\end{tikzpicture}

\end{document}