Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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?

share|improve this question
1  
a tip: you can use backticks ` to mark your inline code as I did in my edit. –  Hendrik Vogt Feb 17 '11 at 11:07
add comment

2 Answers

up vote 8 down vote accepted

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.

share|improve this answer
    
very good answer: the right method, the right code. But note the forbidden sign shape is backwards! –  Matthew Leingang Feb 17 '11 at 13:05
    
@Matthew: You mean the line is drawn in the wrong angle, do you? That's something which should be reported to the PGF/TikZ author. Nevertheless the code of it is a good example for having a circle as background path and the other lines in the foreground. –  Martin Scharrer Feb 17 '11 at 13:29
    
Yes, that's what I meant. I did report it to the mailing list a while back (google tells me it was Feb 2009). Maybe I should follow up on that since it's just a one-line patch—unless now you want it to be an option to have it backwards! –  Matthew Leingang Feb 17 '11 at 13:35
    
@Matthew: Yeah, backwards compatibility (wow what a pun! :-) ) is always an issue even with smaller stuff like this. –  Martin Scharrer Feb 17 '11 at 13:48
    
@Martin: Tell me about it. The new pgfmath engine has introduced bugs in lots of the graphs that I use for teaching. :-( –  Matthew Leingang Feb 17 '11 at 14:17
show 6 more comments

A possibility :

 \begin{tikzpicture}
   \tikzset{oplus/.style={path picture={% 
      \draw[black]
       (path picture bounding box.south) -- (path picture bounding box.north) 
       (path picture bounding box.west) -- (path picture bounding box.east);
      }}} 
    \node[oplus,fill=blue!10,draw=blue,thick,circle] {};
    \end{tikzpicture}

oplus

It's possible to send the cross in the background and to change the color

\begin{tikzpicture}
 \tikzset{oplus/.style={path picture={%
 \begin{pgfonlayer}{background} 
 \draw[red,opacity=.5]
  (path picture bounding box.south) -- (path picture bounding box.north) 
  (path picture bounding box.west) -- (path picture bounding box.east);
\end{pgfonlayer}}}
}
\node[oplus,draw=blue,thick,circle](a) {TEST}; 
\end{tikzpicture}

oplus 2

Now your code execute at end node is not good in this case. This code modifies the content of the node. You can try the next code :

 \begin{tikzpicture}
    \tikzset{foo/.style ={circle,draw, execute at end node={\ #1}}} 
    \node[foo=bad](A) at (2,3){good};
 \end{tikzpicture}

Interesting is execute at begin node=$ and execute at end node=$

Now if my answer is not what you want, you can define new shape like shape =oplus like in the other answer from Martin.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.