TiKZ node name prefixes in scopes
Here's a simple hack that redefines the naming code inside the scope to append a prefix. You can't use a .
as a separator though as that would confuse the parser. I've used a space, but you could use something else (some punctuation, such as .
is special, there's a list somewhere here).
\documentclass{article}
%\url{http://tex.stackexchange.com/q/128049/86}
\usepackage{tikz}
\begin{document}
\tikzstyle{vertex}=[circle,draw,fill=black!20]
\makeatletter
\tikzset{%
prefix node name/.code={%
\tikzset{%
name/.code={\edef\tikz@fig@name{#1 ##1}}
}%
}%
}
\makeatother
\begin{tikzpicture}
% ---- Copy 1
\begin{scope}[yshift=-32pt,prefix node name=G1]
\node[vertex] (u) at (0, 0) {u};
\node[vertex] (v) at (0, 0) {v};
\end{scope}
% ---- Copy 2
\begin{scope}[yshift=32pt,prefix node name=G2]
\node[vertex] (u) at (0, 0) {u};
\node[vertex] (v) at (0, 0) {v};
\end{scope}
\draw (G1 u) -- (G2 v);
\end{tikzpicture}
\end{document}
Note that this works both with implicit and explicit naming of nodes (ie via name=<name>
and \node (name) ...
).
Instead of scopes
, with TiKZ 3.0 is possible to use pics
. If a name
is assigned to a pic
, this name acts as name prefix
and is appended before any internal node name.
An example will be more clear than my english:
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
%\tikzstyle{vertex}=[circle,draw,fill=black!20]
\tikzset{vertex/.style={circle, draw, fill=black!20},
myscope/.pic={
\node[vertex] (-u) at (0,0) {u};
\node[vertex] (-v) at (0,1) {v};
}
}
\begin{tikzpicture}
\pic[yshift=-32pt] (G1) {myscope};
\pic[yshift= 32pt] (G2) {myscope};
\draw (G1-u) to[out=30,in=-30] (G2-v);
\draw (G2-u) to[out=210,in=150] (G1-v);
\end{tikzpicture}
\end{document}
Edit: It looks like my answer below is completely unnecessary since TikZ has a standard name prefix
key that acts much the same way as what I wrote (although it doesn't separate with the prefix from the name with spaces).
The manual has this to say about the name prefix
key:
The value of this key is prefixed to every node inside the current scope. This includes both the naming of the node (via the name key or via the implicit (⟨name⟩) syntax) as well as any referencing of the node. Outside the scope, the nodes can (and need to) be referenced using “full name” consisting of the prefix and the node name.
The net effect of this is that you can set the name prefix at the beginning of a scope to some value and then use short and simple names for the nodes inside the scope. Later, outside the scope, you can reference the nodes via their full name:
\tikz { \begin{scope}[name prefix = top-] \node (A) at (0,1) {A}; \node (B) at (1,1) {B}; \draw (A) -- (B); \end{scope} \begin{scope}[name prefix = bottom-] \node (A) at (0,0) {A}; \node (B) at (1,0) {B}; \draw (A) -- (B); \end{scope} \draw [red] (top-A) -- (bottom-B); }
Using built-in functionality is almost certainly the best choice.
Original answer:
Loop Space gave a nice answer that works as long as you don't need to refer to the nodes by their unprefixed names.
For example, if you add a \draw (u) -- (v);
inside each of those scopes, you get the somewhat mysterious error, Package pgf Error: No shape named u is known.
A better option is to change the definition of prefix node name
to not change how names are recorded but to add an alias with the prefix.
\tikzset{
prefix node name/.style={%
/tikz/name/.append style={%
/tikz/alias={#1 ##1}%
}%
}
}
In essence, adding prefix node name=foo
to a scope will cause all name=bar
inside the scope to act as if it were name=bar,alias={foo bar}
.
Here's a modification of Loop Space's example using the above definition of prefix node name
and a slight modification to the picture (so the nodes aren't on top of each other) and with some \draw
s added to show the effect.
\documentclass{article}
\usepackage{tikz}
\tikzstyle{vertex}=[circle,draw,fill=black!20]
\tikzset{
prefix node name/.style={%
/tikz/name/.append style={%
/tikz/alias={#1 ##1}%
}%
}
}
\begin{document}
\begin{tikzpicture}
% ---- Copy 1
\begin{scope}[yshift=32pt,prefix node name=G1]
\node[vertex] (u) at (0, 0) {u};
\node[vertex] (v) at (2, 0) {v};
\draw (u) -- (v);
\end{scope}
% ---- Copy 2
\begin{scope}[yshift=-32pt,prefix node name=G2]
\node[vertex] (u) at (0, 0) {u};
\node[vertex] (v) at (2, 0) {v};
\draw (u) -- (v);
\end{scope}
\draw[->] (G1 u) -- (G2 v);
\end{tikzpicture}
\end{document}