% %%%%%%% % % From http://tex.stackexchange.com/questions/314053/how-to-declare-a-tikz-directory-or-group-of-keys/314065?noredirect=1#comment765927_314065 % \pgfkeys{ % /handlers/.is directory/.code={ % \pgfkeysedef{\pgfkeyscurrentpath}{ % \noexpand\pgfkeys{\pgfkeyscurrentpath/.cd,##1‌​} % } % } % } % %%%%%%% \ifx\pgfmathsign\relax% \tikzmath{ function sign(\x) { if (\x < 0) then { return -1; } else { if (\x > 0) then { return 1; } else { return 0; }; }; }; } \fi% \newif\iftrianglefitisosceles \newif\iftrianglefitbackground \tikzset{ triangle fit current style/.style={}, triangle fit current background style/.style={}, triangle fit/.unknown/.code={ % \message{triangle fit unknown:\pgfkeyscurrentkeyRAW=#1^^J} \let\trianglefitstorekey=\pgfkeyscurrentkeyRAW \edef\triangleExp{ \noexpand\tikzset{ /tikz/triangle fit current style/.append style={ \trianglefitstorekey=\noexpand#1 } } } \triangleExp %\pgfqkeys{/tikz}{} }, triangle fit/triangle sep/.initial=0.15em, triangle fit/triangle sep/.default=0.15em, triangle fit/top space/.initial=1.5ex, triangle fit/top space/.default=1.5ex, triangle fit/bottom space/.initial=0ex, triangle fit/bottom space/.default=0ex, triangle fit/top/.initial=, triangle fit/nodes/.initial=, triangle fit/no rounded corners/.style={/tikz/rounded corners=0pt}, every triangle fit/.style={ triangle sep=.15em, rounded corners=5pt, isosceles, }, triangle fit/isosceles/.is if=trianglefitisosceles, triangle fit/not isosceles/.style={isosceles=false}, triangle fit/bg/.code={ \tikzset{ triangle fit current background style/.style={#1}, } }, triangle fit/.code={ \tikzset{ /tikz/triangle fit current style/.style={}, /tikz/triangle fit/.cd, /tikz/every triangle fit, #1, } % \node[draw, /tikz/every triangle fit] {EEE} % \edef\currenttrianglestyle{\pgfkeysvalueof{/tikz/triangle fit/style}} % \message{\currenttrianglestyle} % \tikzset{ % triangle fit current style/.style=\currenttrianglestyle, % } % Compute the minimum and maxiumum slope, as well as the maximum y (i.e. height) for the triangle. \tikzmath{ coordinate \pt,\ttop; % int \found; % \found{top} = 0; % \found{bot} = 0; \ttop=([yshift=\pgfkeysvalueof{/tikz/triangle fit/top space}]\pgfkeysvalueof{/tikz/triangle fit/top}); \slopeleft = 0; \sloperight = 0; \maxdy = 0; } % Foreach loop over all nodes, which computes the max and min slopes and triangle height \edef\triangleFitItems{\pgfkeysvalueof{/tikz/triangle fit/nodes}} \foreach \i in \triangleFitItems{ \foreach \ii in {(\i.north east),(\i.south east),(\i.south west),(\i.north west)} { \tikzmath{ \pt = \ii; \dx = \ptx - \ttopx; \dx = \dx + \pgfkeysvalueof{/tikz/triangle fit/triangle sep} * sign(\dx); \dy = \ttopy - \pty; \dy = \dy + \pgfkeysvalueof{/tikz/triangle fit/triangle sep} * sign(\dy); \slope = \dx / \dy; if \slope > \sloperight then { \sloperight = \slope; }; if \slope < \slopeleft then { \slopeleft = \slope; }; if \dy > \maxdy then { \maxdy = \dy; }; } \global\let\sloperight\sloperight% \global\let\slopeleft\slopeleft% \global\let\maxdy\maxdy% % \message{\ii, ptx=\ptx, pty=\pty, dx=\dx, dy=\dy, slope=\slope, sloperight=\sloperight, slopeleft=\slopeleft, maxdy=\maxdy^^J} } } \tikzmath{ \maxdy = \maxdy + \pgfkeysvalueof{/tikz/triangle fit/bottom space}; } \iftrianglefitisosceles \tikzmath{ if -\sloperight < \slopeleft then { \slopeleft = -\sloperight; }; if -\slopeleft > \sloperight then { \sloperight = -\slopeleft; }; } \fi % Draw the triangle: \draw[/tikz/triangle fit current style] (\ttopx,\ttopy) -- +(\sloperight*\maxdy pt,-\maxdy pt) -- +(\slopeleft*\maxdy pt,-\maxdy pt) -- cycle; % Draw the background \begin{pgfonlayer}{background} \path[/tikz/triangle fit current background style] (\ttopx,\ttopy) -- +(\sloperight*\maxdy pt,-\maxdy pt) -- +(\slopeleft*\maxdy pt,-\maxdy pt) -- cycle; \end{pgfonlayer} } } \def\nodx{ node[draw, every triangle fit, triangle fit={top={\fittriangletop},nodes={\fittriangletop\foresteoption{fit these}}}] {nodes:\fittriangletop\foresteoption{fit these}} } % \forestset{ % % every triangle fit/.forward to=/tikz/every triangle fit, % every triangle fit/append/.forward to=/tikz/every triangle fit/append, % every triangle fit/style/.forward to=/tikz/every triangle fit/style, % declare toks={fit these}{}, % triangle fit whole subtree/.style={ % delay={ % temptoksa=, % for descendants={% % temptoksa+/.wrap pgfmath arg={,##1}{name()}, % }, % fit these/.register=temptoksa, % delay={ % % /utils/exec={ % % \pgfmathsetmacro{\fittriangletop}{name()} % % \message{^^JFIT THESE=\foresteoption{fit these}, NAME=\fittriangletop^^J} % % }, % % append after command={ % % \nodx % % }, % tikz+={ % \pgfmathsetmacro{\fittriangletop}{name()} % % \message{\foresteoption{fit these}} % \path[triangle fit={ % top=\fittriangletop.north, % nodes={\fittriangletop\foresteoption{fit these}}, % #1 % }]; % }, % }, % }, % }, % }