为什么以下 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
来记住\pgf@xb
,然后\pgf@xb
在 之后进行修复\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
只是碰巧使用了最坏的方法。