自己交差する線/曲線の装飾

Nov 29 2020

自己交差する線がそれ自体の上に描画されるように二重線を描画するための装飾/事後処理を定義することは可能ですか?私が何を意味するかを示すために、これらのスパイラルを見てください:

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

上のスパイラルは通常の二重線の効果を示し、下のスパイラルは望ましい結果を示しています。\drawアーティファクトのレンダリングを回避smoothし、スパイラル全体でオプションが機能するように、1つのコマンドで結果が得られることを望みます。

最終的には、外側の色として白を使用して、交差効果を作成できるようにしたいと考えています。このサイトの質問にもっとよく答えられるようにするため、例えば円錐形と円筒形のスパイラル

パスを描いているときに、パスの小さなセグメントをダブルにすることで可能になるはずだと思っていました。このような素朴なアプローチ:

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

事前アクションはパス全体に適用され、セグメントには適用されないため、機能しません。

さらに良い解決策は、パスclip自体が可能であれば、交差点が白以外の背景で見栄えがするようにすることです。-おそらくかなり複雑です。

回答

3 Noname Nov 28 2020 at 23:47

これが。の1つの方法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}

この回答には、これに対する完全なスタイルがすでに存在することに注意してください。

4 AndrewStacey Nov 30 2020 at 00:55

knotsTikZライブラリは、この種のものを処理します。plot描画コマンドの使用にはわずかな問題があります。これは、非常に短い線が多数作成され、knotsサブパス間の交差を検索するため、動作方法としては適切ではないためです。幸い、hobbyライブラリを使用すると、ベジェ曲線を使用して補間するため、サンプルの数を大幅に減らすことができます。

knotsライブラリは陸橋効果を生み出すために交差点にカーブの一部だけを再描画することによって動作します。

knotsライブラリでdoubleオプションを使用すると、PDFを表示したときにアーティファクトが生成される可能性があります(印刷時は生成されません)。それらを削除する方法は、tikzノットライブラリの「ミステリーサークル」の問題で詳しく説明されています

コードは次のとおりです。

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

結果: