結び目: \strand コマンドは \clip コマンドに奇妙な効果をもたらすようです

結び目: \strand コマンドは \clip コマンドに奇妙な効果をもたらすようです

結び目図を描いていて、\clipコマンドを使用して領域をシェーディングしています。 ただし、環境\strandのコマンドknotが に奇妙な影響を与えているようです\clip

例えば、正しい結果は(これを図1):望ましい結果 これは

% Diagram 1
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{knots}
\usetikzlibrary{hobby}
\begin{document}
    \definecolor{skyblue}{RGB}{60,120,234}
    \scalebox{0.3}{\begin{tikzpicture}[use Hobby shortcut]
        \pgfdeclarelayer{foreground}
        \pgfsetlayers{main,foreground}
        \begin{pgfonlayer}{foreground}
            \begin{scope}
                \clip (-2,3) .. (0,2) .. (0.4,1)
                            .. (0,0) .. (-0.4,-1)
                            .. (0,-2) .. (2,-3)
                            .. (4.8,0) .. (2,3)
                            .. (0,2) .. (-0.4,1) -- (-2,3);
                \clip (-2,-3) .. (0,-2) .. (0.4,-1)
                            .. (0,0) .. (-0.4,1)
                            .. (0,2) .. (2,3)
                            .. (4.8,0) .. (2,-3)
                            .. (0,-2) .. (-0.4,-1) -- (-2,-3);  
                \fill[skyblue,opacity=0.2] (-4.8,-3) rectangle (4.8,3);
            \end{scope}
            \begin{scope}
                \clip (2,3) .. (0,2) .. (-0.4,1)
                            .. (0,0) .. (0.4,-1)
                            .. (0,-2) .. (-2,-3)
                            .. (-4.8,0) .. (-2,3)
                            .. (0,2) .. (0.4,1) -- (2,3);
                \clip (2,-3) .. (0,-2) .. (-0.4,-1)
                            .. (0,0) .. (0.4,1)
                            .. (0,2) .. (-2,3)
                            .. (-4.8,0) .. (-2,-3)
                            .. (0,-2) .. (0.4,-1) -- (2,-3);  
                \fill[skyblue,opacity=0.2] (-4.8,-3) rectangle (4.8,3);
            \end{scope}    
            \draw (-2.2,0) node[scale=3] {$+$};
            \draw (2.2,0) node[scale=3] {$-$};
            \draw (5,2.5) node[scale=3] {$M$};
        \end{pgfonlayer}
        \begin{knot}[
                        consider self intersections,
                        clip width=10,
                        clip radius=0.5cm,
                        ignore endpoint intersections=false,
                        flip crossing/.list={6,14}
                    ]
            \strand[very thick,black,closed] 
                    (0.4,1) .. (0,2) .. (-2,3) 
                            .. (-4.8,0) .. (-2,-3) 
                            .. (0,-2) .. (0.4,-1) 
                            .. (0,0) .. (-0.4,1) 
                            .. (0,2) .. (2,3) 
                            .. (4.8,0) .. (2,-3) 
                            .. (0,-2) .. (-0.4,-1) .. (0,0);
        \end{knot}
    \end{tikzpicture}}
\end{document}

注意して\clipください前に \strand

\clipただし、 とを含むコードフラグメントの順序を入れ替えると\strand

