9

I'm trying to draw some knots with TikZ. I've got this far:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{knots}
\begin{document}
$\begin{tikzpicture}[domain=-2:2, scale=0.3]
\begin{knot} [clip width=4]
\strand (0,2) to [out=down, in=down, looseness=1.8] (1.5,0);
\strand (1.5,0) to [out=up, in=up, looseness=1.8] (0,-2);
\end{knot}
\draw[dashed] (0,0) circle (2cm);
\end{tikzpicture}$
\end{document}

The point it, that I need a visible "top and bottom" at each crossing (i.e. nonzero clip width). In the above example, the crossings don't work properly. However, if I draw a different (larger) knot such as:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{knots}
\begin{document}
$\begin{tikzpicture}[domain=-2:2, scale=0.3]
\begin{knot} 
\strand (-1.3,1.3) to [out=right, in=right, looseness=2.2] (-1.3,-1.3);
\strand (1.3,1.3) to [out=left, in=left, looseness=2.2] (1.3,-1.3);
\end{knot}
\draw[dashed] (0,0) circle (2cm);
\end{tikzpicture}$
\end{document}

everything is fine. What is causing this strange behavior?

  • If you draw the second strand twice, it works?!! – cfr Dec 12 '14 at 22:02
7

The problem is most likely due to the fact that your crossings are too close to the ends of two strands, making them fail the "end tolerance" distance test. More on this below.


The knots package does some complicated stuff to try to ensure that it gets all possible intersections. Sometimes, this is over complicated so there are options to turn off some of the more extensive routines - and some aren't enabled by default. To make yours work, you need to add the option ignore endpoint intersections=false option to the knot environment.

Note that you mustn't have a space between the \begin{knot} and the start of the optional environment.

\documentclass{article}
%\url{http://tex.stackexchange.com/q/217719/86}
\usepackage{tikz}
\usetikzlibrary{knots}
\begin{document}
\begin{tikzpicture}[domain=-2:2, scale=0.3]
\begin{knot}[
  clip width=4,
  ignore endpoint intersections=false,
]
\strand (0,2) to [out=down, in=down, looseness=1.8] (1.5,0);
\strand (1.5,0) to [out=up, in=up, looseness=1.8] (0,-2);
\end{knot}
\draw[dashed] (0,0) circle (2cm);
\end{tikzpicture}
\end{document}

Note that in investigating what was going on here, I uncovered a bug or two in the library and updated the version on github.

Update: 2014-12-15 One thing that was puzzling me here was as to why this particular crossing was being affected by the test involved in ignore endpoint intersections since this isn't an endpoint and I thought I'd planned the knot code so that this would never become an endpoint (which can happen as paths get split into pieces). In short, the endpoint test ignores crossings that are considered too close to the ends of strands. The alternative solution in the comments gave the game away. The scale=0.3 makes the diagram so small that just about every point inside it is within the default tolerance of the endpoints of the strands (note that because the path is split in to two strands, there is an endpoint at (1.5,0). Note also that it is possible to use a single strand here using the key consider self intersections but this still has the end point issue.). The solution above works by switching off the "are we close to the end of a strand?" test. An alternative is to make the test more rigorous by decreasing the tolerance. Fortunately, I thought of that when I wrote the original package (though had forgotten it since!) and there is a key end tolerance=<dimen> to refine the test. Thus:

\begin{tikzpicture}[domain=-2:2, scale=.3]
\begin{knot}[
  clip width=4,
  end tolerance=1pt,
]
\strand (0,2) to [out=down, in=down, looseness=1.8]
(1.5,0);
\strand (1.5,0) to [out=up, in=up, looseness=1.8]
(0,-2);
\end{knot}
\draw[dashed] (0,0) circle (2cm);
\end{tikzpicture}

also works.

  • (+1) Could have sworn I tried that... – cfr Dec 14 '14 at 1:26
  • @cfr Did you remove the space? If you don't delete the space between \begin{knot} and the [...] then the part in [...] isn't taken as the optional argument to the knot environment but is passed on to \tikzset which doesn't have the same effect. – Loop Space Dec 14 '14 at 1:27
  • Frankly, I'm not sure at this point. Very likely not as that is not something I would have spontaneously thought of in a TiKZ context and I only skimmed the documentation, having never tangled with knots before that I can recall. So I'm sure that must be it. – cfr Dec 14 '14 at 1:35
  • 1
    @cfr Interestingly, the necessity of no spaces is because the knot environment is defined using \NewDocumentEnvironment from xparse rather than the standard \newenvironment. – Loop Space Dec 14 '14 at 1:54
  • @Loop Space: one more information: A collegue of mine gave me this knot-code: \begin{tikzpicture}[scale=1] \begin{knot}[clip width=5] \strand[ultra thick] (0,2) to [out=down, in=down, looseness=1.8] (1.5,0); \strand[ultra thick] (1.5,0) to [out=up, in=up, looseness=1.8] (0,-2); \flipcrossings{1}; \end{knot} \draw[dashed] (0,0) circle (2cm); \end{tikzpicture} which is working as intended. – ulead86 Dec 15 '14 at 8:42
3

This works but I have no idea why:

\documentclass[tikz, border=5pt, mult, varwidth]{standalone}
\usetikzlibrary{knots}
\begin{document}
  \begin{tikzpicture}[domain=-2:2, scale=0.3]
    \begin{knot} [clip width=4]
      \strand (0,2) to [out=down, in=down, looseness=1.8] (1.5,0);
      \strand (1.5,0) to [out=up, in=up, looseness=1.8] (0,-2);
      \strand (1.5,0) to [out=up, in=up, looseness=1.8] (0,-2);
    \end{knot}
    \draw[dashed] (0,0) circle (2cm);
  \end{tikzpicture}
\end{document}

knotted

Alternatively, use the knot=colour and knot gap=factor styles:

\documentclass[tikz, border=5pt, mult, varwidth]{standalone}
\usetikzlibrary{knots}
\begin{document}
  \begin{tikzpicture}[domain=-2:2, scale=0.3, knot gap=7]
      \draw [knot=black] (0,2) to [out=down, in=down, looseness=1.8] (1.5,0) ;
      \draw [knot=black] (1.5,0) to [out=up, in=up, looseness=1.8] (0,-2);
    \draw[dashed] (0,0) circle (2cm);
  \end{tikzpicture}
\end{document}

knotted again

  • Thanks for your reply. Now I'm interested, why your first solution is working and my (nearly the same try) doesn't. – ulead86 Dec 13 '14 at 10:42
  • @ulead86 I don't know. I am interested in the same question. I have no idea why drawing part of the path again should work, but drawing it once does not. – cfr Dec 13 '14 at 17:27

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.