附录

附录

我阅读了 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

我稍微挖掘了一下,发现了以下内容:

当 TiZ 遭遇\draw(A)to(B),这就是将要发生的事情

  • \def\tikztostart{\tikz@pp@name{A}};通常这只是A
  • \def\tikztotarget{\tikz@pp@name{B}};通常这只是B
  • 在这里应用every to/.code

在最简单的情况下,to仅仅是--,所以 TiZ 现在执行

 \draw(\tikztostart)--(\tikztotarget);

请记住,这相当于

 \draw(A)--(B);

所以一切都很好。


然而,在 中.pic,节点名称有前缀和后缀。在这种情况下,假设图片是 名称Emma

  • \tikztostartEmmaA;
  • \tikztotargetEmmaB;
  • 泽塞库特\draw(\tikztostart)--(\tikztotarget);

这相当于

\draw(EmmaA)--(EmmaB);

当 TiZ 尝试解析此节点名称,再次添加前缀(和后缀)。最后你会看到它找不到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 需要修复的。

相关内容