Knot theory is an area of mathematics that usually comes under the aegis of topology and geometry, though it can reach as far as physics and biology and shoelaces. At the cutting edge it involves quite intricate and complicated mathematics, but it is one of those areas where it is quite easy to grasp the basics quite possibly because of the simplicity of the central concept and the visual nature of the subject.
Drawing them, though, is something of an art. In this post I’ll introduce some new tools for helping draw knots, and similar diagrams using one new TikZ library, knots1, and one updated one, hobby.
Introduction
Knots are objects in three dimensional space, but we frequently draw them in two dimensions. When we do so we use a special kind of diagram. If we look at a knot from a particular direction and draw what we see then we will draw a series of curves in the plane which will occasionally intersect. Most of the time these intersections will be of the form of one strand clearly passing over or under another strand. That is, no triple or higher intersections and no strands “running alongside” each other. Indeed, from most angles all of the intersections will be of this type. When drawn from one of these angles then the only thing we need to know to recover the actual knot is which strand was the over strand and which the under one. We show this by drawing a gap in the under strand through which the over strand passes.
Knot diagrams can get quite complicated. Although there are algorithms that will give a drawing from a presentation of a knot, drawing knot diagrams can be more of an art than a science.
Thus a package aimed at helping people draw knot diagrams should be more concerned with supplying a variety of tools than providing a complete solution.
Knots, Links, Braids, Tangles, Strings
Mathematically, there are a variety of things that are studied that are all represented by the same sort of diagram. There are knots, links, braids, tangles, strings, and probably many others that I have yet to hear of. Some have more structure, some have less. Braids, for example, have quite a lot of structure and there my braids
package can exploit this to provide more of a general solution to drawing braids.
For the other types of diagrams there is now a knots
library for TikZ. This provides a variety of methods for drawing knots2. Some are quite straightforward, such as the knot
line style, and some are more complicated. In addition, the latest update to the hobby
TikZ library contains some useful tools for knot diagrams.
The Intersection Method
The most complicated tool in the knots
library was inspired by a comment by Jamie Vicary on his own question about drawing knots.
[It] would be really cool if it was possible to draw the curves, let TikZ calculate all the intersection points automatically, and then tell it to redraw the intersections according to an under/over specification… do you think this is in the realm of plausibility?
The knot
environment does exactly this. It gathers up a load of \strand
s which it draws. It then computes their intersections. At each intersection it renders one strand as going over the other. The user can then tell the algorithm to “flip” various of these intersections to produce the other crossing.
Here’s the code for a trefoil using this method. As the trefoil is a single path we need the key consider self intersections
. The only crossing we need to flip is the second.
\begin{knot}[
consider self intersections,
flip crossing=2
clip width=5,
]
\strand[thick,red]
(90:2) to[out=180,in=-120,looseness=2]
(-30:2) to[out=60,in=120,looseness=2]
(210:2) to[out=-60,in=0,looseness=2] (90:2);
\end{knot}
\end{tikzpicture}
The key consider self intersections
is needed because of how TikZ computes intersections. When working with a single path, every point would be considered a point of intersection. So we first need to “explode” the path into pieces small enough not to self-intersect and consider the intersections between those. If this isn’t needed it is best not to do it so an option is given for that.
Simpler Solutions
The intersection method is the most powerful but it can be a bit overkill in some situations. If the exact locations of the crossings are known in advance, or the order in which to draw the segments can be figured out easily, then the intersection method is a waste of time. However, even in these circumstances there are nifty little tools that come in handy.
If the crossing positions are known it can be useful to draw the crossings first and then join them up afterwards. For this purpose a variety of node shapes are provided. There are four that actually draw the crossing (well, two actually; the other two draw the horizontal and vertical resolutions of the crossing; if you don’t know, don’t worry!) and one that simply places a load of useful anchors.
For example, the trefoil could easily have been drawn as follows.
\foreach \brk in {0,1,2} {
\begin{scope}[rotate=\brk * 120]
\node[knot crossing, transform shape, inner sep=1.5pt] (k\brk) at (0,-1) {};
\end{scope}
}
\foreach \brk in {0,1,2} {
\pgfmathparse{int(Mod(\brk - 1,3))}
\edef\brl{\pgfmathresult}
\draw[thick,red] (k\brk) .. controls (k\brk.4 north west) and (k\brl.4 north east) .. (k\brl.center);
\draw[thick,red] (k\brk.center) .. controls (k\brk.16 south west) and (k\brl.16 south east) .. (k\brl);
}
\end{tikzpicture}
Slightly less clearly, we could have written:
\def\foil{3}
\foreach \brk in {1,...,\foil} {
\begin{scope}[rotate=\brk * 360/\foil]
\node[transform shape, knot crossing, inner sep=1.5pt] (k\brk) at (0,-1) {};
\end{scope}
}
\draw[thick,red] (0,0) \foreach \brk in {1,...,\foil} {let \n0=\brk, \n1={int(Mod(\brk,\foil)+1)}, \n2={int(Mod(\brk+1,\foil)+1)} in (k\n0) .. controls (k\n0.16 south east) and (k\n1.16 south west) .. (k\n1.center) .. controls (k\n1.4 north east) and (k\n2.4 north west) .. (k\n2)};
\end{tikzpicture}
This, at least, can be easily generalised.
When the order in which to draw the strands is known, the only thing that needs to happen is for the over crossings to “cut” the under crossings. This is easily done in TikZ using the double
key. This package provides a knot
style that makes this even simpler.
\draw[red,knot,ultra thick] (0,0) .. controls +(1,0) and +(-1,0) .. (2,1);
\draw[knot=blue,ultra thick] (0,1) .. controls +(1,0) and +(-1,0) .. (2,0);
\end{tikzpicture}
(Note that the colour has to be either the option to the knot
key or come before it.)
Drawing Knots for a Hobby
The latest update to the hobby
package provides a useful tool for drawing knots. In brief, the hobby
package defines an algorithm (due to John Hobby) for drawing a piecewise cubic curve through a predefined set of points. The computationally hard part is figuring out the parameters defining the curve, but often this only needs to be done once. So to improve the usage, I split the generation of the curve from its use. This also meant that it was possible to reuse the curve in slightly different ways.
The data from the curve is the series of cubics joining the points. When passed to TikZ, the algorithm can choose to omit a segment from the rendering (though it still played a part when computing the curves). The curve can then be redrawn with the omitted parts put back, and possibly others omitted. This provides a way to use the curves computed by the hobby
package for knot diagrams.
Here’s the trefoil yet again.
use Hobby shortcut,
every path/.style={
line width=1mm,
white,
double=red,
double distance=.5mm
}
]
\def\nfoil{3}
\draw ([closed]0,2)
\foreach \k in {1,...,\nfoil} {
.. ([blank=soft]90+360<em>\k/\nfoil-180/\nfoil:-.5) .. (90+360</em>\k/\nfoil:2)
};
\draw[use previous Hobby path={invert soft blanks,disjoint}];
\end{tikzpicture}
Interesting stuff. 🙂 Two comments:
(1) The second-to-last image is broken (wrong URL).
(2) These example knots would be more readable if both the lines and the ‘gaps’ were a lot thicker.
I’ve enlarged the pictures, does that look better?
Is this the “proper release quality” version of “brunnian” (http://www.math.ntnu.no/~stacey/HowDidIDoThat/LaTeX/brunnian.html)?
Yes, to a certain extent. I’ve taken the “generic” stuff out of the brunnian package and included it in the knot library (and cleaned it up considerably). I haven’t included the stuff that was for drawing the very specific links. I’m unlikely to put that into a CTAN package as I doubt many people will want to draw those specific links.
Is there a way of installing the knots package without installing expl3?
(For some reason, I didn’t get notified of that comment, sorry.)
No, but you will have the l3 packages on your system already if you have TeXLive or MikTeX.
Using this example
\begin{tikzpicture}
\begin{knot}[
consider self intersections,
flip crossing=2
clip width=5,
]
\strand[thick,red]
(90:2) to[out=180,in=-120,looseness=2]
(-30:2) to[out=60,in=120,looseness=2]
(210:2) to[out=-60,in=0,looseness=2] (90:2);
\end{knot}
\end{tikzpicture}
I get short black line segments at every crossing. Anyone know why this might happen?