5

Ideally, I wish would like a command \vertex such that it behaves as

\vertex (a);                --->  \node[empty vertex] (a) {};
\vertex[foo] (a);           --->  \node[empty vertex, foo] (a) {};
\vertex[foo] (a) at (0, 0); --->  \node[empty vertex, foo] (a) at (0, 0) {};

\vertex (a) {bar}; ---> \node[filled vertex] (a) {bar};

and similarly for various other combinations; but I have no idea how to even write such a function.

Does anyone have any idea if or how this could be achieved?

As a fallback, is it possible for a node style to depend on the node content? This way, one would always have to write the final {...}, but the end result would vary depending on whether these braces are filled or not.

My first thought for this fallback was to try implementing a style like

\tikzset{
    vertex/.append code={
        \ifx\tikz@node@content\relax
            \pgfkeysalso{/tikz/shape=coordinate}
        \else
            \pgfkeysalso{/tikz/shape=circle}
            \pgfkeysalso{/tikz/draw}
        \fi
    },
}

However, this does not seem to work because the style will be parsed before \tikz@node@content is populated[1], so the true branch is always executed.

Ultimately,


[1]: This is based on looking at tikz.code.tex, specifically, line 3668 where \tikz@node@content is set.

JP-Ellis
  • 8,929
  • 2
  • 33
  • 49
  • If I understand your code seems that you want to define a node like coordinate when it's empty and like node if it contains text. Some not very elaborated suggestions. First: matrix library contains something about nodes on empty cells. Second: Why not draw a coordinate and add an optional node over it when text is present? May be with append after command or insert path or pgfextra. (I'm not sure if these commands serve for this) – Ignasi Apr 30 '15 at 09:25
  • @Ignasi should be nodes in empty cells. By the way \tikz@node@content may not contains the actual content since TikZ accepts code like \tikz\node{\verb|%|}; – Symbol 1 Apr 30 '15 at 15:05
  • I have had a quick look at matrix and the way it handles nodes in empty cells and it seems like it parses the matrix node's content and inserts the appropriate TikZ commands as it goes, effectively wrapping the matrix contents. It doesn't seem to ever read the contents of the matrix sub-nodes. I will have a look at checking whether I can use a style to create a 1x1 matrix.

    Also, why would \tikz\node{\verb|%|}; cause an issue?

    – JP-Ellis May 01 '15 at 05:35

2 Answers2

4

I think if we're going to hack, then it is easiest to hack the parser at the point where it insists on a node having some content. Possibly like this...

\documentclass[tikz,border=5]{standalone}
\makeatletter
\newif\iftikznodeallowempty
\def\tikz@@scan@fig{%
  \pgfutil@ifnextchar a{\tikz@fig@scan@at}
  {\pgfutil@ifnextchar({\tikz@fig@scan@name}
    {\pgfutil@ifnextchar[{\tikz@fig@scan@options}%
      {\pgfutil@ifnextchar\bgroup{\tikz@fig@main}%
      {\iftikznodeallowempty%
          \tikzset{every empty node/.try}%
        \else%
          \tikzerror{A node must have a (possibly empty) label text}%
       \fi%
       \tikz@fig@main{}}}}}}%}}

\tikzset{every empty node/.style={shape=coordinate}}

\def\vertex{\path \pgfextra{\tikznodeallowemptytrue} node [every vertex/.try]}

\begin{document} \begin{tikzpicture} \vertex [label=315:v1] (v1); \vertex [label=0:v2] (v2) at (1,1); \vertex [label=90:v3] (v3) at (-1,1); \vertex [anchor=north] (v4) at (-1,-1) {text}; \draw [red] (v1) -- (v2) -- (v3) -- (v4.north) -- cycle; \end{tikzpicture} \end{document}

enter image description here

However, it should be pointed out that one of the reasons an error is generated (unless the node contents keys has been used) is because the parser uses the braces {} to determine when the node specification has ended, so the above hack should be used with care.

Mark Wibrow
  • 70,437
1

Never too late. You can check whether a node is empty by measuring the width of \pgfnodeparttextbox. And then redefine \tikz@shape accordingly.

\documentclass[border=30,tikz]{standalone}
\usepgflibrary{shapes.misc}
\begin{document}

\makeatletter
\def\tikz@fig@boxdone{%
%%% old definition ↓↓↓
            \tikz@atend@node%
          \ifx\tikz@text@width\pgfutil@empty%
          \else%
              \pgfutil@endminipage%
            \endgroup%
          \fi%
        \endpgfinterruptpicture%
      \egroup%
%%% new code ↓↓↓
    \ifdim0pt=\wd\pgfnodeparttextbox%
      \def\tikz@shape{cross out}\tikzset{draw=red}%
    \else%
      \def\tikz@shape{circle}\pgfkeysalso{/tikz/draw}%
    \fi%
%%% old definition ↓↓↓
    \pgfutil@ifnextchar c{\tikz@fig@mustbenamed\tikz@fig@continue}%
    {\pgfutil@ifnextchar[{\tikz@fig@mustbenamed\tikz@fig@continue}%
      {\pgfutil@ifnextchar t{\tikz@fig@mustbenamed\tikz@fig@continue}
        {\pgfutil@ifnextchar e{\tikz@fig@mustbenamed\tikz@fig@continue}
          {\ifx\tikz@after@path\pgfutil@empty\expandafter\tikz@fig@continue\else\expandafter\tikz@fig@mustbenamed\expandafter\tikz@fig@continue\fi}}}}}%}

\tikz\path(0,3)node{}
          (0,2)node{bravo}
          (0,1)node{\hbox to0pt{charlie}}
          (0,0)node{\hbox to-1pt{delta}};

\end{document}
Symbol 1
  • 36,855