[Tex/LaTex] How to draw inside a TikZ node, using node style

nodestikz-pgf

I would like to define a node style, so that the node will look like the LaTeX symbol \oplus, i.e. a circle with lines from north to south, and east to west. (I also have more complicated examples in mind.)

I think that I should draw the lines in the execute at end node, or after mode path arguments, but nothing I have tried seems to work. The code I have in mind is something like this:

\tikzstyle{foo}=[circle,draw,execute at end node={\draw ??????}]

To rephrase the question: How can one do arbitrary drawing within a node, and define this as a style? In particular, how do you get the coordinates of the current node in a style?

Best Answer

All TikZ node shapes are defined using lower-level PGF code. This is described in the pgfmanual in section 75.5 Declaring New Shapes, on page 625 of the v2.1 manual.

You can use the existing code of the circle shape as a base and add the lines to it. The code can be found in the file ${TEXMF}/tex/generic/pgf/modules/pgfmoduleshapes.code.tex.

Here the way I would do it:

Shape declaration:

\pgfdeclareshape{oplus}
%
% Shaped like '\oplus' math symbol. Based on 'circle' shape
%
{%
  % All anchors are taken from the 'circle' shape:
  \inheritsavedanchors[from={circle}]%
  \inheritanchor[from={circle}]{center}%
  \inheritanchor[from={circle}]{mid}%
  \inheritanchor[from={circle}]{base}%
  \inheritanchor[from={circle}]{north}%
  \inheritanchor[from={circle}]{south}%
  \inheritanchor[from={circle}]{west}%
  \inheritanchor[from={circle}]{east}%
  \inheritanchor[from={circle}]{mid west}%
  \inheritanchor[from={circle}]{mid east}%
  \inheritanchor[from={circle}]{base west}%
  \inheritanchor[from={circle}]{base east}%
  \inheritanchor[from={circle}]{north west}%
  \inheritanchor[from={circle}]{south west}%
  \inheritanchor[from={circle}]{north east}%
  \inheritanchor[from={circle}]{south east}%
  \inheritanchorborder[from={circle}]%
  %
  % Only the background path is different
  %
  \backgroundpath{%
    % First the existing 'circle' code:
    \pgfutil@tempdima=\radius%
    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
    \ifdim\pgf@xb<\pgf@yb%
      \advance\pgfutil@tempdima by-\pgf@yb%
    \else%
      \advance\pgfutil@tempdima by-\pgf@xb%
    \fi%
    \pgfpathcircle{\centerpoint}{\pgfutil@tempdima}%
    %
    % Now the | and -- lines:
    \pgfmoveto{\pgfpointadd{\centerpoint}{\pgfpoint{0pt}{\pgfutil@tempdima}}}%
    \pgflineto{\pgfpointadd{\centerpoint}{\pgfpoint{0pt}{-\pgfutil@tempdima}}}%
    \pgfmoveto{\pgfpointadd{\centerpoint}{\pgfpoint{\pgfutil@tempdima}{0pt}}}%
    \pgflineto{\pgfpointadd{\centerpoint}{\pgfpoint{-\pgfutil@tempdima}{0pt}}}%
  }%
}

Usage example:

\documentclass{standalone}

\usepackage{tikz}
\usepackage{pgfshape_oplus}

\begin{document}
\begin{tikzpicture}
  \node [draw=blue,shape=oplus] {Test};
\end{tikzpicture}
\end{document}

Result:

Result

You might also want to draw the additional lines in the \foregroundpath instead. For this see the forbidden sign shape in the file pgflibraryshapes.symbols.code.tex is an good example.