tl; dr

tl; dr

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

punta de flecha mal colocada

Obtengo el comportamiento esperado si elimino la línea doble, elimino la bendingbiblioteca o uso la latexpunta de flecha estándar en lugar de la Latexpunta de flecha de arrows.meta.

sin doble líneasin doblarpunta de flecha de látex

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@xbse 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@xcpara recordar \pgf@xby luego reparar \pgf@xbdespué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 bendingbiblioteca

Sin bendingbiblioteca, el xshift se realiza fuera del grupo donde \pgfarrows@getidarruina todo. Es decir, lo sobrescrito \pgf@xbmuere cuando el grupo termina, por lo que \pgf@xbse utiliza el correcto. (ver \pgf@arrow@drawer. Esta es la versión original de \pgf@draw@curved.)

Sin embargo, dado que bendingla biblioteca introduce tres modos que requieren diferentes tratamientos de xshift, xshift se realiza en el \ifcasegrupo que \pgfarrows@getidarruina 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: latexun ejemplo.

Para puntas de flecha como Latex, \pgfarrows@getidimplica algunos cálculos en PGF/TikLos parámetros de Z. Para ser específicos, deben ejecutarse \pgfarrowslinewidthdependent.

Por qué double?

Porque cuando doublese usa, el cálculo de \pgfarrowslinewidthdependentse vuelve aún más complejo y \pgf@xb¡se sobrescribe!

Respuesta2

Cuando carga la bendingbiblioteca, el método predeterminado para dibujar puntas de flechas cambia de quicka flex. flexes más costoso computacionalmente que quick, pero menos costoso que bend, y generalmente da mejores resultados. Pero no siempre. Puede restaurar el quickvalor 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}

puntas de flecha

Sin embargo, ninguno de los tres métodos da grandes resultados, quicksimplemente ocurre con el mejor de los males disponibles.

información relacionada