7

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

7
  • Please provide a Minimum Working Example... or non-Working, in this case...
    – cfr
    Commented May 17, 2014 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
    Commented May 17, 2014 at 20:02
  • 1
    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
    Commented May 17, 2014 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
    Commented May 17, 2014 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
    Commented May 17, 2014 at 20:43

1 Answer 1

7

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .