24

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?

enter image description here

The minimal template is:

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

I really appreciate your patience!

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

3 Answers 3

25

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}

enter image description here

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}

enter image description here

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

6
  • You are superfast! :-)
    – Sebastiano
    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
  • 1
    @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
12

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

enter image description here

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}
5
  • 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.
    – Thruston
    Dec 19, 2018 at 9:46
  • 2
    It's also possible that the OP intended it to be regularly over and under, but made a mistake... :-)
    – Thruston
    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
3

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}

enter image description here

1

You must log in to answer this question.

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