4

My first post, so apologies for any etiquette failures. For reasons not worth going into I want to decouple the definition of a whole bunch of tikz nodes from their eventual placement. I'm wanting to have a LaTeX macro define separate .styles for each node, defining their contents, names etc. (and other stuff but skipped in this MWE). However, I'm having a problem getting the node naming to work. The attached MWE appears to work at face value, but if I then uncomment the \draw command on the third line from the end I get

ERROR: Package pgf Error: No shape named A is known.

I tried replacing name=\nodename with a similar pgfkeys invocation construct to the one I used to get the "node contents" part working but then I got a TeX capacity exceeded.

Any pointers would be much appreciated. Apologies if the answer is readily found elsewhere and I missed it.

\documentclass[tikz]{standalone}

\newcommand{\nodename}{}
\pgfkeys{mine/.cd, name/.store in=\nodename}

\newcommand{\makenodetype}[1]{%
  \pgfkeys{mine/.cd,#1}
  \tikzset{\nodename/.style={%
      name=\nodename,
      rectangle,
      draw,
      node contents={\pgfkeys{mine/.cd,#1}\nodename}}}}

\makenodetype{name=A}
\makenodetype{name=B}

\begin{document}
\begin{tikzpicture}
\node at (0,0) [A];
\node at (1,0) [B];
% \draw (A) -- (B);
\end{tikzpicture}
\end{document}
  • Welcome to TeX.SX! You can highlight in-line code in your post using back-ticks. – Andrew May 5 '17 at 6:09
  • its working for me without any error. @Nathaniel Livesey – Biki Teron May 5 '17 at 6:12
  • Thanks for checking. Does that including when you re-enable the \draw command on the third line from the end? – Nathaniel Livesey May 5 '17 at 6:14
  • Not really I'm afraid. Your solution returns to the typical tikz approach I know and love. What I'm trying to do, which I grant may be perverse, is to hide as much stuff away in the [] arguments, including both the node name and its contents. The goal of ultimate having a single style invocation as in my example. I want to be able to define a whole bunch of complex nodes in one part of the source code, then place and connect them in a different part of the code. I'll want to do the placing/connecting several different times with different levels of detail hence this approach. – Nathaniel Livesey May 5 '17 at 6:25
3

The problem here is that \nodename is not expanded when the style is defined, so when name=\nodename is executed it just uses whatever value is in \nodename when the style is used. So there is never a shape named A, because when the A style is executed \nodename is defined as B.

By putting \makenodetype{name=B} in between the the \node commands the example works. But this is not a very convenient way of working and while it is possible to use \expandafter, or an extra helper macro or two, it is worth nothing that the whole thing can be done with keys:

\documentclass[tikz,border=5]{standalone}
\tikzset{%
  my node/.style={
    shape=rectangle,
    draw,
    name=#1,
    node contents=#1
  },
  declare my node/.style={
    #1/.style={my node=#1}
  }
}
\tikzset{
  declare my node=A,
  declare my node=B
}
\begin{document}
\begin{tikzpicture}
\node at (0,0) [A];
\node at (1,0) [B];
\draw (A) -- (B);
\end{tikzpicture}
\end{document}

enter image description here

  • Thanks Mark, let me work with that (probably tomorrow at this point). I forgot to mention, if I have a second (non pgfkeys-based) argument to my \makenodetype macro and use that (#2) to define the name it works (and your answer seems to take a similar approach from the quick look). However (and I realize I didn't make this clear), I'm using pgfkeys here because in my non-MWE I plan to have many more arguments. – Nathaniel Livesey May 5 '17 at 6:31
  • Mark, how does this work? Is the magic the use of declare? I see that there is a /tikz/graphs/declare in the manual but nothing else... – Andrew May 5 '17 at 6:43
  • @Andrew the (arbitrarily named) key declare my node takes one argument (e.g., A) and simply creates a style key with the name of that argument (note that in my node=#1 the #1 is the argument to the outer declare my node key). When that style is called from the \node command, it executes the my node style key with the argument A, and my node then executes its options with A as its argument. – Mark Wibrow May 5 '17 at 7:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.