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, the
out' 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:
\pgfnodeparttextbox
in normal\anchor
s 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