我阅读了 PGF 3.0.0 手册中有关如何使用 \pic 的说明,但关于如何为 \pic 命名的描述对我来说并不清楚,并且给出的示例产生了错误:“没有已知的名为 EmmaEmma-left 的形状。”
手册中的示例(第 255 页):
\documentclass[tikz,border=3mm]{standalone}
\tikzset{
seagull/.pic={
% Code for a "seagull". Do you see it?...
\coordinate (-left wing) at (-3mm,0);
\coordinate (-head) at (0,0);
\coordinate (-right wing) at (3mm,0);
\draw (-left wing) to [bend left] (0,0) (-head) to [bend left] (-right wing);
}
}
\begin{document}
\begin{tikzpicture}%\small\sffamily
\pic (Emma) {seagull};
\pic (Alexandra) at (0,1) {seagull};
\draw (Emma-left wing) -- (Alexandra-right wing);
\end{tikzpicture}
\end{document}
上面的例子中显然缺少了一些东西。请告诉我我遗漏了什么。
答案1
这是一种解决方法,而不是解决方案。我想知道这是否是一个错误,但我对此的理解tikz
还不足以确定。
显然,tikz
不再喜欢to
图片中这里的操作的某些内容。
tikz
在这次行动中似乎正在做的事情\draw... to..
是加倍前缀,以便查找EmmaEmma-left wing
显然不存在的前缀。显然,如果您用直线替换命令,它就不会这样做。
您可以通过将 pic 前缀暂时重置为 pic 之外的值,然后将 pic 的名称作为选项传递,使示例正常工作。显然,这是非常笨拙的,绝对不需要。所以,要么这是一个错误,要么就是有什么东西盯着我,而我只是没有看到它。(毕竟,这基本上是手册中的逐字逐句。所以它应该可以工作!)
\documentclass[tikz,border=3mm]{standalone}
\tikzset{
seagull/.pic={
% Code for a "seagull". Do you see it?...
\coordinate (-left wing) at (-3mm,0);
\coordinate (-head) at (0,0);
\coordinate (-right wing) at (3mm,0);
\draw [name prefix ..] (#1-left wing) to [bend left] (0,0) (#1-head) to [bend left] (#1-right wing);
}
}
\begin{document}
\begin{tikzpicture}%\small\sffamily
\pic (Emma) at (0,0) {seagull=Emma};
\pic (Alexandra) at (0,1) {seagull=Alexandra};
\draw (Emma-left wing) -- (Alexandra-right wing);
\end{tikzpicture}
\end{document}
答案2
我稍微挖掘了一下,发现了以下内容:
当 Ti钾Z 遭遇\draw(A)to(B)
,这就是将要发生的事情
\def\tikztostart{\tikz@pp@name{A}}
;通常这只是A
;\def\tikztotarget{\tikz@pp@name{B}}
;通常这只是B
;- 在这里应用
every to/.code
。
在最简单的情况下,to
仅仅是--
,所以 Ti钾Z 现在执行
\draw(\tikztostart)--(\tikztotarget);
请记住,这相当于
\draw(A)--(B);
所以一切都很好。
然而,在 中.pic
,节点名称有前缀和后缀。在这种情况下,假设图片是 名称Emma
,
\tikztostart
是EmmaA
;\tikztotarget
是EmmaB
;- 钛钾泽塞库特
\draw(\tikztostart)--(\tikztotarget);
这相当于
\draw(EmmaA)--(EmmaB);
当 Ti钾Z 尝试解析此节点名称,再次添加前缀(和后缀)。最后你会看到它找不到EmmaEmmaA
。
附录
在tikz.code.tex
第 5157 行
\def\tikz@shapeborder@name{\tikz@pp@name{#2}}%
同一文件,第 2969-2975 行
\def\tikz@to@use@last@coordinate{%
\iftikz@shapeborder%
\edef\tikztostart{\tikz@shapeborder@name}%
\else%
\edef\tikztostart{\the\tikz@lastx,\the\tikz@lasty}%
\fi%
}
以我个人拙见,应该修正 的定义tikztostart
。
答案3
这确实是一个错误,但是由于不同的原因,我认为这是在解析完成时在同一位置发生的,\tikz@subpicture@handle@
但我仍然不完全理解它是如何出错的。
当 TikZ 开始解析 pic 代码中的最后一个\draw
命令并遇到节点名称时,名称前缀已经设置。但它解析的对象是一个节点(坐标也是节点),因此它开始思考嘿,我得给这个引用加个前缀。因此,另一个节点name prefix
被触发并寻找该形状。据我所知,最简单的解决方法是引用显式坐标,以避免节点名称解析,例如;
\documentclass[tikz]{standalone}
\tikzset{
seagull/.pic={
% Code for a "seagull". Do you see it?...
\coordinate (-left wing) at (-3mm,0);
\coordinate (-head) at (0,0);
\coordinate (-right wing) at (3mm,0);
\draw (-left wing.center) to [bend left] (0,0) (-head.center) to [bend left] (-right wing.center);
}
}
\begin{document}
\begin{tikzpicture}
\pic (Emma) {seagull};
\pic (Alexandra) at (0,1) {seagull};
\draw (Emma-left wing) -- (Alexandra-right wing);
\end{tikzpicture}
\end{document}
编译后得到的结果与 cfr 的图片相同。确实很奇怪。但我认为补救起来没那么简单。也可能是节点名称解析出错了,但我没有检查。
我尝试读取名称前缀,看看它是否与节点名称匹配,如果匹配则跳过它,但没有成功。我认为这是 Till Tantau 需要修复的。