1

I am trying to draw a knot using the knots package, but the crossing labels are straight up, which looks bad at most crossings. This is my code:

\begin{tikzpicture}
\begin{knot}[draft mode=crossings, clip width=10pt,consider self intersections,end tolerance=1pt]
\strand[ultra thick]
(0,0.3) to[out=180,in=90]
(-1.2,-1.5) to[out=-90,in=180]
(1,-3.5) to[out=0,in=0,looseness=2]
(0,-1) to[out=180,in=180,looseness=2]
(-1,-3.5) to[out=0,in=-90]
(1.2,-1.5) to[out=90,in=0] (0,0.3);
\end{knot}
\end{tikzpicture}

Bad Trefoil!

How can I change the pins on an individual basis?

Thanks in advance!

  • Hmm, the author of the package doesn't seem to have thought of this possibility. It is possible to change all the labels' styles, but the way that the labels are rendered means that the index of a label is forgotten by the time it is laid out -- I tried a simple solution with extra styles indexed by the label number but it didn't work -- so changing an individual label style is a little more complicated. – Andrew Stacey Jul 13 '18 at 20:18
  • So is the best option probably removing the automatic labels and placing manual ones? –  Jul 13 '18 at 20:21
  • No, the best option is persuading the author to fix the code ... but in the meantime, I have a fix for you. – Andrew Stacey Jul 13 '18 at 20:30

1 Answers1

2

The author of the knots package didn't put a lot of thought in to these labels - they were intended originally only for helping lay out the knot and figure out which crossings to flip. I'm guessing that you want to use them in the final document.

So the best solution would be to modify the existing library to allow for a customisable per-label style. Something like modifying the definition of \knot_render: so that the part that currently reads:

\bool_if:NTF \l__knot_draft_bool
    {
      \tl_set:Nn \l__knot_node_tl {
        \exp_not:N \node[coordinate,
          pin={[knot~ diagram/draft/crossing~ label]
            {\int_use:N \l__knot_intersections_int}}]
      }
    }

was changed to something like:

\bool_if:NTF \l__knot_draft_bool
    {
      \tl_set:Nn \l__knot_node_tl {
        \exp_not:N \node[coordinate,
          pin={[knot~ diagram/draft/crossing~ label, knot~ diagram/draft/crossing~ \int_use:N \l__knot_intersections_int \c_space_tl label/.try]
            {\int_use:N \l__knot_intersections_int}}]
      }
    }

Then you could define styles like draft/crossing 1 label and they'd get executed on the right label.

Without modifying the original package, the alternative is to try to patch the crossing~ label style to execute an additional style which depends on the crossing number. The difficulty with that is that by the time crossing~ label gets executed, the counter \l__knot_intersections_int is no longer useable. So we have to insert a new counter (which adds an extra wriggle as it turns out that the labels are laid out in reverse! Really, the person who wrote this package made some funny decisions.)

Anyway, here's some code that works. Use at your own risk!

\documentclass{article}
%\url{https://tex.stackexchange.com/q/440528/86}
\usepackage{tikz}
\usetikzlibrary{knots}

\ExplSyntaxOn

\int_new:N \l__knot_current_intersection_int

\tikzset{
  knot~ diagram/draft/crossing~ label/.append~ style={
    knot~ diagram/draft/do~ next~ label
  },
  knot~ diagram/draft/do~ next~ label/.code={
    \pgfkeysalso{knot~ diagram/draft/crossing~ \int_eval:n {\l__knot_intersections_int -  \l__knot_current_intersection_int}~ label/.try}
    \int_gincr:N \l__knot_current_intersection_int
  },
  knot~ diagram/reset~ label~ counter/.code={
    \int_gzero:N \l__knot_current_intersection_int
  }
}

\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}
\begin{knot}[
  reset label counter,
  draft mode=crossings,
  clip width=10pt,
  consider self intersections,
  end tolerance=1pt,
  draft/crossing 3 label/.style={
    text=red,
    pin position=45,
  },
  draft/crossing 1 label/.style={
    text=green,
    pin position=135,
  }
]
\strand[ultra thick]
(0,0.3) to[out=180,in=90]
(-1.2,-1.5) to[out=-90,in=180]
(1,-3.5) to[out=0,in=0,looseness=2]
(0,-1) to[out=180,in=180,looseness=2]
(-1,-3.5) to[out=0,in=-90]
(1.2,-1.5) to[out=90,in=0] (0,0.3);
\end{knot}
\end{tikzpicture}

\end{document}

This produces:

labelled trefoil

As a postscript, I've registered this as an issue on the spath3 issue tracker at https://github.com/loopspace/spath3/issues/1

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • Is some package needed for \ExplSyntaxOn, it is showing up as an unrecognized command? –  Jul 13 '18 at 20:53
  • Hmm, you need the expl3 package but the spath3 tikz library should load it so you shouldn't need to load it additionally. But you could try \usepackage{expl3} in the preamble. – Andrew Stacey Jul 13 '18 at 21:02
  • Still no, I am running LaTeX2e is that the wrong version, the documentation of \ExplSyntaxOn seems to be in the LaTeX3 Documentation... –  Jul 13 '18 at 21:16
  • No, LaTeX3 is a set of packages built on top of LaTeX2e so you run pdflatex as usual on the above document. Did you try with exactly the document I posted above? You must have the \usetikzlibrary{knots} before the \ExplSyntaxOn stuff. – Andrew Stacey Jul 13 '18 at 21:53
  • Yes I have copied your code verbatim into TeXstudio. And I am getting this output... NewTrefoil –  Jul 13 '18 at 22:04
  • I've added in what I get. It sounds as though something is wrong with your LaTeX installation. Can you send me your log file? The email address from the knots documentation will get to me (though texdoc tikzmark gives a more up to date email address). – Andrew Stacey Jul 13 '18 at 22:12