当 tikz 图片包含其他 tikz 图片时,节点名称发生冲突

当 tikz 图片包含其他 tikz 图片时,节点名称发生冲突

我为大量小图构建了tikz图片,并赋予了它们宏名。我希望能够使用定义的结构构建更复杂的图片。但是,单个小图中的节点名称与大图中的节点名称冲突。这是一个人为的例子

\def\LL{\begin{tikzpicture}\node (n0) at (0,0) {0}; \node (n1) at (-1,1) {L};\draw(n0) to (n1); \end{tikzpicture}}
\def\RR{\begin{tikzpicture}\node (n0) at (0,0) {0}; \node (n1) at (1,1) {R};\draw(n0) to (n1); \end{tikzpicture}}



\begin{tikzpicture} \node (n0) at (0,0)  {\LL};  \node (n1) at (5,0) {\RR};
\draw (n0) to (n1);
\end{tikzpicture}

这给出了一幅图像,其中 final\draw (n0) to (n1);使用错误的节点坐标。我通过保留和不变但改变外图中节点的名称
来获得我需要的结果,这样就变成了\def\LL\def\RR

\begin{tikzpicture} \node (m0) at (0,0)  {\LL};  \node (m1) at (5,0) {\RR};
\draw (m0) to (m1);
\end{tikzpicture}

tikzpicture如果它们像一个纯粹的程序一样运行而没有副作用,那么一切都会很好。

答案1

tikzpicture不支持嵌套s。句号。

如果它有效,那么根据你的绝望程度和观点,你要么幸运要么不幸。不幸是因为如果它有效,你可能会继续使用该方法,并且你可能认为你现有的代码应该继续工作。也就是说,最终你可能会承受更多的痛苦,尽管现在痛苦少了。幸运的是,如果你现在真的需要它工作,而不在乎它下周是否有效。

无论命名冲突等如何,它都根本不受支持。

根据具体情况,您可能有 2 个选择。

首先,让每个带有小图片的宏都使用一个框。从你所说的来看,我强烈推荐这种方法。它既简单又编译时间更快。

\newsavebox\LLbox
\sbox\LLbox{\begin{tikzpicture}\node (n0) at (0,0) {0}; \node (n1) at (-1,1) {L};\draw(n0) to (n1); \end{tikzpicture}}
\newcommand*\LL{\usebox{\LLbox}}

其次,使用pics。我只会在您需要比 MWE 建议的更多的灵活性时才使用这个。否则,它会涉及不必要的麻烦,并且会不必要地变慢,而没有任何好处。

\tikzset{%
  LL/.pic={
    \node (n0) at (0,0) {0};
    \node (n1) at (-1,1) {L};
    \draw (n0) to (n1);
  }
}
\begin{tikzpicture}
  \pic at (0,0) {LL};
\end{tikzpicture}

我认为这个方法可行。如果你发布了可用的代码,我会测试它。但是你没有,所以我不能不先完成它,而我现在没有时间。

pic您可以绕过 a不是 a的事实node,这样您就可以连接一个命名的东西,如果这很重要的话。但是,不要使用手册中的方法,因为pics 目前有很多错误,命名已经被破坏了一段时间。(它以前可以工作,所以也许它会再次工作,但现在不行了。)

答案2

不要使用宏,而要使用保存框。

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\sbox0{\begin{tikzpicture}\node (n0) at (0,0) {0}; \node (n1) at (-1,1) {L};\draw(n0) to (n1); \end{tikzpicture}}
\sbox1{\begin{tikzpicture}\node (n0) at (0,0) {0}; \node (n1) at (1,1) {R};\draw(n0) to (n1); \end{tikzpicture}}

\begin{tikzpicture} \node (n0) at (0,0)  {\usebox0};  \node (n1) at (5,0) {\usebox1};
\draw (n0) to (n1);
\end{tikzpicture}
\end{document}

答案3

pics正如 cfr 已经提到的,如果您想用tikzpicture多个简单的组件组成一个复杂的组件,最好使用它。

您的命令可以转换为picsPics可以有一个名称,该名称将节点添加到其中。 以下示例显示了如何在复杂图形中使用包含节点的两个图片-right,而不会与节点名称产生冲突:-left

\documentclass[tikz,border=2mm]{standalone}

\begin{document}

\begin{tikzpicture}[%
    circles/.pic={%
        \node[circle, draw, minimum size=1cm, fill] (-right) at (1,0) {-right};
        \node[circle, draw, minimum size=1cm, fill] (-left) at (-1,0) {-left};
        \draw (-right)--(-left);
    },
    boxes/.pic={%
        \node[draw, minimum size=1cm, fill] (-right) at (1,0) {-right};
        \node[draw, minimum size=1cm, fill] (-left) at (-1,0) {-left};
        \draw (-right)--(-left);
    }]

\draw[fill=white, red, fill=orange] pic (A) at (0,0) {circles};

\draw[line width=2pt, red, fill=orange] pic (B) at (0,1.5) {boxes};

\draw[red] (B-left) to[out=60,in=120] (B-right);
\draw[blue] (A-left) to[out=60,in=-120] (B-right);

\end{tikzpicture}

\end{document}

enter image description here

更新使用name prefix

避免使用的另一种选择picsname prefix

此键的值是当前范围内每个节点的前缀。这包括节点的命名(通过 name 键或通过隐式 (hnamei) 语法)以及节点的任何引用。在范围之外,可以(并且需要)使用由前缀和节点名称组成的“全名”来引用节点。

您可以将宏从 转换tikzpicturesscopesname prefix传递到相应范围的参数将为节点名称添加前缀,并且所有节点都将具有不同的名称。

适用于您的示例的解决方案可能是:

\documentclass[tikz,border=2mm]{standalone} 
\usetikzlibrary{positioning}

\newcommand{\LL}[1]{%
\begin{scope}[#1]
\node (n0) at (0,0) {0}; \node (n1) at (-1,1) {L}; \draw(n0) to (n1);
\end{scope}
}

\newcommand{\RR}[1]{%
\begin{scope}[#1]
\node (n0) at (0,0) {0}; \node (n1) at (1,1) {L}; \draw(n0) to (n1);
\end{scope}
}

\begin{document}
\begin{tikzpicture}

 \LL{name prefix=First-}

 \RR{shift={(5,0)}, name prefix=Second-}

 \draw (First-n0) to (Second-n1);

\end{tikzpicture}
\end{document}

enter image description here

相关内容