[Tex/LaTex] Flowchart-decision shape – enforce aspect of pgf diamond shape

diagramsnodespgfplotsshapes

I am using TikZ/PGF to build a flowchart. To construct the shapes I need, I used the flowchart package plus the ones given in this excellent answer. I modified the decision shape to have the aspect ratio of 1.5, since this is what the german norm on flowcharts (DIN 66001) states. But it seems that the aspect of the actual shape doesn´t follow my specification.

How can I enforce the aspect without stating minimum width and height? Will this work also, if my text surpasses the stated minimum width?

MWE:

MWE

\documentclass[a4paper]{scrartcl}

\usepackage{tikz}
\tikzset{every picture/.append style={font=\small}} 
\usetikzlibrary{shapes.geometric}


\begin{document}

\begin{tikzpicture}
\tikzset{decision/.style={ % requires library shapes.geometric
        draw,
        diamond,
        aspect=1.5
    }}
\def\minhg{2cm}
\def\minwd{3cm}

\node [decision,minimum width=\minwd,align=left] {\texttt{hh}$\,>1$};
\node [decision,minimum width=\minwd,minimum height=\minhg,red] {};

\end{tikzpicture}

\end{document}

Best Answer

The problem is that the standard diamond shape sets its aspect ratio first, and then checks whether the minimum width or height requirements are satisfied and if not brutally adjusts either the width or the height disregarding the aspect ratio. Fixing this involves inserting extra code into the shape definition. Below I have made a new shape fdiamond where the aspect ratio is preserved. It is just a copy of the diamond code with 8 lines added.

Sample output

\documentclass[a4paper]{scrartcl}

\usepackage{tikz}
\tikzset{every picture/.append style={font=\small}} 
\usetikzlibrary{shapes.geometric}

\makeatletter
\pgfdeclareshape{fdiamond}
{
  \savedanchor\outernortheast{%
    %
    % Calculate width and height of the inner rectangle
    %
    \pgf@xa=.5\wd\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/inner xsep}}%
    \advance\pgf@xa by\pgf@xc%
    \pgf@ya=.5\ht\pgfnodeparttextbox%
    \advance\pgf@ya by.5\dp\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/inner ysep}}%
    \advance\pgf@ya by\pgf@yc%
    %
    % Calculate width and height of diamond
    %
    \pgf@x=\pgf@xa%
    \advance\pgf@x by\pgfshapeaspect\pgf@ya%
    \pgf@y=\pgfshapeaspectinverse\pgf@xa%
    \advance\pgf@y by\pgf@ya%
    %
    % Check against minimum height/width
    %
    \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/minimum width}}%
    \pgf@xb=.5\pgf@xb%   
    \ifdim\pgf@x<\pgf@xb%
      % yes, too small. Enlarge...
      \pgf@x=\pgf@xb%
    \fi%
    \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/minimum height}}%
    \pgf@yb=.5\pgf@yb%   
    \ifdim\pgf@y<\pgf@yb%
      % yes, too small. Enlarge...
      \pgf@y=\pgf@yb%
    \fi%
    % Fix aspect ratio   %%%ADDED%%%%
    \pgf@xa=\pgfshapeaspect\pgf@y%
    \ifdim\pgf@xa>\pgf@x%
      \pgf@x=\pgf@xa%
    \fi%
    \pgf@ya=\pgfshapeaspectinverse\pgf@x%
    \ifdim\pgf@ya>\pgf@y%
      \pgf@y=\pgf@ya%
    \fi%
    %
    % Add outer border
    %
    \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/outer xsep}}%
    \advance\pgf@x by\pgf@xa%
    \pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/outer ysep}}%
    \advance\pgf@y by\pgf@ya%
  }
  \savedanchor\text{%
    \pgf@x=-.5\wd\pgfnodeparttextbox%
    \pgf@y=-.5\ht\pgfnodeparttextbox%
    \advance\pgf@y by.5\dp\pgfnodeparttextbox%
  }

  %
  % Anchors
  %
  \anchor{text}{\text}%
  \anchor{center}{\pgfpointorigin}%
  \anchor{mid}{%
    \pgf@process{\text}%
    \pgf@x=0pt%
    \pgfmathsetlength\pgf@ya{.5ex}
    \advance\pgf@y by\pgf@ya%
  }
  \anchor{base}{\pgf@process{\text}\pgf@x=0pt  }
  \anchor{north}{\pgf@process{\outernortheast}\pgf@x=0pt}
  \anchor{south}{\pgf@process{\outernortheast}\pgf@x=0pt\pgf@y=-\pgf@y}
  \anchor{west}{\pgf@process{\outernortheast}\pgf@x=-\pgf@x\pgf@y=0pt}
  \anchor{north west}{\pgf@process{\outernortheast}\pgf@x=-.5\pgf@x\pgf@y=.5\pgf@y}
  \anchor{south west}{\pgf@process{\outernortheast}\pgf@x=-.5\pgf@x\pgf@y=-.5\pgf@y}
  \anchor{east}{\pgf@process{\outernortheast}\pgf@y=0pt}
  \anchor{north east}{\pgf@process{\outernortheast}\pgf@x=.5\pgf@x\pgf@y=.5\pgf@y}
  \anchor{south east}{\pgf@process{\outernortheast}\pgf@x=.5\pgf@x\pgf@y=-.5\pgf@y}
  \anchorborder{%
    \pgf@xa=\pgf@x%
    \pgf@ya=\pgf@y%
    \pgf@process{\outernortheast}%
    \ifdim\pgf@xa>0pt%
    \else%
      \pgf@x=-\pgf@x%
    \fi%
    \ifdim\pgf@ya>0pt%
    \else%
      \pgf@y=-\pgf@y%
    \fi%
    \edef\pgf@marshal{%
      \noexpand\pgfpointintersectionoflines
      {\noexpand\pgfpointorigin}
      {\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}
      {\noexpand\pgfqpoint{\the\pgf@x}{0pt}}
      {\noexpand\pgfqpoint{0pt}{\the\pgf@y}}%
    }%
    \pgf@process{\pgf@marshal}%
  }

  %
  % Background path
  %
  \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%
  }
}
\makeatother


\begin{document}

\begin{tikzpicture}
\tikzset{decision/.style={ % requires library shapes.geometric
        draw,
        fdiamond,
        aspect=1.5
    }}
\def\minhg{2cm}
\def\minwd{3cm}

\node [decision,minimum width=\minwd,align=left] {\texttt{hh}$\,>1$};
\node [decision,minimum width=\minwd,minimum height=\minhg,red] {};

\end{tikzpicture}

\end{document}
Related Question