% Diagram 2
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{knots}
\usetikzlibrary{hobby}
\begin{document}
    \definecolor{skyblue}{RGB}{60,120,234}
    \scalebox{0.3}{\begin{tikzpicture}[use Hobby shortcut]
        \pgfdeclarelayer{foreground}
        \pgfsetlayers{main,foreground}
        \begin{knot}[
                        consider self intersections,
                        clip width=10,
                        clip radius=0.5cm,
                        ignore endpoint intersections=false,
                        flip crossing/.list={6,14}
                    ]
            \strand[very thick,black,closed] 
                    (0.4,1) .. (0,2) .. (-2,3) 
                            .. (-4.8,0) .. (-2,-3) 
                            .. (0,-2) .. (0.4,-1) 
                            .. (0,0) .. (-0.4,1) 
                            .. (0,2) .. (2,3) 
                            .. (4.8,0) .. (2,-3) 
                            .. (0,-2) .. (-0.4,-1) .. (0,0);
        \end{knot}
        \begin{pgfonlayer}{foreground}
            \begin{scope}
                \clip (-2,3) .. (0,2) .. (0.4,1)
                            .. (0,0) .. (-0.4,-1)
                            .. (0,-2) .. (2,-3)
                            .. (4.8,0) .. (2,3)
                            .. (0,2) .. (-0.4,1) -- (-2,3);
                \clip (-2,-3) .. (0,-2) .. (0.4,-1)
                            .. (0,0) .. (-0.4,1)
                            .. (0,2) .. (2,3)
                            .. (4.8,0) .. (2,-3)
                            .. (0,-2) .. (-0.4,-1) -- (-2,-3);  
                \fill[skyblue,opacity=0.2] (-4.8,-3) rectangle (4.8,3);
            \end{scope}
            \begin{scope}
                \clip (2,3) .. (0,2) .. (-0.4,1)
                            .. (0,0) .. (0.4,-1)
                            .. (0,-2) .. (-2,-3)
                            .. (-4.8,0) .. (-2,3)
                            .. (0,2) .. (0.4,1) -- (2,3);
                \clip (2,-3) .. (0,-2) .. (-0.4,-1)
                            .. (0,0) .. (0.4,1)
                            .. (0,2) .. (-2,3)
                            .. (-4.8,0) .. (-2,-3)
                            .. (0,-2) .. (0.4,-1) -- (2,-3);  
                \fill[skyblue,opacity=0.2] (-4.8,-3) rectangle (4.8,3);
            \end{scope}    
            \draw (-2.2,0) node[scale=3] {$+$};
            \draw (2.2,0) node[scale=3] {$-$};
            \draw (5,2.5) node[scale=3] {$M$};
        \end{pgfonlayer}
    \end{tikzpicture}}
\end{document}

その結果は(これを図2): 悪いイメージ ご覧のとおり、陰影は曲線に適合していません。

