我为大量小图构建了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}}
其次,使用pic
s。我只会在您需要比 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
,这样您就可以连接一个命名的东西,如果这很重要的话。但是,不要使用手册中的方法,因为pic
s 目前有很多错误,命名已经被破坏了一段时间。(它以前可以工作,所以也许它会再次工作,但现在不行了。)
答案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
多个简单的组件组成一个复杂的组件,最好使用它。
您的命令可以转换为pics
。Pics
可以有一个名称,该名称将节点添加到其中。 以下示例显示了如何在复杂图形中使用包含节点的两个图片-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}
更新使用name prefix
避免使用的另一种选择pics
是name prefix
。
此键的值是当前范围内每个节点的前缀。这包括节点的命名(通过 name 键或通过隐式 (hnamei) 语法)以及节点的任何引用。在范围之外,可以(并且需要)使用由前缀和节点名称组成的“全名”来引用节点。
您可以将宏从 转换tikzpictures
为scopes
。name 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}