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}

enter image description here


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 \draws 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}

enter image description here

Tags:

Nodes

Tikz Pgf