
Warum platziert der folgende Tikz-Code die Pfeilspitze dort, wo sie platziert ist?
\documentclass[border=5pt, tikz]{standalone}
\usetikzlibrary{arrows.meta, bending}
\begin{document}
\begin{tikzpicture}
\draw[-Latex, double] (0:0.5) arc (0:180:0.5);
\end{tikzpicture}
\end{document}
Ich erhalte das erwartete Verhalten, wenn ich die Doppellinie entferne, die bending
Bibliothek entferne oder die Standardpfeilspitze latex
anstelle der Latex
Pfeilspitze von verwende arrows.meta
.
Die Kombination dieser drei Funktionen scheint jedoch irgendwie zu scheitern. Gibt es eine Möglichkeit, alle drei zusammenarbeiten zu lassen?
Antwort1
tl;dr
Definieren Sie das folgende Makro neu, indem Sie zwei neue Zeilen hinzufügen:
\documentclass[border=5pt,tikz]{standalone}
\usetikzlibrary{arrows.meta,bending}
\begin{document}
\makeatletter
\def\pgf@draw@curved#1#2{%
% Prepare:
{%
\pgf@xc\pgf@xb % <--- adding new line
\pgfarrows@getid{#1}{#2}%
\pgf@xb\pgf@xc % <--- adding new line
% Do shift:
\expandafter\expandafter\expandafter\pgf@arrow@drawer@rigid@shift\csname pgf@ar@ends@\pgf@arrow@id\endcsname%
\expandafter\let\expandafter\pgf@arrow@bending@mode\csname pgf@ar@bending@mode@#1\endcsname%
\ifx\pgf@arrow@bending@mode\pgfutil@empty\let\pgf@arrow@flex@mode\pgf@arrow@mode@is@flex\fi%
% do swap:
{%
\csname pgf@ar@saves@\pgf@arrow@id\endcsname%
\ifcase\pgf@arrow@flex@mode\relax%
\expandafter\expandafter\expandafter\pgf@arrow@drawer@rigid\csname pgf@ar@visual@\pgf@arrow@id\endcsname% like flex
\or%
\expandafter\expandafter\expandafter\pgf@arrow@drawer@rigid\csname pgf@ar@visual@\pgf@arrow@id\endcsname%
\or%
\expandafter\expandafter\expandafter\pgf@arrow@drawer@rigid\csname pgf@ar@ends@\pgf@arrow@id\endcsname%
\or%
\pgf@arrow@drawer@bend%
\fi%
% hull points inside the above
}%
\expandafter}%
% Transform to next tip:
\expandafter\pgf@xb\the\pgf@xb%
}
\def\pgf@arrow@drawer@rigid@shift#1#2#3{% tip end, back end, line end, sep
% Let xa be the actual back end of the current arrow plus the back end:
\advance\pgf@xb by#2%
\pgf@xa\pgf@xb%
% Update the xb:
\pgf@x#1%
\advance\pgf@x by\pgfarrowsep%
\advance\pgf@xb by-\pgf@x%
}
\def\pgf@arrow@drawer#1#2{%
% Prepare:
{%
\pgfarrows@getid{#1}{#2}%
% Do shift:
\expandafter\expandafter\expandafter\pgf@arrow@drawer@shift\csname pgf@ar@ends@\pgf@arrow@id\endcsname%
% Do slant:
\ifdim\pgfarrows@slant pt=0pt%
\else%
\pgftransformxslant{\pgfarrows@slant}%
\fi%
% do swap:
\ifpgfarrowswap%
\pgftransformyscale{-1}%
\fi%
{%
\csname pgf@ar@saves@\pgf@arrow@id\endcsname%
\pgfscope%
\pgf@arrows@color@setup%
\pgflowlevelsynccm\csname pgf@ar@cache@\pgf@arrow@id\endcsname%
\endpgfscope%
\pgf@arrows@rigid@hull%
}%
\expandafter}%
% Transform to next tip:
\expandafter\pgftransformxshift\expandafter{\the\pgf@xc}%
}
\def\test#1{\tikz\draw[double,-{#1}](1,0)..controls(1,1)and(0,1)..(0,0);}
\test{Rectangle[length=1,width=5,black]
Rectangle[length=2,width=4,black!80]
Rectangle[length=3,width=3,black!60]
Rectangle[length=4,width=2,black!40]
Rectangle[length=10,width=1,black!20]}
\test{latex[]}
\test{Straight Barb}
\test{Hooks}
\test{Arc Barb}
\test{Tee Barb}
\test{Classical TikZ Rightarrow}
\test{Computer Modern Rightarrow}
\test{Implies}
\test{Latex}
\test{Stealth}
\test{Kite}
\test{Square}
\test{Circle}
\test{Round Cap}
\test{Butt Cap}
\test{Triangle Cap}
\test{Fast Triangle}
\test{Fast Round}
\test{Rays}
\end{document}
Längere Geschichte
Die Dimension \pgf@xb
wird verwendet, um die Positionen der Pfeilspitzen zu speichern. Aus irgendeinem Grund wird sie jedoch durch etwas in überschrieben \pgfarrows@getid
.
Ein Workaround besteht darin, \pgf@xc
zum Erinnern zu verwenden \pgf@xb
und anschließend zu reparieren \pgf@xb
. \pgfarrows@getid
Man kann jedes beliebige Dimensionsregister verwenden. Langfristig ist es jedoch besser, eine neue Dimension zu deklarieren.
Noch längere Geschichte
Warum bending
Bibliothek
Ohne bending
Bibliothek wird das Xshift außerhalb der Gruppe durchgeführt, was \pgfarrows@getid
alles ruiniert. Das heißt, das Überschriebene \pgf@xb
wird gelöscht, wenn die Gruppe beendet wird, sodass das Richtige \pgf@xb
verwendet wird. (siehe \pgf@arrow@drawer
. Dies ist die Originalversion von \pgf@draw@curved
.)
Da die Bibliothek jedoch bending
drei Modi einführt, die eine unterschiedliche Behandlung von Xshift erfordern, wird Xshift in dem ausgeführt, \ifcase
das in der Gruppe liegt, wo \pgfarrows@getid
alles ruiniert wird.
Warum sind manche Pfeilspitzen immun?
Einige Pfeilspitzen sind Duplikate der Pfeile, die wir im Mathematikmodus verwenden. Diese Pfeile sind unabhängig von PGF/TikZs Parameter. Kurz gesagt: latex
eine Instanz.
Für Pfeilspitzen wie sind einige Berechnungen auf PGF/Ti erforderlich Latex
.\pgfarrows@getid
kDie Parameter von Z. Genauer gesagt müssen sie ausgeführt werden \pgfarrowslinewidthdependent
.
Warum double
?
Denn wenn double
verwendet wird, wird die Berechnung \pgfarrowslinewidthdependent
noch komplexer und \pgf@xb
überschrieben!
Antwort2
Wenn Sie die bending
Bibliothek laden, wird die Standardmethode zum Zeichnen von Pfeilspitzen von quick
in geändert flex
. flex
ist rechenintensiver als quick
, aber weniger aufwendig als bend
und liefert normalerweise bessere Ergebnisse. Aber nicht immer. Sie können die quick
Standardeinstellung wiederherstellen, indem Sie sie explizit angeben:
\documentclass[border=5pt, tikz]{standalone}
\usetikzlibrary{arrows.meta, bending}
\begin{document}
\begin{tikzpicture}
\draw[-Latex, double] (0:0.5) arc (0:180:0.5);
\scoped[yshift=10mm]{\draw[-{Latex[quick]}, double] (0:0.5) arc (0:180:0.5);}
\end{tikzpicture}
\end{document}
Keine der drei Methoden führt jedoch zu großartigen Ergebnissen – das quick
passiert einfach dem besten der verfügbaren Übel.