生成コードを使用しても図1( は\clipの前にあります)コードの前に他のコマンド\strandがある場合でもエラーは表示されます。これは、コードを繰り返して確認することができます。\strand\clip図12回:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{knots}
\usetikzlibrary{hobby}
\begin{document}
    \definecolor{skyblue}{RGB}{60,120,234}
    \scalebox{0.3}{\begin{tikzpicture}[use Hobby shortcut]
        \pgfdeclarelayer{foreground}
        \pgfsetlayers{main,foreground}
        \begin{pgfonlayer}{foreground}
            \begin{scope}
                \clip (-2,3) .. (0,2) .. (0.4,1)
                            .. (0,0) .. (-0.4,-1)
                            .. (0,-2) .. (2,-3)
                            .. (4.8,0) .. (2,3)
                            .. (0,2) .. (-0.4,1) -- (-2,3);
                \clip (-2,-3) .. (0,-2) .. (0.4,-1)
                            .. (0,0) .. (-0.4,1)
                            .. (0,2) .. (2,3)
                            .. (4.8,0) .. (2,-3)
                            .. (0,-2) .. (-0.4,-1) -- (-2,-3);  
                \fill[skyblue,opacity=0.2] (-4.8,-3) rectangle (4.8,3);
            \end{scope}
            \begin{scope}
                \clip (2,3) .. (0,2) .. (-0.4,1)
                            .. (0,0) .. (0.4,-1)
                            .. (0,-2) .. (-2,-3)
                            .. (-4.8,0) .. (-2,3)
                            .. (0,2) .. (0.4,1) -- (2,3);
                \clip (2,-3) .. (0,-2) .. (-0.4,-1)
                            .. (0,0) .. (0.4,1)
                            .. (0,2) .. (-2,3)
                            .. (-4.8,0) .. (-2,-3)
                            .. (0,-2) .. (0.4,-1) -- (2,-3);  
                \fill[skyblue,opacity=0.2] (-4.8,-3) rectangle (4.8,3);
            \end{scope}    
            \draw (-2.2,0) node[scale=3] {$+$};
            \draw (2.2,0) node[scale=3] {$-$};
            \draw (5,2.5) node[scale=3] {$M$};
        \end{pgfonlayer}
        \begin{knot}[
                        consider self intersections,
                        clip width=10,
                        clip radius=0.5cm,
                        ignore endpoint intersections=false,
                        flip crossing/.list={6,14}
                    ]
            \strand[very thick,black,closed] 
                    (0.4,1) .. (0,2) .. (-2,3) 
                            .. (-4.8,0) .. (-2,-3) 
                            .. (0,-2) .. (0.4,-1) 
                            .. (0,0) .. (-0.4,1) 
                            .. (0,2) .. (2,3) 
                            .. (4.8,0) .. (2,-3) 
                            .. (0,-2) .. (-0.4,-1) .. (0,0);
        \end{knot}
    \end{tikzpicture}}

    \scalebox{0.3}{\begin{tikzpicture}[use Hobby shortcut]
        \pgfdeclarelayer{foreground}
        \pgfsetlayers{main,foreground}
        \begin{pgfonlayer}{foreground}
            \begin{scope}
                \clip (-2,3) .. (0,2) .. (0.4,1)
                            .. (0,0) .. (-0.4,-1)
                            .. (0,-2) .. (2,-3)
                            .. (4.8,0) .. (2,3)
                            .. (0,2) .. (-0.4,1) -- (-2,3);
                \clip (-2,-3) .. (0,-2) .. (0.4,-1)
                            .. (0,0) .. (-0.4,1)
                            .. (0,2) .. (2,3)
                            .. (4.8,0) .. (2,-3)
                            .. (0,-2) .. (-0.4,-1) -- (-2,-3);  
                \fill[skyblue,opacity=0.2] (-4.8,-3) rectangle (4.8,3);
            \end{scope}
            \begin{scope}
                \clip (2,3) .. (0,2) .. (-0.4,1)
                            .. (0,0) .. (0.4,-1)
                            .. (0,-2) .. (-2,-3)
                            .. (-4.8,0) .. (-2,3)
                            .. (0,2) .. (0.4,1) -- (2,3);
                \clip (2,-3) .. (0,-2) .. (-0.4,-1)
                            .. (0,0) .. (0.4,1)
                            .. (0,2) .. (-2,3)
                            .. (-4.8,0) .. (-2,-3)
                            .. (0,-2) .. (0.4,-1) -- (2,-3);  
                \fill[skyblue,opacity=0.2] (-4.8,-3) rectangle (4.8,3);
            \end{scope}    
            \draw (-2.2,0) node[scale=3] {$+$};
            \draw (2.2,0) node[scale=3] {$-$};
            \draw (5,2.5) node[scale=3] {$M$};
        \end{pgfonlayer}
        \begin{knot}[
                        consider self intersections,
                        clip width=10,
                        clip radius=0.5cm,
                        ignore endpoint intersections=false,
                        flip crossing/.list={6,14}
                    ]
            \strand[very thick,black,closed] 
                    (0.4,1) .. (0,2) .. (-2,3) 
                            .. (-4.8,0) .. (-2,-3) 
                            .. (0,-2) .. (0.4,-1) 
                            .. (0,0) .. (-0.4,1) 
                            .. (0,2) .. (2,3) 
                            .. (4.8,0) .. (2,-3) 
                            .. (0,-2) .. (-0.4,-1) .. (0,0);
        \end{knot}
    \end{tikzpicture}}
\end{document}

ここに画像の説明を入力してください 明らかに、それらは同じTikZ コードの場合、結果は同じではありません。

何が起こっているのか誰か説明してくれませんか?これを修正する方法? 前もって感謝します。

答え1

さらにテストしてみると、これは または のどちらのバグでもなくhobbyknotsおそらくどこかに文書化されるべき相互作用の「機能」であることがわかりました。

閉じた趣味曲線を作成するには、次のように入力します。

\draw[closed] (0,0) .. (1,1) .. (0,2) .. (-1,1) .. (0,0);

は、closed曲線が、端点がたまたま同じ点にある曲線ではなく、閉じた曲線として扱われることを示します (hobby違いの詳細については、ドキュメントを参照してください)。

closedこの時点では、TikZ は趣味の曲線が途中にあることを認識していないため、コマンドのオプションは\draw少し場違いです。そのため、そのコマンドを保存して、実質的に「次に遭遇する趣味の曲線にこれを適用する」ように指示する必要があります。結局のところ、趣味の曲線が作成される前に、パス上に趣味以外のものがある可能性があります。

これは通常、すべて問題なく、趣味の曲線を閉じるように指定する最も簡単な方法です。ただし、同じパスで 2 つの趣味の構造を使用する場合など、より細かい制御が必要になる場合があります。この状況では、closed趣味のパスの座標にオプションを追加できます。したがって、次のいずれかを実行すると、上記と同じパスが描画されます。

