6

I have a document with several TikZ pictures in it. I generally use simple names for the nodes such as:

\node (A) at ..... 
\node (B) at .....

and so forth. Because of this I have name clashes between the various pictures. That's generally not a problem. However I find myself in a position where I may or may not have defined a certain node within a given picture. So I use the following snippet to test whether the node has been defined:

\makeatletter
\long\def\ifnodedefined#1#2#3{%%
  \@ifundefined{pgf@sh@ns@#1}{#3}{#2}}
\makeatother

Unfortunately this fails if I've already created a node by the same name in another picture.

Is there a way to scope the definitions of nodes or is there a way to undefine nodes once you no longer need them?

P.S.

I'm aware that I could embed each picture in a standalone file and import it using \includegraphics. Unfortunately, this approach will not work for the document I'm creating.

MWE

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\long\def\ifnodedefined#1#2#3{%%
  \@ifundefined{pgf@sh@ns@#1}{#3}{#2}}
\makeatother

\setlength{\parindent}{0pt}
\pagestyle{empty}
\begin{document}


There's no node \textbf{D} here, so I draw a triangle:\par
\begin{tikzpicture}

  \coordinate (A) at (0,0);
  \coordinate (B) at (1,0);
  \coordinate (C) at (1,1);
%  \coordinate (D) at (0,1);

  \ifnodedefined{D}
    {  \draw (A) foreach \myn in {B,C,D} {  -- (\myn) } --cycle;  }
    {  \draw (A) foreach \myn in {B,C}   {  -- (\myn) } --cycle;  }

\end{tikzpicture}




There is a node \textbf{D} here, so I draw a square:\par
\begin{tikzpicture}

  \coordinate (A) at (0,0);
  \coordinate (B) at (1,0);
  \coordinate (C) at (1,1);
  \coordinate (D) at (0,1);

  \ifnodedefined{D}
    {  \draw (A) foreach \myn in {B,C,D} {  -- (\myn) } --cycle;  }
    {  \draw (A) foreach \myn in {B,C}   {  -- (\myn) } --cycle;  }

\end{tikzpicture}





There isn't supposed to be a node \textbf{D} here.  I'm expecting a
triangle, but get a square.\par
\begin{tikzpicture}

  \coordinate (A) at (0,0);
  \coordinate (B) at (1,0);
  \coordinate (C) at (1,1);
%  \coordinate (D) at (0,1);

  \ifnodedefined{D}
    {  \draw (A) foreach \myn in {B,C,D} {  -- (\myn) } --cycle;  }
    {  \draw (A) foreach \myn in {B,C}   {  -- (\myn) } --cycle;  }

\end{tikzpicture}

\end{document}

produces:

enter image description here

  • Please provide a Minimum Working Example... or non-Working, in this case... – cfr May 17 '14 at 19:52
  • @cfr While I'm not opposed to posting a MWE, I'm not sure what would be gained here. The question seems simple and straight-forward, "Can you undefine a node?" – A.Ellett May 17 '14 at 20:02
  • I asked because when I tried to create a MWE, I just reused the same node name in the two pictures and had no trouble. No errors, no missing nodes. So clearly something more is required for it to be a problem and I was wondering what. Even if I use relative positioning and put the first myothernode left of the first mynode and the second myothernode right of the second mynode, it still all works. – cfr May 17 '14 at 20:11
  • 1
    @cfr Ah! I see what you mean. OK. I'll post something to better illustrate what I'm trying to do. – A.Ellett May 17 '14 at 20:19
  • 1
    Thank you! Now I understand the question. (I was originally really confused possibly because my tikz skills are similar to a bored snail's. No offence meant to bored snails.) – cfr May 17 '14 at 20:43
6

It seems I practically answered my question by the way I asked it:

\makeatletter

\newcommand\aeundefinenode[1]{%%
  \expandafter\ifx\csname pgf@sh@ns@#1\endcsname\relax
  \else
    \typeout{===>Undefining node "#1"}%%
    \global\expandafter\let\csname pgf@sh@ns@#1\endcsname\relax
  \fi
}

Here's working example:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter

\long\def\ifnodedefined#1#2#3{%%
  \@ifundefined{pgf@sh@ns@#1}{#3}{#2}}

\newcommand\aeundefinenode[1]{%%
  \expandafter\ifx\csname pgf@sh@ns@#1\endcsname\relax
  \else
    \typeout{===>Undefining node "#1"}%%
    \global\expandafter\let\csname pgf@sh@ns@#1\endcsname\relax
  \fi
}

\newcommand\aeundefinethesenodes[1]{%%
  \foreach \myn  in {#1}
    {%%
      \expandafter\aeundefinenode\expandafter{\myn}%%
    }%%
}

\makeatother

\setlength{\parindent}{0pt}
\pagestyle{empty}
\begin{document}

%-@-(1)---------------------------------------------------------------------
There's no node \textbf{D} here, so I draw a triangle:\par
\begin{tikzpicture}

  \coordinate (A) at (0,0);
  \coordinate (B) at (1,0);
  \coordinate (C) at (1,1);
%  \coordinate (D) at (0,1);

  \ifnodedefined{D}
    {  \draw (A) foreach \myn in {B,C,D} {  -- (\myn) } --cycle;  }
    {  \draw (A) foreach \myn in {B,C}   {  -- (\myn) } --cycle;  }

\end{tikzpicture}

%-@-(2)---------------------------------------------------------------------
There is a node \textbf{D} here, so I draw a square:\par
\begin{tikzpicture}

  \coordinate (A) at (0,0);
  \coordinate (B) at (1,0);
  \coordinate (C) at (1,1);
  \coordinate (D) at (0,1);

  \ifnodedefined{D}
    {  \draw (A) foreach \myn in {B,C,D} {  -- (\myn) } --cycle;  }
    {  \draw (A) foreach \myn in {B,C}   {  -- (\myn) } --cycle;  }

  \aeundefinethesenodes{A,B,C,D}
\end{tikzpicture}

%-@-(3)---------------------------------------------------------------------
There isn't supposed to be a node \textbf{D} here.  I'm expecting a
triangle, and get a triangle.\par
\begin{tikzpicture}

  \coordinate (A) at (0,0);
  \coordinate (B) at (1,0);
  \coordinate (C) at (1,1);
%  \coordinate (D) at (0,1);

  \ifnodedefined{D}
    {  \draw (A) foreach \myn in {B,C,D} {  -- (\myn) } --cycle;  }
    {  \draw (A) foreach \myn in {B,C}   {  -- (\myn) } --cycle;  }

\end{tikzpicture}

\end{document}

\newcommand\aeundefinethesenodes[1]{%%
  \foreach \myn  in {#1}
    {%%
      \expandafter\aeundefinenode\expandafter{\myn}%%
    }%%
}

\makeatother

enter image description here

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.