6

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

1 Answer 1

3

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}
5
  • Thanks a lot for this solution! However, I don´t understand why the red node is bigger than the one with text. Shouldn´t they have the same size, since minwd and minhg already have the given aspect? Commented Feb 3, 2015 at 18:17
  • Is it possible that the new shape ignores the minimum width? In my real example it behaves like this... Commented Feb 3, 2015 at 18:36
  • Sorry, there was a stupid error in the code. Having fixed that both the problems you mention are dealt with. Commented Feb 4, 2015 at 11:05
  • Thanks a lot for your help, that works nicely. So the mistake was < versus >? I tried to understand the first part of the code and it went pretty well, but didn´t find the mistake either. Commented Feb 8, 2015 at 1:15
  • Glad this helps - yes, the mistake was reversed inequalities in the added code. Commented Feb 8, 2015 at 13:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .