34

I was wondering if anyone could suggest software/packages to create nice knot diagrams (hopefully with a link to images they have made in the past).

I have used xy-pic recently but am mainly interested in hearing about other options.

5 Answers5

38

I have a prototype package for this using TikZ/PGF. At the moment, it is a bit basic as it was originally designed to draw very specific link diagrams and only afterwards did I start to extract the more general bits. Nonetheless, it can produce quite nice knot diagrams (I think) and I'd be happy to hear ideas on how it could be improved. You can get it from my homepage (when it is a little more polished then I'll put it on CTAN).

Here are some samples to whet your appetite. First, the preamble for all these examples:

\documentclass{article}
\usepackage{brunnian}

\usetikzlibrary{%
  arrows%
}

\tikzset{every path/.style={red,line width=2pt},every node/.style={transform shape,knot crossing,inner sep=1.5pt},>=triangle 60,text node/.style={rectangle,transform shape=false,black}}

Next, a trefoil

\begin{tikzpicture}
\foreach \brk in {0,1,2} {
\begin{scope}[rotate=\brk * 120]
\node (k\brk) at (0,-1) {};
\end{scope}
}
\draw (0,0) \foreach \brk in {0,1,2} {let \n0=\brk, \n1={int(Mod(\brk+1,3))}, \n2={int(Mod(\brk+2,3))} 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)} (k2);
\end{tikzpicture}

trefoil

This extends very easily to, for example, a cinquefoil:

\begin{tikzpicture}
\foreach \brk in {0,...,4} {
\begin{scope}[rotate=\brk * 72]
\node (k\brk) at (0,-1.5) {};
\end{scope}
}
\draw (0,0) \foreach \brk in {0,...,4} {let \n0=\brk, \n1={int(Mod(\brk+1,5))}, \n2={int(Mod(\brk+2,5))} 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)} (k2);
\end{tikzpicture}

cinquefoil

\begin{tikzpicture}
\foreach \brk in {0,...,4} {
\begin{scope}[rotate=-\brk * 72]
\node (k\brk) at (0,-1.5) {};
\pgfmathtruncatemacro{\brl}{\brk+97}
\node[text node] at (0,2) {\(\char\brl\)};
\end{scope}
}
\node[text node] at (0,0) {\(f\)};
\node[text node] at (126:2.5) {\(g\)};
\draw (0,0) \foreach \brk in {0,...,4} {let \n0=\brk, \n1={int(Mod(\brk-1,5))}, \n2={int(Mod(\brk-2,5))} 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)} (k2);

\end{tikzpicture}

(K)not sure what this one is called, it's an obvious extension of the figure 8 knot:

sort of figure 8ish

\begin{tikzpicture}
\node[rotate=45] (tl) at (-1,1) {};
\node[rotate=-45] (tr) at (1,1) {};
\edef\twists{10}
\foreach \brk in {0,...,\twists} {
\node (m\brk) at (0,-1 - \brk) {};
}
\foreach \brk in {1,...,\twists} {
\pgfmathparse{int(\brk - 1)}
\edef\brl{\pgfmathresult}
\draw (m\brk) .. controls (m\brk.4 north west) and (m\brl.4 south west) .. (m\brl.center);
\draw (m\brk.center) .. controls (m\brk.4 north east) and (m\brl.4 south east) .. (m\brl);
}
\draw (m0) .. controls (m0.8 north west) and (tl.3 south west) .. (tl.center);
\draw (m0.center) .. controls (m0.8 north east) and (tr.3 south east) .. (tr);
\draw (tl.center) .. controls (tl.16 north east) and (tr.16 north west) .. (tr);
\draw (m\twists) .. controls (m\twists.32 south east) and (tr.32 north east) .. (tr.center);
\draw (m\twists.center) .. controls (m\twists.32 south west) and (tl.32 north west) .. (tl);
\draw (tl) -- (tr.center);
\end{tikzpicture}

Also have examples of the Reidemeister moves and likewise. Most of the images listed at this nLab page were done using this package and then exported to SVG via tex4ht. All of the images at this page were done using this package. In particular, the following monstrosity!

iterated Brunnian link with inscription

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
23

Run with xelatex or use package auto-pst-pdf or run latex->dvips->ps2pdf

\documentclass{article}
\usepackage{pst-knot}
\begin{document}

\begin{pspicture}(-2,-2)(5,2)
 \psKnot[linewidth=3pt,linecolor=red](0,0){3-1}
 \psKnot[linewidth=3pt,linecolor=blue](4,0){4-1}
\end{pspicture}

\end{document}

enter image description here

The documentation explains the meaning of 3-1 and 4-1

20

The question is old, so just for the record. MetaPost package fiziko may not be the most practical or stable tool for drawing knots, but the images it produces look somewhat fancy. All examples are in ConTeXt, but the same code can be used in LuaLaTeX or standalone as well:

\startMPcode
    input fiziko.mp;
    path p;
    p := (dir(90)*4/3cm) {dir(0)} .. tension 3/2 
        .. (dir(90 + 120)*4/3cm){dir(90 + 30)} .. tension 3/2 
        .. (dir(90 - 120)*4/3cm){dir(-90 - 30)} .. tension 3/2 
        .. cycle;
    % p := pathSubdivide(p, 6);
    addStrandToKnot (primeOne) (p, 1/5cm, "l", "1, -1, 1");
    draw knotFromStrands (primeOne);
\stopMPcode

enter image description here

