7

Using the knots package, I have drawn a (3,7)-torus knot. I would like for the inner region of the diagram to be shaded gray.

A minimal working example for the code follows.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{hobby,knots}
\begin{document}

\begin{tikzpicture}[use Hobby shortcut]
\fill[black!30!white] (90:1) \foreach \k in {1,...,7}{--(90+\k*360/7:1)};

\begin{knot}[
  consider self intersections=true,
  ignore endpoint intersections = false,
  flip crossing/.list={1,7,6,11,10, 13, 15, 2}
]
\strand[very thick] ([closed]90:2) foreach \k in {1,...,7} 
   { .. (90-360/7+\k*1080/7:1) .. (90+\k*1080/7:2) } (90:2);
\end{knot}

\end{tikzpicture}
\end{document}

The figure produced by this code follows.

enter image description here

The problem with the figure is that I would like the gray region to fit neatly next to the arcs of the knot diagram that bounds it. There are three issues I would like to fix.

  1. The knot tikzlibrary works by drawing larger white background lines around the strands that appear on top at a crossing. This is how the effect of an over/under crossing is achieved (I think). I want the shaded region to ignore those larger white lines and meet the actual arcs of the knot diagram.
  2. I've guessed the crossing coordinates in my \fill command. Is there anyway to compute exactly what those coordinates are?
  3. The arcs in the inner region are closely approximated by straight line segments. In this case, I could probably get away by filling a path (if question 1 was resolved). However, I do not know how to approach shading some of the regions with curvier boundaries.

Any help is greatly appreciated.

  • 1
    Please expand your code snippet into a complete minimal working example: that is, a minimal piece of code that compiles and demonstrates your problem. –  Jan 12 '18 at 22:57
  • @Andrew, I believe I have a minimal working example that shows my problem and my attempt so far. Does this help? – Adam Lowrance Jan 13 '18 at 00:07
  • 1
  • @marmot That does not seem to be the same problem at all. Technically, the issues seem to me entirely distinct. Can you explain why, of all the questions on the site, you thought yours was the most likely to be helpful to the OP? :-) – cfr Jan 13 '18 at 02:16
  • 1
    If I were you, I'd try to change my mind about what I was trying to draw. How crucial is this? Because it is probably going to be a PITA, to be honest. You can presumably (I guess) get the coordinates from the package - if they are provided in sufficiently accessible form. Then you will need to compensate by an amount equal to the line width less half the distance between doubles. To do this neatly, you'll need to adjust at an angle which depends on the two lines meeting at that coordinate. At least, I think so. Rather you than me, I must say. – cfr Jan 13 '18 at 02:23
  • 1
    If you wanted all the background grey or something, that'd be easy. Or if you wanted a colour other than white for the borders of the lines. I also wonder if you've thought about what the result will look like. I expect it will look rather odd at the points where the intersections abut the grey. It will look as if the white appears out of the grey, which seems odd. The result won't be properly balanced. – cfr Jan 13 '18 at 02:25
  • The point of the picture is to highlight that region to the reader. The figure will describe an operation called region crossing change where all crossings touching that region are changed to their mirror image. Of course, I could just label the region with a letter instead of shading it. But I thought the shading would be more visually appealing. An example is the first picture here. – Adam Lowrance Jan 13 '18 at 02:36
  • @cfr Well, I might be naive, but isn't the underlying difficulty letting TikZ clip complicated paths? That is, ! Package tikz Error: Extra options not allowed for clipping path command.. If this was not the case, I thought it should be straightforward to clip / fill the knot, or the area surrounded by the arcs drawn in this post. –  Jan 13 '18 at 03:15
  • @marmot Not really, because the 'clip' here needs to exclude part of the path, which is not the case in the other example. That is, the white is part of what is being drawn and this needs to be filled over with the grey. So it is a different problem, even though the immediate issue is the same. That is, the superficial problem is the same, but the underlying one is not. – cfr Jan 14 '18 at 03:46

2 Answers2

7

I have no idea how to fill exactly this area, but you can cheat like this :

\documentclass[tikz,border=7pt]{standalone}
\usetikzlibrary{hobby,knots,shapes}

\begin{document}

  \begin{tikzpicture}[use Hobby shortcut]

    \begin{knot}[
        consider self intersections=true,
        ignore endpoint intersections = false,
        flip crossing/.list={1,7,6,11,10, 13, 15, 2}
      ]
      \strand[very thick] ([closed]90:2) foreach \k in {1,...,7}
        { .. (90-360/7+\k*1080/7:1) .. (90+\k*1080/7:2) } (90:2);
    \end{knot}

    \node[regular polygon,regular polygon sides=7,fill,fill opacity=.21, inner sep=6.8mm, rotate=7] {};
  \end{tikzpicture}
\end{document}

enter image description here

Kpym
  • 23,002
  • I’m a bit ashamed I did not come up with this solution myself. I suspect cfr is right that the general case is more trouble than it’s worth, but this does get the job done for this example. – Adam Lowrance Jan 13 '18 at 17:31
  • 1
    @AdamLowrance If you put it in a blend scope, you don't have to be as accurate in specifying the path to clip. That might help in cases which are slightly more problematic than this one, even though it still wouldn't help in the general case. (Effectively, you can stop the grey painting over the black, so it doesn't matter if you don't clip perfectly to the white area, except at the intersections.) – cfr Jan 14 '18 at 03:49
5

Here's a method using blend modes (the PGF manual warns that these might not be supported by all renderers/printers). The thinking behind it is that the white-out part of the knot should blank out other strands of the knot but not anything else. So everything ends up in a blend group and we choose the blend modes appropriately.

