3

In order to avoid repetitive lines of code, we have\tikzset.

On similar lines , is there a possibility to create nodes with \newcommand.

For example,

Instead of \node[draw=black] (a) at (0,0) {} and \node[draw=black] (b) at (0,5) {} with two node statements , We can use single statement,

\newcommand[2]{\createnode}{\node[draw=black] #1 at #2 {}}

Will this approach work and will the nodes created via this approach be accessible at a later stage?

Also with this approach, how will scope work if we create the same node in two scopes.

Will this work?

Peter Grill
  • 223,288
subham soni
  • 9,673
  • 3
    Sorry, don't mean to be rude, but why don't you try this and ask the follow-up question in case it turns out not to work? Feels like the kind of problem you could try in less time than it takes for us to read that question. – sheß Apr 01 '19 at 17:25
  • 2
    TikZ has all the means to avoid using \newcommands. \documentclass[border=3.14mm,tikz]{standalone} \begin{document} \begin{tikzpicture}[soni/.style n args={2}{insert path={node[draw=black] #1 at #2 {}}}] \path[soni={(a)}{(0,0)}]; \end{tikzpicture} \end{document} –  Apr 01 '19 at 18:07
  • 1
    Using \newcommand as you suggest works as expected. I have used that often and have not had any major issues with it. Used within a scope also works exactly as expected. The only minor issue I am aware of (which is not an issue with tikz) is with the use of trailing ; following the use of a macro is the nullfont warnings in the log file. This is explained nicely by Martin Scharrer's comment at [tikzpicture options causing “There is no in font nullfont!”?. But, if you are aware of this upfront you can easily avoid it. – Peter Grill Apr 01 '19 at 18:31

1 Answers1

2

First of all, your syntax of \newcommand is wrong.

\newcommand[2]{\createnode}{\node[draw=black] #1 at #2 {}}

won't work. These ones will work

\newcommand{\createnode}[2]{\node[draw=black] #1 at #2 {}}
\newcommand\createnode[2]{\node[draw=black] #1 at #2 {}} % I prefer this way

Regarding the first question,

Will this approach work and will the nodes created via this approach be accessible at a later stage?

It works (see the example below), but take care of the braces, brackets and semicolons.

\documentclass[tikz]{standalone}
\newcommand\createnode[2]{\node[draw=black] (#1) at (#2) {}}
\begin{document}
\begin{tikzpicture}
\createnode{x}{0,0};
\createnode{y}{3,4};
\draw[-stealth] (x) to[bend left] (y);
\end{tikzpicture}
\end{document}

enter image description here

It can be used with normal \nodes:

\documentclass[tikz]{standalone}
\newcommand\createnode[2]{\node[draw=black] (#1) at (#2) {}}
\begin{document}
\begin{tikzpicture}
\createnode{x}{0,0};
\node[circle,draw] (y) at (3,4) {$y$};
\draw[-stealth] (x) to[bend left] (y);
\end{tikzpicture}
\end{document}

enter image description here

It can even be used in remember picture

\documentclass[varwidth]{standalone}
\usepackage{tikz}
\newcommand\createnode[2]{\node[draw=black] (#1) at (#2) {}}
\begin{document}
This is a node: \tikz[remember picture]{\createnode{x}{0,2};}

And this is another node: \tikz[remember picture]{\createnode{y}{1,3};}

Let's try adding an arrow between them. It works!
\begin{tikzpicture}[overlay,remember picture]
\draw[-stealth] (x) to[bend left] (y);
\end{tikzpicture}
\end{document}

enter image description here


Regarding the second question,

Also with this approach, how will scope work if we create the same node in two scopes.

Consider the following code: it is not using \createnode:

\documentclass[tikz]{standalone}
%\newcommand\createnode[2]{\node[draw=black] (#1) at (#2) {}}
\begin{document}
\begin{tikzpicture}
\begin{scope}
\node[draw] (x) at (2,3) {};
\node[draw] (z) at (0,3) {};
\draw[-stealth] (z) -- (x);
\end{scope}
\begin{scope}
\node[draw] (x) at (0,0) {};
\node[draw] (y) at (2,1) {};
\end{scope}
\draw[-stealth] (z) -- (x);
\end{tikzpicture}
\end{document}

enter image description here

Node (x) is redefined in the later scope, so the two arrows are different.

Let try it with \createnode:

\documentclass[tikz]{standalone}
\newcommand\createnode[2]{\node[draw=black] (#1) at (#2) {}}
\begin{document}
\begin{tikzpicture}
\begin{scope}
\node[draw] (x) at (2,3) {};
\node[draw] (z) at (0,3) {};
\draw[-stealth] (z) -- (x);
\end{scope}
\begin{scope}
%\node[draw] (x) at (0,0) {};
\createnode{x}{0,0};
\node[draw] (y) at (2,1) {};
\end{scope}
\draw[-stealth] (z) -- (x);
\end{tikzpicture}
\end{document}

\documentclass[tikz]{standalone}
\newcommand\createnode[2]{\node[draw=black] (#1) at (#2) {}}
\begin{document}
\begin{tikzpicture}
\begin{scope}
\node[draw] (x) at (2,3) {};
\createnode{x}{2,3};
\node[draw] (z) at (0,3) {};
\draw[-stealth] (z) -- (x);
\end{scope}
\begin{scope}
\node[draw] (x) at (0,0) {};
%\createnode{x}{0,0};
\node[draw] (y) at (2,1) {};
\end{scope}
\draw[-stealth] (z) -- (x);
\end{tikzpicture}
\end{document}

Actually nothing changes.

enter image description here


My conclusion: If you use it carefully, it will definitely work as expected.


My comments: I think defining a new command for this is quite good. Sometimes I use this way too. However, please only use it when your command is really complicated and it is repeated several times, because you have to use it very carefully – the lack of a single semicolon can cause you many troubles. Don't overuse this way for simple commands like \node, otherwise it may be very hard to debug your code in some cases.