2

I want to create a triangle shape for flow diagrams, so far I succeeded but the anchors I have defined are badly placed. This seems to be wired as I have just copied and pasted the code from the computation of the background path (see MWE below). So my question is, is there a (hidden) canvas transformation going so that I am computing different things for anchors and for the background path? ATM the angle in the right lower corner is fixed to 60 degrees, as it has to be parallel to other such boxes.

Remark: The in' anchor should be placed on the middle of the bottom line, theout' anchor on the middle of the slanted (right) line. Here also as in other node shapes (notably trapezium) one sees that the end of the connecting line is not fully reaching the border line of the node, but the gap is very small.

Here is the code:

\documentclass{article}
%=======================================================================
% include macros
%-----------------------------------------------------------------------
\usepackage{tikz}
\usetikzlibrary{shapes, shapes.multipart, shapes.geometric}
\tikzstyle{string}=[line width=1.25pt]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% state or program
%
\newlength\progsize
\setlength\progsize{0.2cm}
\newlength\minimumstatesize
\setlength\minimumstatesize{0.4cm}
%%
%%
%%
\makeatletter
\pgfdeclareshape{prog}
{% -- some dimensions
   \saveddimen{\halftextwidth}{%
       \pgf@x=0.5\wd\pgfnodeparttextbox
       % get xsep
       \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/inner xsep}}%
       \advance\pgf@x by \pgf@xc%
       % get minimum width
       \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/minimum width}}%
       \divide\pgf@xb by 2
       \ifdim\pgf@x<\pgf@xb%
          % yes, too small. enlarge...
          \pgf@x=\pgf@xb%
       \fi%  
   }
   \saveddimen{\halftextheight}{%
       \pgf@x=0.5\ht\pgfnodeparttextbox
       % get ysep
       \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/inner ysep}}%
       \advance\pgf@x by \pgf@xc%
       % get minimum width
       \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/minimum height}}%
       \divide\pgf@xb by 2
       \ifdim\pgf@x<\pgf@xb%
          % yes, too small. enlarge...
          \pgf@x=\pgf@xb%
       \fi%  
   }
   % -- anchors
   \savedanchor\centerpoint{%  midpoint on base line
       \pgf@x=0pt 
       \pgf@y=0pt
   }
   \anchor{center}{\centerpoint}
   \anchor{text}{%
         % horrizontal midpoint of pgfnodeparttextbox
         \pgf@x=-0.5\wd\pgfnodeparttextbox
         \pgf@y=-0.5\ht\pgfnodeparttextbox
         \advance\pgf@y by -0.5\dp\pgfnodeparttextbox
         }
   \anchor{in}{% use triangle corners as computed in \backgroundpath below
         \pgf@xa=\halftextwidth        % (xa)
         \pgf@xb=\pgf@xa
            \pgf@xc=\halftextheight
            \pgf@xc=1.732\pgf@xc
            \advance\pgf@xb by \pgf@xc % (xb)
         \pgf@x=\pgf@xb                % (x) = (xb-xa)/2   
            \advance\pgf@x by -\pgf@xa
            \divide\pgf@x by 2
         %
         %% same code as in \backgroundpath !!!!
         \pgf@ya=2pt                   % (ya)
            \advance\pgf@ya by 0.5\ht\pgfnodeparttextbox
            \advance\pgf@ya by    \dp\pgfnodeparttextbox
            \pgf@y=-\pgf@ya    % (y) = (-ya)
         }
   \anchor{out}{% use trinagle corners as computed in \backgroundpath below
         %% (x)
         \pgf@xa=\halftextwidth        % (xa)
         \pgf@xb=\pgf@xa
            \pgf@xc=\halftextheight
            \pgf@xc=1.732\pgf@xc
            \advance\pgf@xb by \pgf@xc % (xb)
         \pgf@x=\pgf@xb          
            \advance\pgf@x by -\pgf@xa
            \divide\pgf@x by 2         % (x) = (xb-xa)/2
         %% (y)
         \pgf@ya=2pt                     % (ya)
            \advance\pgf@ya by 0.5\ht\pgfnodeparttextbox
            \advance\pgf@ya by    \dp\pgfnodeparttextbox
         \pgf@yc=\pgf@xb                % (yc)
            \advance\pgf@yc by \pgf@xa
            \pgf@yc=1.732\pgf@yc
         \pgf@y=0.5\pgf@yc
            \advance\pgf@y by -0.5\pgf@ya   % (y) = (xc-ya)/2
   }      
   %%
   %%
   \backgroundpath
   {
   %% -- compute the corners (A,B,C) of a trinagle with such that:
   %%    AB horizonlat, AC vertical, and
   %%    A: left bottom angle 90degrees (xa,ya)
   %%    B: right bottom angle 60 degrees (xb,yb=ya)
   %%    C: top angle 30 degrees (xc=xa,yc)
         \pgf@xa=\halftextwidth          % (xa)
         \pgf@ya=2pt                     % (ya)
            \advance\pgf@ya by 0.5\ht\pgfnodeparttextbox
            \advance\pgf@ya by \dp\pgfnodeparttextbox 
         \pgf@xb=\pgf@xa                 % (xb)  (yb=ya)
            \pgf@xc=\halftextheight
            \pgf@xc=1.732\pgf@xc         % tan(Pi/3) ~= 1.732
            \advance\pgf@xb by \pgf@xc
         \pgf@yc=\pgf@xb                 % (yc)  (xc=xa)
            \advance\pgf@yc by \pgf@xa
            \pgf@yc=1.732\pgf@yc
         %
         \pgfpathmoveto{\pgfqpoint{-\pgf@xa}{-\pgf@ya}}
         \pgfpathlineto{\pgfqpoint{-\pgf@xa}{\pgf@yc}}
         \pgfpathlineto{\pgfqpoint{\pgf@xb}{-\pgf@ya}}
         \pgfpathclose
         %\pgfcircle{\centerpoint}{2pt}
   }
}
\makeatother

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%=======================================================================
\begin{document}
%=======================================================================

\[\begin{tikzpicture}
        \node[prog,draw,string,inner xsep=1pt,inner ysep=-1.5pt] (p1) at (0,0.5) {\texttt{t}};
        \node[prog,draw,string,inner xsep=1pt,inner ysep=0pt] (p2) at (1,0.5) {\texttt{p}};
        %
        \draw[string] (p1.in |- 0.2,0) -- (p1.in);
       \draw[string] (p2.in |- 0.2,0) -- (p2.in);
        \draw[string] (p1.out) -- (0.5,1);
        \draw[string] (p2.out) -- (1.5,1);  
\end{tikzpicture}\]
\end{document}

and here is the (wrong) output:

enter image description here

  • 2
    Do not use \pgfnodeparttextbox in normal \anchors but only in \savedanchor (or \saveddimen and such). You cannot guarantee that the box is the same as when the node has been created. The \anchor anchors are calculated when they are used and not when the node is created. – Qrrbrbirlbel Oct 1 '13 at 13:19
  • ah, grr, I fell into that pit earlier. Thanks. – Bertfried Fauser Oct 1 '13 at 13:38
1

Do not use \pgfnodeparttextbox in normal \anchors but only in \savedanchor, \saveddimen or \savedmacro. There is no guarantee that the box is the same as when the node has been created as the \anchor definitions are first executed and evaluated after the node has been typeset.

In your case, you already have set up the appropriate macros \halftextheight and \halftextwidth that you can use for .5\ht\pgfnodeparttextbox and .5\wd\pgfnodeparttextbox. You just need to add \halftextdepth or something similar.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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