Decoración para líneas / curvas autocruzadas

Nov 29 2020

¿Es posible definir una decoración / postacción, para dibujar una línea doble de modo que una línea que se interseca se dibuje sobre sí misma? Para mostrar lo que quiero decir, vea estas espirales:

\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}

La espiral superior muestra el efecto de una línea doble normal y la espiral inferior muestra el resultado deseado. Deseo que el resultado se haga con un solo \drawcomando para evitar la renderización de artefactos y hacer que la smoothopción funcione en toda la espiral.

En última instancia, quiero poder usar el blanco como color exterior y así crear un efecto de cruce. Para poder responder mejor a las preguntas en este sitio, por ejemplo, espirales cónicas y cilíndricas

Estaba pensando que debería ser posible haciendo el doble en pequeños segmentos del camino a medida que se dibuja. Un enfoque ingenuo como este:

\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}

no funciona ya que la preacción se aplica a toda la ruta y no a los segmentos.

Una solución aún mejor sería si el camino pudiera cliphacerlo por sí mismo, de modo que el cruce se vea bien sobre un fondo no blanco. - Probablemente bastante complicado.

Respuestas

3 Noname Nov 28 2020 at 23:47

Aquí hay una forma con 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}

Tenga en cuenta que ya hay estilos completos para esto en esta respuesta .

4 AndrewStacey Nov 30 2020 at 00:55

La knotsbiblioteca TikZ maneja este tipo de cosas. Hay un pequeño problema con el uso del plotcomando de dibujo porque crea muchas líneas muy cortas y eso no es bueno para la forma en que knotsfunciona, ya que busca intersecciones entre subtrayectos. Afortunadamente, al usar la hobbybiblioteca, puedo reducir considerablemente el número de muestras, ya que se interpola usando curvas Bézier.

La knotsbiblioteca funciona redibujando solo parte de la curva en las intersecciones para producir el efecto de paso elevado.

El uso de la opción doble con la knotsbiblioteca puede producir artefactos cuando se visualiza el PDF (pero no cuando se imprime). El método para eliminarlos se detalla en el problema con "círculos de cultivo" en la biblioteca de nudos tikz

Aquí está el código:

\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/80*pi, {cos(22.5*\x )} , {sin(22.5*\x )} ) };
\end{knot}
\end{tikzpicture}
\end{document}

Resultado: