
Почему следующий код tikz размещает наконечник стрелки именно там, где он должен быть?
\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}
Я получаю ожидаемое поведение, если удаляю двойную линию, удаляю библиотеку bending
или использую стандартный latex
наконечник стрелки вместо наконечника Latex
стрелки из arrows.meta
.
Однако каким-то образом сочетание этих трех функций, похоже, нарушается. Есть ли способ заставить все три работать вместе?
решение1
вкратце
Переопределите следующий макрос, добавив две новые строки:
\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}
Более длинная история
Измерение \pgf@xb
используется для запоминания положений наконечников стрелок. Но по какой-то причине оно перезаписывается чем-то в \pgfarrows@getid
.
Так что обходной путь — использовать \pgf@xc
to remember \pgf@xb
, а затем repair \pgf@xb
after \pgfarrows@getid
. Можно использовать любой регистр размерности, который нравится. Однако лучше объявить новую размерность в долгосрочной перспективе.
Еще более длинная история
Почему bending
библиотека
Без bending
библиотеки xshift выполняется вне группы, где \pgfarrows@getid
все рушится. То есть перезаписанное умирает, когда группа завершается, поэтому используется \pgf@xb
правильное . (см . . Это оригинальная версия .)\pgf@xb
\pgf@arrow@drawer
\pgf@draw@curved
Однако, поскольку bending
библиотека вводит три режима, которые требуют различной обработки xshift, xshift выполняется в , \ifcase
который лежит в группе, где \pgfarrows@getid
все портит.
Почему некоторые наконечники стрел невосприимчивы?
Некоторые наконечники стрелок дублируют те, что мы используем в математическом режиме. Эти стрелки не зависят от PGF/TiкПараметры Z. Короче говоря: latex
пример.
Для наконечников стрел, таких как Latex
, их\pgfarrows@getid
требуются некоторые расчеты по PGF/TiкПараметры Z. Если быть точным, то им нужно запустить \pgfarrowslinewidthdependent
.
Почему double
?
Потому что при double
использовании вычисление \pgfarrowslinewidthdependent
становится еще более сложным и \pgf@xb
перезаписывается!
решение2
При загрузке bending
библиотеки метод по умолчанию для рисования наконечников стрелок меняется с quick
на flex
. flex
является более вычислительно затратным, чем quick
, но менее затратным, чем bend
, и обычно дает лучшие результаты. Но не всегда. Вы можете восстановить метод quick
по умолчанию, указав его явно:
\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}
Однако ни один из трех методов не дает хороших результатов — quick
просто происходит лучшее из возможных зол.