[Tex/LaTex] Draw inside nodes to get BPMN gateway shapes

nodestikz-styles

This question is a follow up to How to draw inside a TikZ node, using node style?

I am trying to get the AND and XOR gateway from BPMN as seen here http://www.omg.org/bpmn/Samples/Elements/Gateways.GIF

As a starting point I found this style file https://github.com/sbadia/gdeploy/blob/master/francegrilles/tikz-bpmn.sty but to get the plus and x in the gateway I have to set them as text. That does not look nice at all… How would I draw a thick 'plus' for the AND gateway and add the same share rotated by 45° for the XOR? With 'thick' I mean that it is significantly thicker than the border of the shape. Also note that neither the plus nor the x actually reach the border of the surrounding shape.

Reference showing BPMN Gateways

Best Answer

I created three new shapes based on diamond. If you need to scale these shapes and if you need to scale the circle, the cross, the + etc..., it would be interesting to choice another way to draw inside the diamond. Only the EB is well defined, for all other you need to draw a path and to fill it. But it's a lot of work.

Picture

BPMN

Code

\documentclass[11pt]{scrartcl}
\usepackage{tikz} 
\usetikzlibrary{shapes}
\makeatletter

\pgfdeclareshape{CD}
{
  \inheritsavedanchors[from=diamond] % this is nearly a rectangle
  \inheritanchorborder[from=diamond]
  \inheritanchor[from=diamond]{center}
  \inheritanchor[from=diamond]{north}
  \inheritanchor[from=diamond]{south}
  \inheritanchor[from=diamond]{west}
  \inheritanchor[from=diamond]{east}
  \inheritanchor[from=diamond]{north east}
  \inheritanchor[from=diamond]{south east}
  \inheritanchor[from=diamond]{north west}
  \inheritanchor[from=diamond]{south west}                    

  \backgroundpath{
    \pgf@process{\outernortheast}%
    \pgf@xc=\pgf@x%
    \pgf@yc=\pgf@y%
    \pgfmathsetlength{\pgf@xa}{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength{\pgf@ya}{\pgfkeysvalueof{/pgf/outer ysep}}%
    \advance\pgf@xc by-1.414213\pgf@xa%
    \advance\pgf@yc by-1.414213\pgf@ya%
    \pgfpathmoveto{\pgfqpoint{\pgf@xc}{0pt}}%
    \pgfpathlineto{\pgfqpoint{0pt}{\pgf@yc}}%
    \pgfpathlineto{\pgfqpoint{-\pgf@xc}{0pt}}%
    \pgfpathlineto{\pgfqpoint{0pt}{-\pgf@yc}}%
    \pgfpathclose\pgfusepath{stroke} 
    % add 
    \advance\pgf@xc by -.5\pgf@xc% 
    \advance\pgf@yc by -.5\pgf@yc%
    \pgfsetlinewidth{2pt}
    \pgfpathmoveto{\pgfqpoint{\pgf@xc}{0pt}}%
    \pgfpathlineto{\pgfqpoint{-\pgf@xc}{0pt}}%
    \pgfpathmoveto{\pgfqpoint{0pt}{\pgf@yc}}%
    \pgfpathlineto{\pgfqpoint{0pt}{-\pgf@yc}}%
    \pgfpathmoveto{\pgfqpoint{0.707\pgf@xc}{0.707\pgf@yc}}%
     \pgfpathlineto{\pgfqpoint{-0.707\pgf@xc}{-0.707\pgf@yc}}%
     \pgfpathmoveto{\pgfqpoint{-0.707\pgf@xc}{0.707\pgf@yc}}%
     \pgfpathlineto{\pgfqpoint{0.707\pgf@xc}{-0.707\pgf@yc}}%  
      }
}

\pgfdeclareshape{PF}
{
  \inheritsavedanchors[from=diamond] % this is nearly a rectangle
  \inheritanchorborder[from=diamond]
  \inheritanchor[from=diamond]{center}
  \inheritanchor[from=diamond]{north}
  \inheritanchor[from=diamond]{south}
  \inheritanchor[from=diamond]{west}
  \inheritanchor[from=diamond]{east}
  \inheritanchor[from=diamond]{north east}
  \inheritanchor[from=diamond]{south east}
  \inheritanchor[from=diamond]{north west}
  \inheritanchor[from=diamond]{south west}                    

  \backgroundpath{
    \pgf@process{\outernortheast}%
    \pgf@xc=\pgf@x%
    \pgf@yc=\pgf@y%
    \pgfmathsetlength{\pgf@xa}{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength{\pgf@ya}{\pgfkeysvalueof{/pgf/outer ysep}}%
    \advance\pgf@xc by-1.414213\pgf@xa%
    \advance\pgf@yc by-1.414213\pgf@ya%
    \pgfpathmoveto{\pgfqpoint{\pgf@xc}{0pt}}%
    \pgfpathlineto{\pgfqpoint{0pt}{\pgf@yc}}%
    \pgfpathlineto{\pgfqpoint{-\pgf@xc}{0pt}}%
    \pgfpathlineto{\pgfqpoint{0pt}{-\pgf@yc}}%
    \pgfpathclose\pgfusepath{stroke} 
    % add 
    \advance\pgf@xc by -.5\pgf@xc% 
    \advance\pgf@yc by -.5\pgf@yc%
    \pgfsetlinewidth{2pt}
    \pgfpathmoveto{\pgfqpoint{\pgf@xc}{0pt}}%
    \pgfpathlineto{\pgfqpoint{-\pgf@xc}{0pt}}%
    \pgfpathmoveto{\pgfqpoint{0pt}{\pgf@yc}}%
    \pgfpathlineto{\pgfqpoint{0pt}{-\pgf@yc}}% 
      }
}

\pgfdeclareshape{ID}
{
  \inheritsavedanchors[from=diamond] % this is nearly a rectangle
  \inheritanchorborder[from=diamond]
  \inheritanchor[from=diamond]{center}
  \inheritanchor[from=diamond]{north}
  \inheritanchor[from=diamond]{south}
  \inheritanchor[from=diamond]{west}
  \inheritanchor[from=diamond]{east}
  \inheritanchor[from=diamond]{north east}
  \inheritanchor[from=diamond]{south east}
  \inheritanchor[from=diamond]{north west}
  \inheritanchor[from=diamond]{south west}                    

  \backgroundpath{
    \pgf@process{\outernortheast}%
    \pgf@xc=\pgf@x%
    \pgf@yc=\pgf@y%
    \pgfmathsetlength{\pgf@xa}{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength{\pgf@ya}{\pgfkeysvalueof{/pgf/outer ysep}}%
    \advance\pgf@xc by-1.414213\pgf@xa%
    \advance\pgf@yc by-1.414213\pgf@ya%
    \pgfpathmoveto{\pgfqpoint{\pgf@xc}{0pt}}%
    \pgfpathlineto{\pgfqpoint{0pt}{\pgf@yc}}%
    \pgfpathlineto{\pgfqpoint{-\pgf@xc}{0pt}}%
    \pgfpathlineto{\pgfqpoint{0pt}{-\pgf@yc}}%
    \pgfpathclose\pgfusepath{stroke}
    % add 
    \pgfsetlinewidth{2pt}
    \pgfutil@tempdima=\pgf@xc%
    \pgfutil@tempdima=0.5\pgfutil@tempdima%
    \pgfpathcircle{\pgfpointorigin}{\pgfutil@tempdima}
      }
} 

\pgfdeclareshape{EB}
{
  \inheritsavedanchors[from=diamond] % this is nearly a rectangle
  \inheritanchorborder[from=diamond]
  \inheritanchor[from=diamond]{center}
  \inheritanchor[from=diamond]{north}
  \inheritanchor[from=diamond]{south}
  \inheritanchor[from=diamond]{west}
  \inheritanchor[from=diamond]{east}
  \inheritanchor[from=diamond]{north east}
  \inheritanchor[from=diamond]{south east}
  \inheritanchor[from=diamond]{north west}
  \inheritanchor[from=diamond]{south west}                    

  \backgroundpath{
    \pgf@process{\outernortheast}%
    \pgf@xc=\pgf@x%
    \pgf@yc=\pgf@y%
    \pgfmathsetlength{\pgf@xa}{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength{\pgf@ya}{\pgfkeysvalueof{/pgf/outer ysep}}%
    \advance\pgf@xc by-1.414213\pgf@xa%
    \advance\pgf@yc by-1.414213\pgf@ya%
    \pgfpathmoveto{\pgfqpoint{\pgf@xc}{0pt}}%
    \pgfpathlineto{\pgfqpoint{0pt}{\pgf@yc}}%
    \pgfpathlineto{\pgfqpoint{-\pgf@xc}{0pt}}%
    \pgfpathlineto{\pgfqpoint{0pt}{-\pgf@yc}}%
    \pgfpathclose\pgfusepath{stroke}
    % add 
    \pgfutil@tempdima=\pgf@xc%
    \pgfutil@tempdima=0.6\pgfutil@tempdima%
    \pgfpathcircle{\pgfpointorigin}{\pgfutil@tempdima} 
        \pgfutil@tempdima=0.8\pgfutil@tempdima%
    \pgfpathcircle{\pgfpointorigin}{\pgfutil@tempdima}
     \pgfusepath{stroke} 
    %add 
        \pgfpathmoveto{\pgfqpoint{0pt}{\pgfutil@tempdima}}%
        \pgfpathlineto{\pgfqpoint{0.25\pgfutil@tempdima}{0.433\pgfutil@tempdima}}% 
        \pgfpathlineto{\pgfqpoint{0.866\pgfutil@tempdima}{0.5\pgfutil@tempdima}}%
        \pgfpathlineto{\pgfqpoint{0.5\pgfutil@tempdima}{0pt}}%
        \pgfpathlineto{\pgfqpoint{0.866\pgfutil@tempdima}{-0.5\pgfutil@tempdima}}%   
        \pgfpathlineto{\pgfqpoint{0.25\pgfutil@tempdima}{-0.433\pgfutil@tempdima}}% 
        \pgfpathlineto{\pgfqpoint{0pt}{-\pgfutil@tempdima}}% 
        \pgfpathlineto{\pgfqpoint{-0.25\pgfutil@tempdima}{-0.433\pgfutil@tempdima}}%    
        \pgfpathlineto{\pgfqpoint{-0.866\pgfutil@tempdima}{-0.5\pgfutil@tempdima}}%
        \pgfpathlineto{\pgfqpoint{-0.5\pgfutil@tempdima}{0pt}}%    
        \pgfpathlineto{\pgfqpoint{-0.866\pgfutil@tempdima}{0.5\pgfutil@tempdima}}% 
        \pgfpathlineto{\pgfqpoint{-0.25\pgfutil@tempdima}{0.433\pgfutil@tempdima}}%
        \pgfpathclose 
        \pgfusepath{fill}
       }
}  

\pgfdeclareshape{XOR}
{
  \inheritsavedanchors[from=diamond] % this is nearly a rectangle
  \inheritanchorborder[from=diamond]
  \inheritanchor[from=diamond]{center}
  \inheritanchor[from=diamond]{north}
  \inheritanchor[from=diamond]{south}
  \inheritanchor[from=diamond]{west}
  \inheritanchor[from=diamond]{east}
  \inheritanchor[from=diamond]{north east}
  \inheritanchor[from=diamond]{south east}
  \inheritanchor[from=diamond]{north west}
  \inheritanchor[from=diamond]{south west}                    

  \backgroundpath{
    \pgf@process{\outernortheast}%
    \pgf@xc=\pgf@x%
    \pgf@yc=\pgf@y%
    \pgfmathsetlength{\pgf@xa}{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength{\pgf@ya}{\pgfkeysvalueof{/pgf/outer ysep}}%
    \advance\pgf@xc by-1.414213\pgf@xa%
    \advance\pgf@yc by-1.414213\pgf@ya%
    \pgfpathmoveto{\pgfqpoint{\pgf@xc}{0pt}}%
    \pgfpathlineto{\pgfqpoint{0pt}{\pgf@yc}}%
    \pgfpathlineto{\pgfqpoint{-\pgf@xc}{0pt}}%
    \pgfpathlineto{\pgfqpoint{0pt}{-\pgf@yc}}%
    \pgfpathclose\pgfusepath{stroke}
    %add 
    \advance\pgf@xc by -.5\pgf@xc% 
    \pgfsetlinewidth{2pt}
    \pgfpathmoveto{\pgfqpoint{ 0.6\pgf@xc}{0.8484\pgf@xc}}%
    \pgfpathlineto{\pgfqpoint{-0.6\pgf@xc}{-0.8484\pgf@xc}}%
    \pgfpathmoveto{\pgfqpoint{-0.6\pgf@xc}{0.8484\pgf@xc}}%
    \pgfpathlineto{\pgfqpoint{ 0.6\pgf@xc}{-0.8484\pgf@xc}}%  
    }
} 
\begin{document}

\begin{tikzpicture}
  \node[draw,shape=CD,minimum size=1cm] (x) {};
  \node[draw,shape=PF,minimum size=1cm] at ([shift=(0:5cm)]x) (y) {};
  \node[draw,shape=ID,minimum size=1cm] at ([shift=(90:5cm)]x) (z) {};
  \node[draw,shape=EB,minimum size=1cm] at ([shift=(0:5cm)]z) (t) {};
  \node[draw,shape=XOR,minimum size=1cm] at ([shift=(-30:3cm)]t) (v) {};   
  \draw[dashed,ultra thick] (x) -- (y) -- (z)--(t) -- (v);
\end{tikzpicture}

\end{document}