
¿Por qué el siguiente código tikz coloca la punta de la flecha donde lo hace?
\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}
Obtengo el comportamiento esperado si elimino la línea doble, elimino la bending
biblioteca o uso la latex
punta de flecha estándar en lugar de la Latex
punta de flecha de arrows.meta
.
Sin embargo, de alguna manera la combinación de estas tres características parece romperse. ¿Hay alguna manera de hacer que los tres trabajen juntos?
Respuesta1
tl; dr
Redefina la siguiente macro agregando dos líneas nuevas:
\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}
Historia más larga
La dimensión \pgf@xb
se utiliza para recordar las posiciones de las puntas de las flechas. Pero por alguna razón se sobrescribe con algo en \pgfarrows@getid
.
Entonces, una solución alternativa es usar \pgf@xc
para recordar \pgf@xb
y luego reparar \pgf@xb
después \pgfarrows@getid
. Se puede utilizar cualquier registro de dimensión que se desee. Sin embargo, es mejor declarar una nueva dimensión a largo plazo.
Historia aún más larga
Por que bending
biblioteca
Sin bending
biblioteca, el xshift se realiza fuera del grupo donde \pgfarrows@getid
arruina todo. Es decir, lo sobrescrito \pgf@xb
muere cuando el grupo termina, por lo que \pgf@xb
se utiliza el correcto. (ver \pgf@arrow@drawer
. Esta es la versión original de \pgf@draw@curved
.)
Sin embargo, dado que bending
la biblioteca introduce tres modos que requieren diferentes tratamientos de xshift, xshift se realiza en el \ifcase
grupo que \pgfarrows@getid
arruina todo.
¿Por qué algunas puntas de flecha son inmunes?
Algunas puntas de flecha son duplicados de las que usamos en el modo matemático. Estas flechas son independientes de PGF/Ti.kLos parámetros de Z. En pocas palabras: latex
un ejemplo.
Para puntas de flecha como Latex
, \pgfarrows@getid
implica algunos cálculos en PGF/TikLos parámetros de Z. Para ser específicos, deben ejecutarse \pgfarrowslinewidthdependent
.
Por qué double
?
Porque cuando double
se usa, el cálculo de \pgfarrowslinewidthdependent
se vuelve aún más complejo y \pgf@xb
¡se sobrescribe!
Respuesta2
Cuando carga la bending
biblioteca, el método predeterminado para dibujar puntas de flechas cambia de quick
a flex
. flex
es más costoso computacionalmente que quick
, pero menos costoso que bend
, y generalmente da mejores resultados. Pero no siempre. Puede restaurar el quick
valor predeterminado especificándolo explícitamente:
\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}
Sin embargo, ninguno de los tres métodos da grandes resultados, quick
simplemente ocurre con el mejor de los males disponibles.