TikZ:嵌套“pic”中的命名节点

TikZ:嵌套“pic”中的命名节点

我正在使用新的 TikZ/PGF 3.0pic功能。我大量使用它们,包括在另一张图片中使用一张图片。问题是 Tikz 有时找不到嵌套图片的节点名称。

我期望以下操作能够起作用:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}
\tikzset{complex/.pic={
  \node(re) {re};
  \node[right=0mm of re](im) {im};
}}
\tikzset{su3v/.pic={
  \path pic(c0) {complex};
  \path pic[right=1mm of c0im](c1) {complex};
  \path pic[right=1mm of c1im](c2) {complex};
}}
\tikzset{spinor/.pic={
  \path pic(v0) {su3v};
  \path pic[below=2mm of v0c2re](v1) {su3v};
  \path pic[below=2mm of v1c2re](v2) {su3v};
  \path pic[below=2mm of v2c2re](v3) {su3v};
}}

\path pic {su3v};       % Works
\path pic(name) {su3v}; % ! Package pgf Error: No shape named namec0im is known.
\path pic {spinor};     % ! Package pgf Error: No shape named v0c1im is known.
\end{tikzpicture}
\end{document}

这里有什么问题?

答案1

我要去漏洞在这一点上。

绘制 时pic,可以使用子节点(和坐标)。如果为 outerpic指定了名称,则该名称将作为前缀传递给所有子节点(和坐标)。这是一件好事,因为这意味着您不会冒名称冲突的风险。您正在嵌套pics,因此名称应该累积。我们可以将嵌套和命名绘制为一棵树,说明應該发生。name是当前 的名称picprefix是所有 的指定前缀图片。

pic {su3v};                    <no prefix>   <no name>
 |
 -- pic (c0) {complex}          c0            c0
     |
     -- node (re) {re}                        c0re
     -- node (im) {im}                        c0im

pic (name) {su3v};              name          name
 |
 -- pic (c0) {complex}          namec0        namec0
     |
     -- node (re) {re}                        namec0re
     -- node (im) {im}                        namec0im

pic {spinor};                  <no prefix>   <no name>
 |
 -- pic (v0) {su3v}             v0            v0
     |
     -- pic (c0) {complex}      v0c0          v0c0
         |
         -- node (re) {re}                    v0c0re
         -- node (im) {im}                    v0c0im

(对于那些不熟悉这一点的人来说,我们的想法是,要引用节点,我们使用全名减去当前前缀。所以在里面su3v我们可以像你一样引用c0imc1im,即使su3v被命名或在里面使用spinor。)

现在,我说的是應該发生。它没有。实际上发生的是,当 apic开始时,然后name prefix現在全名设置它是前缀。也就是说,本身name prefix有一个前缀,并且该前缀是满的当前的名称pic。关键是该名称具有已经附加了自己的前缀。

因此,当嵌套pics 时,会发生以下情况。第一个命名的pic,我们称之为outer,将 的前缀设置name prefix为其名称,在本例中为outer。因此,每当name prefix被调用时,outer都会将 添加到其值的前缀中。在 内部outer,我们假设有另一个pic,比如inner。由于这在 内部outer,因此其真实名称为outerinnername prefix的前缀设置为此,但name prefix其本身保留其 的值outer。因此有效name prefix的是outerinnerouter。因此实际的树如下:

pic {su3v};                    <no prefix>   <no name>
 |
 -- pic (c0) {complex}          c0            c0
     |
     -- node (re) {re}                        c0re
     -- node (im) {im}                        c0im

pic (name) {su3v};              name          name
 |
 -- pic (c0) {complex}          namec0name    namec0
     |
     -- node (re) {re}                        namec0namere
     -- node (im) {im}                        namec0nameim

pic {spinor};                  <no prefix>   <no name>
 |
 -- pic (v0) {su3v}             v0            v0
     |
     -- pic (c0) {complex}      v0c0v0        v0c0
         |
         -- node (re) {re}                    v0c0v0re
         -- node (im) {im}                    v0c0v0im

此时我应该提到一个有用的诊断。这是将以下内容放入您的序言中:

\makeatletter
\tikzset{show fig name/.code={\tikz@addmode{\message{Fig name is: |\tikz@fig@name|}}}}
\makeatother

然后show fig name在各种元素上使用该键。

我想这一点是如果你手动然后name prefix你想保留它并附加所有自动前缀。如果你从不这样做,一个解决方法是将代码复制\def\tikz@subpicture@handle@到你的序言中(在强制\makeatletter .. \makeatother配对之间)并更改

  \ifx\tikz@fig@name\pgfutil@empty\else%
    \tikzset{name prefix/.prefix/.expanded=\tikz@fig@name}%
  \fi%

  \ifx\tikz@fig@name\pgfutil@empty\else%
    \tikzset{name prefix/.expanded=\tikz@fig@name}%
  \fi%

更好的解决方案是,不使用\tikz@fig@name,而是使用已声明名称(目前尚未保存 - 前缀和后缀是在节点/图片/坐标首次命名时添加的)并将其添加为后缀字首name prefix。也就是说,关键的一行可能是:

\tikzset{name prefix/.prefix/.suffix/.expanded=\tikz@fig@declaredname}

name密钥必须是:

\tikzset{
  name/.code={\edef\tikz@fig@name{\tikz@pp@name{#1}}\edef\tikz@fig@declaredname{#1}}%
 }

不幸的是,嵌套/.prefix/.suffix不起作用,因此必须等待 PGF 人员找出一个好的解决方案才能进行适当的修复。与此同时,如果您从不调用name prefix自身,那么修改\tikz@subpicture@handle@似乎有效。

但没有保证。


其实,我刚刚想到了一个替代解决方案。那就是 name prefix/.prefix到 ,\tikz@fig@name就像原始代码一样,但随后 会自行清除,name prefix因为无论当前name prefix是什么,它都已在 中考虑在内\tikz@fig@name。进一步调用name prefix将保持前缀 到 的name prefix预期。

此外,我将此问题提交到 PGF 错误列表并附有此处的链接。

相关内容