
Ich zeichne ein Knotendiagramm und verwende den \clip
Befehl, um die Bereiche zu schattieren. Es scheint jedoch, dass der \strand
Befehl der knot
Umgebung einen seltsamen Effekt hat \clip
.
Das richtige Ergebnis sollte beispielsweise lauten (nennen wir esDiagramm 1):
welches erzeugt wird durch
% 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}
Beachten Sie, \clip
dassVor \strand
.
Wenn ich jedoch die Reihenfolge des Codefragments ändere, das \clip
und enthält \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}
Das Ergebnis ist (nennen wir esDiagramm 2):
Wie man sieht, passt die Schattierung nicht in die Kurve.
Auch wenn ich den Code zum Generieren verwendeDiagramm 1(wobei \clip
vor steht ), würde der Fehler immer noch auftreten, wenn vor dem Code \strand
andere Befehle stehen . Dies kann man sehen, indem man den Code wiederholt für\strand
\clip
Diagramm 1zweimal:
\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}
Man kann deutlich sehen, dass sie, obwohl sie von derDasselbeTikZ-Codes, die Ergebnisse sind nicht dieselben.
Könnte mir jemand erklären, was los ist undWie kann ich das beheben?? Dank im Voraus.
Antwort1
Bei etwas weiteren Tests stellt sich heraus, dass dies weder in noch ein Fehler ist hobby
, knots
sondern ein „Feature“ ihrer Interaktion, das wahrscheinlich irgendwo dokumentiert werden sollte.
Um eine geschlossene Hobbykurve zu erstellen, können Sie Folgendes eingeben:
\draw[closed] (0,0) .. (1,1) .. (0,2) .. (-1,1) .. (0,0);
und closed
gibt an, dass die Kurve als geschlossene Kurve zu betrachten ist und nicht als eine Kurve, deren Endpunkte zufällig am selben Punkt liegen ( hobby
weitere Informationen zum Unterschied finden Sie in der Dokumentation).
Jetzt ist die Option closed
des \draw
Befehls etwas fehl am Platz, da TikZ zu diesem Zeitpunkt nicht weiß, dass eine Hobbykurve unterwegs ist. Wir müssen diesen Befehl also speichern und effektiv sagen: „Wende dies auf die nächste Hobbykurve an, die du findest.“ Schließlich könnte sich auf dem Weg einiges Nicht-Hobby-Zeug befinden, bevor die Hobbykurve erstellt wird.
Das ist normalerweise alles gut und schön und die einfachste Möglichkeit, anzugeben, dass eine Hobbykurve geschlossen sein soll. Manchmal benötigen wir jedoch eine feinere Kontrolle, beispielsweise wenn wir zwei Hobbykonstruktionen im selben Pfad verwenden. In dieser Situation können wir die closed
Option einer Koordinate im Hobbypfad hinzufügen. So würde jede der folgenden Optionen denselben Pfad wie oben zeichnen:
\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);
Im zweiten und dritten Schritt weiß TikZ, dass es einen Hobbypfad erstellt und kann daher sagen: „Gut, wir schließenDasPfad.". Im ersten wurde die Hobby-Konstruktion nicht ausgelöst (was beim ersten passiert ..
), alsoDas closed
heißt immer noch „Wenden Sie dies auf den nächsten Hobbypfad an.“. Aber das ist eine kleine Formalität.
Sobald Optionen auf einen Hobbypfad angewendet werden, sei es aus einer früheren Stileinstellung oder aus Optionen, die aus den Koordinaten gesammelt wurden, dannsind gelöscht(und global). Wenn beim Clearing etwas schief geht, dann gibt es einen Stil, clear next Hobby path options
mit dem manGewaltLöschen Sie die Optionen.
Es verhält sich also hobby
so, wie es sollte.
Kommen wir zu knots
. Wenn Sie einen Strang definieren (über \strand
), dann wird der Pfad verwendeteine Menge. Wenn nichts anderes, wird es verwendet, um den Strang selbst zu zeichnen und dann Teile aus den Strängen auszuschneiden, über die es geht (so wird der Strang für jede Kreuzung neu gezeichnet). Die Dinge werden noch schlimmer, wenn der Schlüssel consider self intersections
verwendet wird, weil dies erfordert, den Strang in Komponenten aufzuteilen und jede davon separat zu betrachten. Der Strang wird also gezeichnetoft.
Jedes Mal, wenn es gezeichnet wird, muss es gestaltet werden. So \strand
speichert seine Stiloptionen und ruft sie jedes Mal erneut auf, wenn der Strang gezeichnet wird. Normalerweise ist das genau das, was benötigt wird. Aber Optionen, die dasKonstruktiondes Pfades werden hier nicht benötigt, da der Pfad bereits erstellt wurde. Normalerweise spielt dies keine Rolle – solche Optionen werden normalerweise verworfen.
Aber nicht die closed
Option für Hobbypfade. Da es sich hier um einen Befehl mit verzögerter Aktion handelt, wartet er auf den nächsten Hobbypfad. Der Hobbypfad, den es wargemeintdenn es wurde erstellt und bearbeitet. Also wartet es sehr geduldig auf das nächste. Und da dieses nächste nicht geschlossen werden soll, erleben Sie die Überraschung, dass es doch passiert ist.
Okay, nun zu den Lösungen. Die einfachste und meiner Meinung nach beste Lösung besteht darin, closed
von der \strand
zu einer der Koordinaten zu verschieben.
\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);
Eine Alternative wäre, den Schlüssel clear next Hobby path options
vor den Pfad zu setzen, der durcheinandergebracht wird. Das erscheint mir nicht ganz so elegant, aber ich erwähne es als Alternative.
Man könnte argumentieren, dass beim Starten eines Pfads die Optionen gelöscht werden sollten, sodass jeder Pfad mit einer leeren Tafel beginnt. Um dies jedoch robust zu machen, müsste ich mich auf einer etwas tieferen Ebene in den TikZ-Bereichsmechanismus einklinken, als ich es bisher mit dem Hobby-Paket getan habe. Das ist also etwas, das ich im Hinterkopf behalten werde, falls ich aus einem anderen Grund einklinken muss, aber vorerst werde ich das auf die lange Bank schieben.
Nachdem das geklärt ist, hier meine empfohlene Lösung:
\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}