To get the actual region, we fill the knot path using the even odd rule and clip against a circle of just the right size (magic numbers courtesy of www.i-just-made-them-up.com). This gets us the correct region (for a more generic shape, one might have to be a bit creative for this part). Drawing the knot over the top sort of works, but has the issue of the white-out showing and hence the use of blend modes.

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

\begin{document}

\begin{tikzpicture}[use Hobby shortcut]

\begin{scope}[blend group=darken]

\begin{scope}[blend group=normal,even odd rule]
\clip (0,0) circle[radius=1.07];
\fill[black!30!white, save Hobby path={knot}] ([closed]90:2) foreach \k in {1,...,7} 
   { .. (90-360/7+\k*1080/7:1) .. (90+\k*1080/7:2) } (90:2);
\end{scope}

\begin{scope}[blend group=normal]
\begin{knot}[
  consider self intersections=true,
  ignore endpoint intersections = false,
  flip crossing/.list={1,7,6,11,10, 13, 15, 2}
]
   \strand[very thick] ([closed]90:2) foreach \k in {1,...,7} { .. (90-360/7+\k*1080/7:1) .. (90+\k*1080/7:2) } (90:2);
\end{knot}
\end{scope}

\end{scope}
\end{tikzpicture}
\end{document}

Result:

shaded knot

Detail of a single junction:

single junction

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • The code doesn't seem to compile. I get You can't use\mathchar"1' after \advance.along with manyUndefined control sequence` errors. – Apoorv Potnis Oct 18 '22 at 12:27
  • @ApoorvPotnis I've just re-tried the code and it compiles. I'm using the latest version of the spath3/knots library, but I don't think I've changed much in the knots library lately so it should also work with the version on CTAN. If you have more details, I can try to help but I can't reproduce that error. – Andrew Stacey Oct 18 '22 at 21:18
  • I have uploaded the resulting log files to the following links. lualatex: https://justpaste.it/4phe5 xelatex: https://justpaste.it/3xygr pdflatex: https://justpaste.it/3xygr Please tell me if you need any additional information. I am using TeX Live 2022, updated today. – Apoorv Potnis Oct 18 '22 at 23:02
  • I get the same errors on Overleaf as well. – Apoorv Potnis Oct 18 '22 at 23:09
  • This looks like an incompatibility between knots and the latest latex3. Are you able to test with the version from github? Download the spath3_code.dtx file and compile it with just tex to create the libraries. I think that should work. – Andrew Stacey Oct 19 '22 at 06:02
  • https://github.com/loopspace/spath3 – Andrew Stacey Oct 19 '22 at 06:02
  • I compiled the .dtx file using tex and placed the above code in the same directory as the libraries. Is this correct? I still get the same error with pdf/lua/xelatex. – Apoorv Potnis Oct 19 '22 at 06:26
  • Okay, looks like I need to update my TL and see what they've done to L3 this time. sigh – Andrew Stacey Oct 19 '22 at 18:26
  • Gah! My TL update broke lualatex, but I did manage to get pdflatex working and that compiled okay. I hadn't noticed, but tgis vote also uses the hobby library which is also susceptible to l3 updates, and also available from github. – Andrew Stacey Oct 20 '22 at 05:51
  • I get errors on TeX Live 2022, 2021 and 2020. I get three errors on 2019 as well but the code compiles and I get a pdf. I don't think they update their distribution at Overleaf in between releases. So, probably the problem goes deeper than the recent changes to l3. – Apoorv Potnis Oct 20 '22 at 11:31
  • I don't get any errors on 2018/17 but the clippings are not correct. The output is same for both. The output is correct on 2019 though (with three errors). – Apoorv Potnis Oct 20 '22 at 11:35
  • @ApoorvPotnis I can't fix overleaf. I've just updated my installation of TL2022 and while it's somehow broken my version of lualatex, I can run pdflatex. With the most up to date versions of both the spath3 suite (including knots) and hobby packages then it compiles and produces the correct output. – Andrew Stacey Oct 20 '22 at 21:24
  • Sorry to bring this up again, but I cannot compile this on my TeX Live 2023 (updated today, default settings). I have tried compiling it withe the github version of spath3 as well. Same errors. I complains about errors on line 15. I can paste the log files if needed. – Apoorv Potnis Aug 29 '23 at 11:51
  • with both pdflatex and lualatex – Apoorv Potnis Aug 29 '23 at 11:57
  • Perhaps the code pasted here is different from the one you are using to compile on your machine, say a typo of a misplaced character? The code does not compile on texlive.net as well. – Apoorv Potnis Aug 29 '23 at 12:04
  • The issue actually lay with the hobby package - which I did mention as a possible source of incompatibility and had suggested that you try with the latest version from github. I hadn't uploaded the latest version to CTAN because it needs a major overhaul and I think that at the time it was merely triggering warnings and not actual errors. I've uploaded the latest version now, and it should make its way to TL shortly. In the meantime, you can get the latest version at https://github.org/loopspace/hobby – Andrew Stacey Aug 30 '23 at 20:58
  • I mistakenly did not use the github version of hobby, just spath3. Actually, it turns out that I didn't fully understand how to use the github versions. I foolishly simply cloned the directories and did not generate the .dtx files. I get the correct output now, thanks for the quick fix. – Apoorv Potnis Aug 30 '23 at 22:02
  • Sorry it took so long - these days you have to catch me when I have time to investigate. Fortunately, I'm procrastinating a bit at the moment so this was just timed right to dig a little deeper. – Andrew Stacey Aug 30 '23 at 22:05