\startMPcode
    input fiziko.mp;
    path p;
    p := (0, 2cm) .. (1/2cm, 3/2cm) .. (-1/2cm, 0) .. (1/2cm, -2/3cm) .. (4/3cm, 0) .. (0, 3/2cm) .. (-4/3cm, 0) .. (-1/2cm, -2/3cm) .. (1/2cm, 0) .. (-1/2cm, 3/2cm) .. cycle ;
    % p := pathSubdivide(p, 6) shifted (4cm, -1/2cm);
    addStrandToKnot (primeTwo) (p, 1/6cm, "l", "1, -1, 1, -1, 1");
    draw knotFromStrands (primeTwo);
\stopMPcode

enter image description here

\startMPcode
    input fiziko.mp;
    path p[];
    p1 := (fullcircle scaled 2cm) shifted (-1/2cm, 0);
    p2 := p1 shifted (1cm, 0);
    p3 := (-2cm, 0) -- (2cm, 0);
    % p3 := pathSubdivide(p3, 4);
    addStrandToKnot (someKnot) (p1, 1/6cm, "l", "0, 1, 0, 1");
    addStrandToKnot (someKnot) (p2, 1/6cm, "l", "");
    addStrandToKnot (someKnot) (p3, 1/6cm, "l", "1, -1, 1, -1");
    draw knotFromStrands (someKnot);
\stopMPcode

enter image description here

In addStrandToKnot (primeOne) (p, 1/5cm, "l", "1, -1, 1");, primeOne is the knot name. p is a path along which the strand should be drawn (note that pathSubdivide thing, the path should contain some reasonable number of points; upd: with recent updates there's no need to subdivide paths for knots in most cases), 1/5cm is the strand thickness, "l" is the type of shading (can be "l", "t" or "e", the latter is simply empty outline which works much faster and "t" doesn't work very well for now) and "1, -1, 1" is a list of "layers" where intersections in order of appearance along the path, go (above default "zero" level or below it).

And knotFromStrands (primeOne) actually draws all the strands and returns a picture.

Upd:

Default shading settings have been changed since the images above were produced and the output would look somewhat different now. These settings can be altered with defineMinStrokeWidth macro, which determines shading stroke width (default is 1/5pt) and defineLightDirection, which determines where does "light" come from (default is -1/8pi, 1/8pi). For instance, first knot with

defineLightDirection(1/8pi, -1/6pi);
defineMinStrokeWidth(1/5pt);

would look like this:

enter image description here

  • 3
    That looks pretty nice! – Henri Menke Aug 30 '18 at 09:58
  • Can you add an option to for basic knot drawing (with plain indication above or below) – Anton Petrunin Mar 21 '20 at 00:20
  • I think i can, but could you provide an example of what you want to have? – Sergey Slyusarev Mar 21 '20 at 09:47
  • This is looking great! I have never used "startMPcode", and I get an "undefined control sequence" with pdflatex. Do you know how I can use it without changing to LuaLatex? – Pxx Jul 26 '20 at 11:14
  • is it possible to have a path "split" in two, like in this question? – Pxx Jul 26 '20 at 11:37
  • 1
    @Jxx Thank you! Initially, i did use pdflatex with emp package to include metapost code directly into the document. Eventually, it stopped working and I tried gmp https://ctan.org/pkg/gmp , it did work similarly, but it was slow and I switched to LuaLaTeX, but now I can't get gmp to do its thing. You can try it, maybe it's just my setup. I'll try and find a way to make it work and, in case of success, will follow up here. – Sergey Slyusarev Jul 26 '20 at 12:24
  • @Jxx Branching is a feature i really want to include, but i didn't find a reasonable solution to the problem of the user interface for this. How would one conveniently describe a branching structure? Otherwise, it's doable and may be implemented in the future. – Sergey Slyusarev Jul 26 '20 at 12:28
  • @SergeySlyusarev Yes it is not so easy to do it in an automated way. I have started drawing some in Photoshop, and there I just put a few shadings on the corners of the branching, but not much. Of course the best would be to have the edges slightly rounded, which probably makes it more difficult. – Pxx Jul 26 '20 at 12:42
15

(This question, although old, keeps coming up when I search for tikz knots - yes, I know I'm searching for my own package but it's how I find the documentation when I'm on a foreign machine - so I thought I'd add an answer about the tikz knots library which was developed some time after this question was asked.)

There's a TikZ library, knots, which is available on CTAN (as part of a package called spath3) and github. There are quite a few questions on this site with examples using this package, here are just a few:

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
2

(The interface just asked me "Are you sure you want to add yet another answer?")

The spath3 (which the knots library is actually part of) has now been extended with a new set of routines that are useful in drawing knots. These work by actually cutting a path at the points where it intersects with another path and inserting gaps at those points, so it is particularly suited to situations where there is a non-uniform background, or where the aim is to style different pieces of the diagram differently (for example to illustrate a 3-colouring).

Here's a trefoil example. For more examples, see the documentation (texdoc spath3) or look on github.

\documentclass{article}
%\url{https://tex.stackexchange.com/q/17181/86}

\usepackage{tikz} \usetikzlibrary{spath3, intersections, hobby} \begin{document} \begin{tikzpicture}[ use Hobby shortcut, every trefoil component/.style={ultra thick, draw, red}, trefoil component 1/.style={blue}, ] \path[spath/save=trefoil] ([closed]90:2) foreach \k in {1,...,3} { .. (-30+\k240:.5) .. (90+\k240:2) } (90:2); \tikzset{spath/knot={trefoil}{8pt}{1,3,5}} \end{tikzpicture} \end{document}

trefoil with one component blue

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751