Cambiar estilo para contenido de nodo vacío/no vacío

Cambiar estilo para contenido de nodo vacío/no vacío

Idealmente, me gustaría tener un comando \vertexque se comporte como

\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};

y de manera similar para varias otras combinaciones; pero no tengo idea de cómo escribir tal función.

¿Alguien tiene alguna idea de si esto podría lograrse y cómo?

Como alternativa, ¿es posible que el estilo de un nodo dependa del contenido del nodo? De esta manera siempre habría que escribir el final {...}, pero el resultado final variaría dependiendo de si estas llaves están rellenas o no.

Mi primer pensamiento para esta alternativa fue intentar implementar un estilo como

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

Sin embargo, esto no parece funcionar porque el estilo se analizará antes de \tikz@node@contentcompletarse [1] , por lo que la truerama siempre se ejecuta.

Por último,


[1]: Esto se basa en mirar tikz.code.tex, específicamente, la línea 3668 donde \tikz@node@contentestá configurada.

Respuesta1

Creo que si vamos a hackear, entonces es más fácil hackear el analizador en el punto en el que insiste en que un nodo tenga algún contenido. Posiblemente así...

\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}

ingrese la descripción de la imagen aquí

Sin embargo, se debe señalar que una de las razones por las que se genera un error (a menos que node contentsse hayan usado las claves) es porque el analizador usa las llaves {}para determinar cuándo finalizó la especificación del nodo, por lo que el truco anterior debe usarse con cuidado.

Respuesta2

Nunca demasiado tarde. Puede comprobar si un nodo está vacío midiendo el ancho de \pgfnodeparttextbox. Y luego redefinir \tikz@shapeen consecuencia.

\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}

información relacionada