1

Is it possible to define a decoration/postaction, for drawing a double line so that a self intersecting line will draw on top of itself? To show what I mean see these spirals:

\documentclass[tikz, border=1cm]{standalone}
\begin{document}
\begin{tikzpicture}
\draw[red, double=yellow, thick, domain=0:pi, smooth, samples=200] plot (\x, {cos(10*\x r)} , {sin(10*\x r)} );
\begin{scope}[yshift=-3cm]
\foreach \i in {1,...,10}
\draw[red, double=yellow, thick, domain=pi*(\i-1)/10:pi*\i/10, smooth, samples=200] plot (\x, {cos(10*\x r)} , {sin(10*\x r)} );
\end{scope}
\end{tikzpicture}
\end{document}

Two spirals

The top spiral shows the effect of a normal double line and the bottom spiral shows the desired result. I wish the result done with just one \draw command to avoid rendering artefacts and make the smooth option work across the whole spiral.

Ultimately, I want to be able to use white as the outer color and thereby creating a crossing effect. To be able to better answer questions on this site e.g. Conical and cylindircal spirals

I was thinking that it should be possible by making the double on small segments of the path as it is being drawn. A naive approach like this:

\documentclass[tikz, border=1cm]{standalone}
\usetikzlibrary {decorations.pathmorphing}
\begin{document}
\begin{tikzpicture}
\draw[yellow, 
decorate, decoration={zigzag, segment length=1mm, amplitude=0mm},
preaction={draw, ultra thick, red},
domain=0:pi, samples=200] plot (\x, {cos(10*\x r)} , {sin(10*\x r)} );
\end{tikzpicture}
\end{document}

does not work as the preaction is applied to the whole path and not the segments.

A even better solution would be if the path could clip itself, so that the crossing would look nice on a non-white background. - Probably quite complicated.

2 Answers2

4

Here is one way with the show path construction.

\documentclass[tikz, border=1cm]{standalone}
\usetikzlibrary{decorations.pathreplacing}
\begin{document}
\begin{tikzpicture}[path decomposition/.style={%
    postaction={decoration={show path construction,
    lineto code={
      \draw[#1]  (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
    },
    curveto code={
      \draw[#1]  (\tikzinputsegmentfirst) .. controls
        (\tikzinputsegmentsupporta) and (\tikzinputsegmentsupportb)
        ..(\tikzinputsegmentlast) ;
    },
    closepath code={
      \draw[#1]  (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast) {closepath};} }
    ,decorate}}]
\draw[red, double=yellow, thick, domain=0:pi, smooth, samples=200,
path decomposition={red, double=yellow, thick}] plot (\x, {cos(10*\x r)} , {sin(10*\x r)} );
\begin{scope}[yshift=-3cm]
\foreach \i in {1,...,10}
\draw[red, double=yellow, thick, domain=pi*(\i-1)/10:pi*\i/10, smooth, samples=200] plot (\x, {cos(10*\x r)} , {sin(10*\x r)} );
\end{scope}
\end{tikzpicture}
\end{document}

enter image description here

Please note that there are already complete styles for this in this answer.

  • You are fast :o) . Also thanks for the link - I will study it. – hpekristiansen Nov 28 '20 at 17:04
  • It is a very beautiful solution. At first, I could not see how it could possible be more elegant. -but at closer look, there are many rendering artefacts. It can be spotted on your picture, but it is easier seen with black on white. There are many hairline spikes and gaps. I do not understand the spikes(I believe that double is implemented by drawing fat line first and then center - the center should not be able to poke out.). Maybe the gaps could be corrected with shorten!? – hpekristiansen Nov 28 '20 at 17:18
  • I will probably accept your answer, but I would like your opinion on wether the artefacts are possibly corrected. – hpekristiansen Nov 28 '20 at 17:19
  • shorten <=-0.002 pt makes it better – hpekristiansen Nov 28 '20 at 17:28
  • @hpekristiansen I do not know if the artifacts can be corrected easily. They seem also to be a bit viewer dependent. Another way to go is to use the knots library. However, I am not sure if this is ideal for the scenario you want to use it on. IMHO the 3d coil from the linked answer might be a reasonable alternative. (I also tried to shorten the stretches by a negative amount but the result does not look fully convincing on all viewers I tried.) –  Nov 28 '20 at 17:29
  • Maybe it is better to replacing \draw[red, double=yellow, with \path[ . -so that it is not drawn twice. I am not sure that it does anything. – hpekristiansen Nov 28 '20 at 17:53
  • By not having the smooth option, it is very visible that the line segments are not mitred. In the same way will individual curved segments not end in the exact same angle as the next curve segment starts. Conclusion: The artefacts are real and not just viewer rendering. – hpekristiansen Nov 28 '20 at 18:04
  • 1
    @hpekristiansen The artifacts are real, of course, since the path gets decomposed, but how they look like does depend on the viewer. I get very different results with acroread and preview. –  Nov 28 '20 at 18:07
  • One last question: Do you know what controls the segment length? I can not find it in the manual. – hpekristiansen Nov 28 '20 at 18:13
  • 1
    @hpekristiansen The decoration really just hooks into the segments as they get created by the path. In your case, the segment length is controlled by samples=200, which produces 199 plot segments, each of which is a Bezier curve since you use the smooth key. That is, the segment length is entirely specified by the path you decorate. –  Nov 28 '20 at 18:16
4

The knots TikZ library handles this sort of thing. There's a slight issue with using the plot drawing command because that creates a lot of very short lines and that's not great for the way that knots works since it looks for intersections between subpaths. Fortunately, using the hobby library I can reduce the number of samples considerably as it interpolates using bezier curves.

The knots library works by redrawing just part of the curve at the intersections to produce the overpass effect.

Using the double option with the knots library can produce artefacts when the PDF is viewed (but not when it is printed). The method for removing them is detailed at problem with "crop circles" in tikz knot library

Here's the code:

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

\tikzset{ basic strand/.style={ red, double=yellow, double distance=1pt, }, crossing strand/.style={ line width=1.8pt, only when rendering/.style={% draw=yellow,% line width=1pt, double=none, } } }

\begin{document} \begin{tikzpicture}[use Hobby shortcut] \begin{knot}[ consider self intersections=true, ignore endpoint intersections=false, background colour=red, every intersection/.style={ crossing strand }, only when rendering/.style={ basic strand }, clip width=1 ] \strand (0,1,0) \foreach \x in {1,...,80} { .. (\x/80pi, {cos(22.5\x )} , {sin(22.5*\x )} ) }; \end{knot} \end{tikzpicture} \end{document}

Result:

Coil with overlay effect

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • Cool - I have not used knots or hobby before. -I need to read the manual. I guess, that no amount of screaming and jumping, will completely eliminate artefacts as also shown here: https://tex.stackexchange.com/questions/572839/joining-tikz-paths-seamlessly/572882#572882 .-but this is definitely an improvement. – hpekristiansen Nov 30 '20 at 15:08
  • @hpekristiansen Actually, those artefacts can be easily removed. See https://tex.stackexchange.com/q/188447/86 – Andrew Stacey Nov 30 '20 at 21:41
  • @hpekristiansen I've modified it to use the non-artefact code. – Andrew Stacey Nov 30 '20 at 21:55