\draw ([closed]0,0) .. (1,1) .. (0,2) .. (-1,1) .. (0,0);
\draw (0,0) .. ([closed]1,1) .. (0,2) .. (-1,1) .. (0,0);
\draw (0,0) .. (1,1) .. (0,2) .. (-1,1) .. ([closed]0,0);

2番目と3番目では、TikZは趣味のパスを構築していることを認識しているので、「よし、閉じよう」と言うことができます。これパス」。最初は趣味の構築がトリガーされていない(最初に発生する..)ので、それ closed依然として「これを次の趣味の道に適用する」です。しかし、それは小さな技術的な問題です。

以前のスタイル設定から、または座標から収集されたオプションから、趣味のパスにオプションが適用されると、クリアされる(そしてグローバルに)。クリアリングで何か問題が発生した場合clear next Hobby path optionsオプションをクリアします。

当然のことながら、そうhobby振る舞うべきです。

を見てみましょうknots。 ストランドを定義すると( 経由\strand)、パスが使われますたくさん少なくとも、ストランド自体を描画し、次に通過するストランドからビットを切り取るために使用されます(したがって、各交差点でストランドが再描画されます)。キーをconsider self intersections使用すると、ストランドをコンポーネントに分割し、それぞれを個別に考慮する必要があるため、状況はさらに悪くなります。そのため、ストランドは描画されます。多くの時間

描画されるたびにスタイルを設定する必要があります。そのため、\strandスタイルオプションを保存し、ストランドが描画されるたびにそれらを呼び出します。通常、これはまさに必要なことです。しかし、工事パスはすでに構築されているため、パスのオプションはここでは必要ありません。通常、これは問題ではありません。このようなオプションは通常破棄されます。

しかし、closed趣味の道のオプションではありません。これは遅延アクションコマンドなので、次の趣味の道を待って待機します。意味すでに構築され、処理されています。そのため、次のものを非常に辛抱強く待ちます。そして、この次のものは閉じられることを意図していないため、閉じられたという驚きが得られます。

さて、解決策に移りましょう。最も簡単で、私見では最善の解決策は、closedを から の\strand座標の 1 つにシフトすることです。

        \strand[very thick,black] 
                ([closed]0.4,1) .. (0,2) .. (-2,3) 
                        .. (-4.8,0) .. (-2,-3) 
                        .. (0,-2) .. (0.4,-1) 
                        .. (0,0) .. (-0.4,1) 
                        .. (0,2) .. (2,3) 
                        .. (4.8,0) .. (2,-3) 
                        .. (0,-2) .. (-0.4,-1) .. (0,0);

clear next Hobby path options代替案としては、混乱しているパスの前にキーを配置する方法があります。これは私にとってはそれほどエレガントではないように思いますが、代替案として言及しておきます。

パスが開始するときにオプションをクリアして、すべてのパスが白紙の状態から開始されるようにすべきだと主張する人もいるでしょう。しかし、それを堅牢にするには、趣味のパッケージでこれまで行ったよりも少し深いレベルで TikZ スコープ メカニズムにフックする必要があります。したがって、別の理由でフックする必要があることがわかった場合は、これを念頭に置いておくことになりますが、今のところは後回しにしておきます。

以上のことを踏まえて、私が推奨する解決策は次のとおりです。

\documentclass{standalone}
% \url{https://tex.stackexchange.com/q/505080/86}
\usepackage{tikz}
\usetikzlibrary{knots}
\usetikzlibrary{hobby}
\begin{document}
    \definecolor{skyblue}{RGB}{60,120,234}
    \scalebox{0.3}{\begin{tikzpicture}[use Hobby shortcut]
        \pgfdeclarelayer{foreground}
        \pgfsetlayers{main,foreground}
        \begin{pgfonlayer}{foreground}
            \begin{scope}
                \clip (-2,3) .. (0,2) .. (0.4,1)
                            .. (0,0) .. (-0.4,-1)
                            .. (0,-2) .. (2,-3)
                            .. (4.8,0) .. (2,3)
                            .. (0,2) .. (-0.4,1) -- (-2,3);
                \clip (-2,-3) .. (0,-2) .. (0.4,-1)
                            .. (0,0) .. (-0.4,1)
                            .. (0,2) .. (2,3)
                            .. (4.8,0) .. (2,-3)
                            .. (0,-2) .. (-0.4,-1) -- (-2,-3);  
                \fill[skyblue,opacity=0.2] (-4.8,-3) rectangle (4.8,3);
            \end{scope}
            \begin{scope}
                \clip (2,3) .. (0,2) .. (-0.4,1)
                            .. (0,0) .. (0.4,-1)
                            .. (0,-2) .. (-2,-3)
                            .. (-4.8,0) .. (-2,3)
                            .. (0,2) .. (0.4,1) -- (2,3);
                \clip (2,-3) .. (0,-2) .. (-0.4,-1)
                            .. (0,0) .. (0.4,1)
                            .. (0,2) .. (-2,3)
                            .. (-4.8,0) .. (-2,-3)
                            .. (0,-2) .. (0.4,-1) -- (2,-3);  
                \fill[skyblue,opacity=0.2] (-4.8,-3) rectangle (4.8,3);
            \end{scope}    
            \draw (-2.2,0) node[scale=3] {$+$};
            \draw (2.2,0) node[scale=3] {$-$};
            \draw (5,2.5) node[scale=3] {$M$};
        \end{pgfonlayer}
        \begin{knot}[
                        consider self intersections,
                        clip width=10,
                        clip radius=0.5cm,
                        ignore endpoint intersections=false,
                        flip crossing/.list={6,14}
                    ]
            \strand[very thick,black]
                    ([closed]0.4,1) .. (0,2) .. (-2,3) 
                            .. (-4.8,0) .. (-2,-3) 
                            .. (0,-2) .. (0.4,-1) 
                            .. (0,0) .. (-0.4,1) 
                            .. (0,2) .. (2,3) 
                            .. (4.8,0) .. (2,-3) 
                            .. (0,-2) .. (-0.4,-1) .. (0,0);
        \end{knot}
    \end{tikzpicture}}

    \scalebox{0.3}{\begin{tikzpicture}[use Hobby shortcut]
        \pgfdeclarelayer{foreground}
        \pgfsetlayers{main,foreground}
        \begin{pgfonlayer}{foreground}
            \begin{scope}
                \clip (-2,3) .. (0,2) .. (0.4,1)
                            .. (0,0) .. (-0.4,-1)
                            .. (0,-2) .. (2,-3)
                            .. (4.8,0) .. (2,3)
                            .. (0,2) .. (-0.4,1) -- (-2,3);
                \clip (-2,-3) .. (0,-2) .. (0.4,-1)
                            .. (0,0) .. (-0.4,1)
                            .. (0,2) .. (2,3)
                            .. (4.8,0) .. (2,-3)
                            .. (0,-2) .. (-0.4,-1) -- (-2,-3);  
                \fill[skyblue,opacity=0.2] (-4.8,-3) rectangle (4.8,3);
            \end{scope}
            \begin{scope}
                \clip (2,3) .. (0,2) .. (-0.4,1)
                            .. (0,0) .. (0.4,-1)
                            .. (0,-2) .. (-2,-3)
                            .. (-4.8,0) .. (-2,3)
                            .. (0,2) .. (0.4,1) -- (2,3);
                \clip (2,-3) .. (0,-2) .. (-0.4,-1)
                            .. (0,0) .. (0.4,1)
                            .. (0,2) .. (-2,3)
                            .. (-4.8,0) .. (-2,-3)
                            .. (0,-2) .. (0.4,-1) -- (2,-3);  
                \fill[skyblue,opacity=0.2] (-4.8,-3) rectangle (4.8,3);
            \end{scope}    
            \draw (-2.2,0) node[scale=3] {$+$};
            \draw (2.2,0) node[scale=3] {$-$};
            \draw (5,2.5) node[scale=3] {$M$};
        \end{pgfonlayer}
        \begin{knot}[
                        consider self intersections,
                        clip width=10,
                        clip radius=0.5cm,
                        ignore endpoint intersections=false,
                        flip crossing/.list={6,14}
                    ]
            \strand[very thick,black] 
                    ([closed]0.4,1) .. (0,2) .. (-2,3) 
                            .. (-4.8,0) .. (-2,-3) 
                            .. (0,-2) .. (0.4,-1) 
                            .. (0,0) .. (-0.4,1) 
                            .. (0,2) .. (2,3) 
                            .. (4.8,0) .. (2,-3) 
                            .. (0,-2) .. (-0.4,-1) .. (0,0);
        \end{knot}
    \end{tikzpicture}}
\end{document}

趣味と結び目の正しい使い方

関連情報