From 20355f9c01516429f9362ba19a6796e6c45aedf7 Mon Sep 17 00:00:00 2001 From: Jensen Date: Thu, 17 Aug 2017 16:48:43 +0200 Subject: [PATCH] correlation section started --- correlation-macros.tex | 234 + forest-compat.sty | 190 + forest-doc.sty | 240 + forest-lib-edges.sty | 74 + forest-lib-linguistics.sty | 133 + forest.sty | 7497 +++++++++++++++++++ growingwave.sty | 125 + justtrees.sty | 165 + main.tex | 243 +- oni-tree-defaults.sty | 35 + oni-trees.sty | 308 + tikzlibrarydecorations.growingwave.code.tex | 126 + tikzlibraryoni-squiggly.code.tex | 83 + tikzlibrarytree-triangle-fit.code.tex | 182 + tikzlibrarytriangle-fit.code.tex | 189 + 15 files changed, 9817 insertions(+), 7 deletions(-) create mode 100644 correlation-macros.tex create mode 100755 forest-compat.sty create mode 100755 forest-doc.sty create mode 100755 forest-lib-edges.sty create mode 100755 forest-lib-linguistics.sty create mode 100755 forest.sty create mode 100755 growingwave.sty create mode 100755 justtrees.sty create mode 100755 oni-tree-defaults.sty create mode 100755 oni-trees.sty create mode 100755 tikzlibrarydecorations.growingwave.code.tex create mode 100755 tikzlibraryoni-squiggly.code.tex create mode 100755 tikzlibrarytree-triangle-fit.code.tex create mode 100755 tikzlibrarytriangle-fit.code.tex diff --git a/correlation-macros.tex b/correlation-macros.tex new file mode 100644 index 0000000..714eaf7 --- /dev/null +++ b/correlation-macros.tex @@ -0,0 +1,234 @@ + +%%Macros +% This is the definition of meet_r +\def\meetR{% + \alignedmathop{% + \bigwedge% + }{% + \mathchoice% + {\bigwedge\mkern-0.5mu\smash{\raisebox{-0.9ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{R}}}}$}}}% + {\bigwedge\mkern-1.5mu\smash{\raisebox{-0.6ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{R}}}}$}}}% + {\bigwedge\mkern-2.25mu\smash{\raisebox{-0.3ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{R}}}}$}}}% + {\bigwedge\mkern-2.5mu\smash{\raisebox{-0.35ex}{$\resetstyle\mathlarger{{}_{\mathcal{R}}}$}}}% + }% +} +% +% This is the definition of join_k +\def\ijoin{% + \alignedmathop{% + \bigvee% + }{% + \mathchoice% + {\bigvee\mkern-6mu\smash{\raisebox{-0.9ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{K}}}}$}}}% + {\bigvee\mkern-5mu\smash{\raisebox{-0.6ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{K}}}}$}}}% + {\bigvee\mkern-2.25mu\smash{\raisebox{-0.3ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{K}}}}$}}}% + {\bigvee\mkern-2.5mu\smash{\raisebox{-0.35ex}{$\resetstyle\mathlarger{{}_{\mathcal{K}}}$}}}% + }% +} +\def\largeijoin{% + \alignedmathop{% + \bigvee% + }{% + \mathchoice% + {\bigvee\mkern-7mu\smash{\raisebox{-0.6ex}{$\resetstyle\mathlarger{{}_{\mathcal{K}}}$}}}% + {\bigvee\mkern-5mu\smash{\raisebox{-0.6ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{K}}}}$}}}% + {\bigvee\mkern-2.25mu\smash{\raisebox{-0.3ex}{$\resetstyle\mathlarger{\mathlarger{{}_{\mathcal{K}}}}$}}}% + {\bigvee\mkern-2.5mu\smash{\raisebox{-0.35ex}{$\resetstyle\mathlarger{{}_{\mathcal{K}}}$}}}% + }% +} + + + +%%For Tikz figures +%%%%% Custom pattern definition (not my code): +% defining the new dimensions + \newlength{\hatchspread} + \newlength{\hatchoffset} + \newlength{\hatchthickness} + % declaring the keys in tikz + \tikzset{ + hatchspread/.code={\setlength{\hatchspread}{#1}}, + hatchoffset/.code={\setlength{\hatchoffset}{#1}}, + hatchthickness/.code={\setlength{\hatchthickness}{#1}} + } + % setting the default values + \tikzset{ + hatchspread=.5cm, + hatchoffset=0.4pt, + hatchthickness=0.4pt + } + % declaring the pattern + \pgfdeclarepatternformonly[\hatchspread,\hatchthickness]% variables + {custom north east lines}% name + {\pgfqpoint{-2\hatchthickness}{-2\hatchthickness}}% lower left corner + {\pgfqpoint{\dimexpr\hatchspread+2\hatchthickness}{\dimexpr\hatchspread+2\hatchthickness}}% upper right corner + {\pgfqpoint{\hatchspread}{\hatchspread}}% tile size + {% shape description + \pgfsetlinewidth{\hatchthickness} + \pgfpathmoveto{\pgfqpoint{0pt}{\hatchoffset}} + \pgfpathlineto{\pgfqpoint{\dimexpr\hatchspread-\hatchoffset}{\hatchspread}} + \pgfpathmoveto{\pgfqpoint{\dimexpr\hatchspread-\hatchoffset}{0pt}} + \pgfpathlineto{\pgfqpoint{\dimexpr\hatchspread}{\hatchoffset}} + \pgfusepath{stroke} + } +%%%%% End custom pattern definition. + +%\pgfmathparse{\year+\time+\currenthour+\currentminute*\currentsecond} +\edef\rndseed{4101} %%%%% To choose a fixed seed +%\edef\rndseed{\pgfmathresult} %%%%% Random seed +\pgfmathsetseed{\rndseed} + +\def\cellw{.7cm} +\def\cellh{.8cm} +\def\minth{.15cm} +\def\vtpadding{.2cm} +\def\vbpadding{.1cm} +\def\hpadding{.05cm} +\def\nbnodes{4} +\def\minrand{0.3} +\def\borderh{0.2cm} + +\def\triangleArray#1#2{ + \foreach \i in {0,...,\nbnodes} {% + \node[inner sep=0pt,minimum height=\cellh, minimum width=\cellw, alias=#1-last, anchor=north west, xshift=\i*\cellw] (#1-\i) at #2 {}; + + % Magic coordinate calculations + % Fixed top position: + \pgfmathsetmacro{\tpos}{0} + % Random top position: + % \pgfmathsetmacro{\tpos}{rnd*(1-\minrand)+\minrand} + \pgfmathsetmacro{\trih}{rnd*(1-\minrand)+\minrand} + \def\tposformula{(\vtpadding+\tpos*(\cellh-\minth-\vtpadding-\vbpadding))} + \def\thformula{min(\trih*(\cellh-\tposformula-\vbpadding), \cellw*(1/.5555)*.5-2*\hpadding)} + % Triangle: + \draw #2 ++(\i*\cellw+.5*\cellw,{-\tposformula}) coordinate (#1-tt-\i) -- ++({.5555*\thformula},{-\thformula}) coordinate (#1-tr-\i) -- ++({-.5555*\thformula*2},0) coordinate (#1-tl-\i) -- cycle; + \coordinate (#1-tc-\i) at (barycentric cs:#1-tt-\i=1,#1-tr-\i=1,#1-tl-\i=1); + \coordinate (#1-tb-\i) at ($(#1-tl-\i)!.5!(#1-tr-\i)$); + } + + % \draw (#1-0.north west) ++(0,\borderh) -- ($(#1-last.north east)+(0,\borderh)$) -- (#1-last.south east) -- (#1-0.south west) -- cycle; + % \draw (#1-0.north west) -- (#1-last.north east); + + \draw (#1-last.north east) -- (#1-last.south east) -- (#1-0.south west) -- (#1-0.north west); + \draw[fill=black!7] (#1-0.north west) -- (#1-last.north east) -- ++(0,\borderh) -- ($(#1-0.north west)+(0,\borderh)$) -- cycle; + + \foreach \i in {1,...,\nbnodes} { + \draw (#1-\i.north west) -- (#1-\i.south west); + } +} + +%Leq for pequiv +\def\rleq{\mathrel{\sqsubseteq_{\kern0.15pt\rdom}}} +\def\rjoin{\mathrel{\vee_{\kern-0.25pt\rdom}}} +\def\rmeet{\mathrel{\wedge_{\kern0.15pt\rdom}}} +%\DeclareMathOperator*{\rbigwedge}{\bigwedge_\rdom} + + +%Macros for pequiv relations +\def\rdom{\mathscr{R}} +\def\equal{\textsf{Equal}} +\def\qmark{\textsf{Any}} + +%\def\rel{\mathit{\mathcal{R}}} +\def\rel{R} +\newcommand{\srel}[2]{\{#1_1 \mapsto \rel_1; \ldots; #1_{#2} \mapsto \rel_{#2}\}} +\newcommand{\sreljoin}[2]{\{#1_1 \mapsto \rel_1 \rjoin \rel'_1; \ldots; #1_{#2} \mapsto \rel_{#2} \rjoin \rel'_{#2} \}} +\newcommand{\srelmeet}[2]{\{#1_1 \mapsto \rel_1 \rmeet \rel'_1; \ldots; #1_{#2} \mapsto \rel_{#2} \rmeet \rel'_{#2} \}} +\newcommand{\sreli}[2]{\{#1_1 \mapsto \rel_1; \ldots; #1_i \mapsto \rel_i; \ldots; #1_{#2} \mapsto \rel_{#2}\}} +\newcommand{\srelitop}[3]{\{#1_1 \mapsto \qmark; \ldots; #1_i \mapsto #3; \ldots; #1_{#2} \mapsto \qmark\}} +\def\srelibot{\{f_1 \mapsto \equal; \ldots; f_i \mapsto \qmark; \ldots; f_n \mapsto \equal\}} + +\newcommand{\vrel}[2]{[#1_1 \mapsto \rel_1; \ldots; #1_{#2} \mapsto \rel_{#2}]} +\newcommand{\vreljoin}[2]{[#1_1 \mapsto \rel_1 \rjoin \rel'_1; \ldots; #1_{#2} \mapsto \rel_{#2} \rjoin \rel'_{#2}]} +\newcommand{\vrelmeet}[2]{[#1_1 \mapsto \rel_1 \rmeet \rel'_1; \ldots; #1_{#2} \mapsto \rel_{#2} \rmeet \rel'_{#2}]} +\newcommand{\vreli}[2]{[#1_1 \mapsto \rel_1; \ldots; #1_i \mapsto \rel_i; \ldots; #1_{#2} \mapsto \rel_{#2}]} +\newcommand{\vrelitop}[3]{[#1_1 \mapsto \qmark; \ldots; #1_i \mapsto #3; \ldots; #1_{#2} \mapsto \qmark]} + + +\newcommand{\arel}[1]{\langle #1 \rangle} +\newcommand{\aerel}[3]{\left\langle #1 \triangleright #2: \; #3 \right\rangle} +\newcommand{\aerelnoleftright}[3]{\langle #1 \triangleright #2: \; #3 \rangle} + +\newcommand{\rels}{\srel{f}{n}} +\newcommand{\relsi}{\sreli{f}{n}} +\newcommand{\relv}{\vrel{C}{n}} +\newcommand{\relvi}{\vreli{C}{n}} +\newcommand{\rela}{\arel{\rel}} +\newcommand{\relai}{\langle \rel_{\mathit{def}} \triangleright i \;: \; \rel_{\mathit{exc}} \rangle} +\def\relaitop{\langle \equal \triangleright i \;: \; \qmark \rangle} + +\newcommand{\srelv}[3]{\{#1_1 \mapsto #3_1; \ldots; #1_{#2} \mapsto #3_{#2}\}} +\newcommand{\vrelv}[3]{[#1_1 \mapsto #3_1; \ldots; #1_{#2} \mapsto #3_{#2}]} + +\newcommand{\semrel}[2]{\llbracket #1 \rrbracket^{#2}} + + +%Projections on pequiv +\def\fieldp{\textrm{\textsf{\emph{extr}}}_f} +\def\consp{\textrm{\textsf{\emph{extr}}}_C} +\def\allp{\textrm{\textsf{\emph{extr}}}_{\langle * \rangle}} +\def\cellp{\textrm{\textsf{\emph{extr}}}_{\langle i \rangle}} +\def\outp{\textrm{\textsf{\emph{extr}}}_{\langle * \setminus i \rangle}} + + +%Macros for paths +\def\pcell{\langle i \rangle} +\def\pstruct{.f} +\def\pvar{@C} +\def\pempty{\widehat{\varepsilon}} +\def\identical{\textsf{Identical}} +\def\incompatible{\textsf{Incompatible}} +\def\leftcase{\textsf{Left}} +\def\rightcase{\textsf{Right}} +\def\findl{\curlywedge} +\def\append{\dblcolon} + +%Macros for path operators: +%\DeclareMathOperator{\pproj}{\rightsquigarrow} +%\DeclareMathOperator{\pinj}{\curvearrowleft} + +%Macros for correlations +%\def\cor{\hat{\mathcal{C}}} +\def\cor{\mathscr{K}} +%\def\corv{\hat{c}} +\def\corv{\kappa} +\def\aleq{\mathrel{\hat{\sqsubseteq}}} +%\DeclareMathOperator*{\ajoin}{\hat{\bigvee}} +%\DeclareMathOperator*{\hatbigwedge}{\hat{\bigwedge}} +\def\acompose{\mathop{\ocircle}} +\def\raligned{\rel_{\aligned(\pi', \rho')}^{(\pi, \rho)}} +\def\ralignedc{\rel_{\aligned\corv}^{(\pi, \rho)}} +\def\ralignedv{\rel_{\aligned\corv_1}^{(\pi, \rho)}} +\def\ralignedw{\rel_{\aligned\corv_2}^{(\pi, \rho)}} + +%Macros for intra domains +\def\ileq{\sqsubseteq_{\mathcal{K}}} +%\def\ijoin{\bigvee_{\mathcal{K}}} +\def\justif{\Vvdash} +\def\aligned{\parallel} +\def\intracor{K} +\def\compose{\odot} + +%Macros for equations +\newcommand{\Ctransfer}[3]{\mathbb{C}^{#2}_{#3}(#1)} + +\def\inter{\mathcal{K}_p} +%Colors +%\definecolor{indianred}{rgb}{0.8, 0.36, 0.36} +\definecolor{iburg}{rgb}{0.75, 0.0, 0.2} + +% hat math variables + +\def\cptype{\ensuremath{\widehat{\Pi}}} +\def\cpath{\ensuremath{\widehat{\pi}}} +\def\crho{\ensuremath{\widehat{\rho}}} +\def\csigma{\ensuremath{\widehat{\sigma}}} +\def\calpha{\ensuremath{\widehat{\alpha}}} +\def\cbeta{\ensuremath{\widehat{\beta}}} +\def\cgamma{\ensuremath{\widehat{\gamma}}} +\def\cdelta{\ensuremath{\widehat{\delta}}} + +\def\kset{$\textrm{\emph{kill}}_\lambda$} +\def\kseti{$\textrm{\emph{kill}}_i$} +\def\ksettrue{$\textrm{\emph{kill}}_{\mathit{true}}$} +\def\dls{c_{\lambda}^s} diff --git a/forest-compat.sty b/forest-compat.sty new file mode 100755 index 0000000..4245f10 --- /dev/null +++ b/forest-compat.sty @@ -0,0 +1,190 @@ +% \CheckSum{12884} +% \iffalse meta-comment +% forest-index.dtx +%% `forest-compat' defines a compatibility layer of package `forest'. +%% +%% Copyright (c) 2015 Saso Zivanovic +%% (Sa\v{s}o \v{Z}ivanovi\'{c}) +%% saso.zivanovic@guest.arnes.si +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% +%% http://www.latex-project.org/lppl.txt +%% +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `author-maintained'. +%% +%% This file is a part of package `forest'. For the list of files +%% constituting the package see main source file of the package, +%% `forest.dtx', or the derived `forest.sty'. + +\ProvidesPackage{forest-compat} + +\def\forest@deprecated#1{% + \PackageWarning{forest}{Compatibility mode for #1}% +} +\forestset{@@deprecated/.code={\forest@deprecated{#1}}} +\def\forestcompat#1{\pgfqkeys{/forest/@compat}{#1}} +\forestcompat{ + silent/.style={\def\forest@deprecated##1{}}, + %%% begin listing region: compat_keys + most/.style={1.0-most}, + all/.style={1.0-all}, + none/.style={}, + 1.0-most/.style={ + 1.0-triangle,1.0-linear,1.0-nodewalk,1.0-ancestors, + 1.0-fittotree,1.0-for,1.0-forall + }, + 1.0-all/.style={ + 1.0-most, + 1.0-forstep,1.0-rotate,1.0-stages,1.0-name, + 2.0.2-all, + }, + 2.0.2-all/.style={ + 2.0.2-delayn,2.0.2-wrapnpgfmathargs, + }, + %%% end listing region: compat_keys + 1.0-triangle/.style={ + /forest/triangle/.style={ + @@deprecated={key "triangle" from v1.0.x. Use key "roof" from library "linguistics" instead}, + edge path'={% + (.north west)--(!u.south)--(.north east)--cycle + } + } + }, + 1.0-linear/.style={ + /forest/define long step={linear next}{autostep}{% + \forest@deprecated{nodewalk step "linear next" from v1.0. Use key "next node" instead.}% + \edef\forest@cn{\forest@node@linearnextid}}, + /forest/define long step={linear previous}{autostep}{% + \forest@deprecated{nodewalk step "linear previous" from v1.0. Use key "previous node" instead.}% + \edef\forest@cn{\forest@node@linearpreviousid}}, + }, + 1.0-nodewalk/.style={ + /forest/node walk/before walk/.style={}, + /forest/node walk/every step/.style={}, + /forest/node walk/after walk/.style={}, + /forest/node walk/.style={ + @@deprecated={key "node walk" from v1.0. Use key "nodewalk" instead.}, + /forest/node walk/before walk, + /forest/nodewalk/before walk/.style={/forest/node walk/before walk}, + /forest/nodewalk/every step/.style={/forest/node walk/every step}, + /forest/nodewalk/after walk/.style={/forest/node walk/after walk}, + /forest/nodewalk/node walk/.style={before walk,for nodewalk={####1,options={/forest/nodewalk/after walk}}{/forest/nodewalk/every step}}, + for nodewalk={##1,options={/forest/nodewalk/after walk}}{/forest/nodewalk/every step}, + }, + }, + 1.0-ancestors/.style={ + /forest/for ancestors'/.style={ + @@deprecated={key "for ancestors'" from v1.0.x. Use key "for current and ancestors" instead.}, + for current and ancestors={##1}}, + }, + 1.0-fittotree/.style={% + /tikz/fit to tree/.style={ + /forest/@@deprecated={key "/tikz/fit to tree" from v1.0.x. Use "/tikz/fit to=tree" instead.}, + inner sep=0pt,fit to=tree + } + }, + 1.0-for/.style={ + /forest/for/.code 2 args={% #1 = nodewalk, #2 = after walk keylist + \forest@deprecated{Key "for" from v1.0.x. Use key "for group" instead.}% + \forest@forthis{\forest@nodewalk{##1,options={##2}}{}}% + } + }, + 1.0-forall/.style={ + /forest/for all next/.style={ + @@deprecated={Key "for all next" from v1.0.x. Use key "for following siblings" instead.}, + for following siblings={##1}}, + /forest/for all previous/.style={ + @@deprecated={Key "for all previous" from v1.0.x. Use key "for preceding siblings" instead.}, + for preceding siblings={##1}}, + }, + 1.0-forstep/.code={% + \def\forest@forstepwrapper##1##2{% + \def\forest@nodewalk@config@everystep@method{independent}% + \def\forest@nodewalk@config@history@method{independent}% + \edef\forest@marshal{% + \def\noexpand\forest@nodewalk@config@oninvalid{compatfake}% + \unexpanded{\forest@Nodewalk{##1}{##2}}% + \def\noexpand\forest@cn{\forest@cn}% + \def\noexpand\forest@nodewalk@config@oninvalid{\forest@nodewalk@config@oninvalid}% + }\forest@marshal + }% + \def\forest@relatednode@option@compat@ignoreinvalidsteps##1{% + \forest@saveandrestoremacro\forest@nodewalk@oninvalid{% + \def\forest@nodewalk@oninvalid{compatfake}% + ##1% + }% + }% + }, + 1.0-rotate/.style={ + /forest/undef option=rotate, + rotate/.style={ + @@deprecate={Using non-autoforwarded key "rotate". Some keys, like "forked edges" and "folder", might produce a wrong result.}, + node options={rotate={##1}}, + }, + }, + 1.0-stages/.style={ + /forest/@@deprecated={Using v1.0.x "stages" style}, + /forest/stages/.style={ + process keylist=before typesetting nodes, + typeset nodes stage, + process keylist=before packing, + pack stage, + process keylist=before computing xy, + compute xy stage, + process keylist=before drawing tree, + draw tree stage, + }, + /forest/TeX={% + \def\forest@defstages##1{% + \def\forest@stages{% + begin forest, + for root'={ + process keylist register=default preamble, + process keylist register=preamble + }, + process keylist=given options, + ##1, + end forest + }% + }% + }, + }, + 1.0-name/.code={% + \forest@deprecated{key "name": using key "name" from v1.0.x, which does not enforce uniqueness. If you really need this, you're doing something wrong.}% + \def\forest@node@setname##1{% + \ifstrempty{##1}{}{% + \forestoeset{name}{##1}% + \csedef{forest@id@of@##1}{\forest@cn}% + }% + }% + \def\forest@node@setalias##1{% + \ifstrempty{##1}{}{% + \csedef{forest@id@of@##1}{\forest@cn}% + }% + }% + }, + 2.0.2-delayn/.style={ + /forest/delay@n/.style 2 args={ + @@deprecated={propagator "delay n" (it introduces two levels of hash doubling)}, + if={##1==1}{delay={##2}}{delay={delay@n/.wrap pgfmath arg={{####1}{##2}}{##1-1}}} + }, + }, + 2.0.2-wrapnpgfmathargs/.code={ + \def\forest@wrap@pgfmath@args@@@wrapandpasson{% + \forest@deprecated{handler "wrap n pgfmath args" (it introduces two levels of hash doubling)}% + \expandafter\expandafter\expandafter\def + \expandafter\expandafter\expandafter\forest@wrapped + \expandafter\expandafter\expandafter{% + \expandafter\forest@wrap@code\forest@wrap@args}% + \expandafter\pgfkeysalso\expandafter{\expandafter\pgfkeyscurrentpath\expandafter=\expandafter{\forest@wrapped}}% + }% + }, +} +\expandafter\forestcompat\expandafter{\forest@compat} diff --git a/forest-doc.sty b/forest-doc.sty new file mode 100755 index 0000000..70f8456 --- /dev/null +++ b/forest-doc.sty @@ -0,0 +1,240 @@ +%% forest-doc.sty +%% `forest-doc.sty` is an auxiliary package needed to compile the documentation of package `forest`. +%% +%% Copyright (c) 2015 Saso Zivanovic +%% (Sa\v{s}o \v{Z}ivanovi\'{c}) +%% saso.zivanovic@guest.arnes.si +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% +%% http://www.latex-project.org/lppl.txt +%% +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `author-maintained'. +%% +%% This file is a part of package `forest'. For the list of files +%% constituting the package see main source file of the package, +%% `forest.dtx', or the derived `forest.sty'. +%% +\ProvidesPackage{forest-doc} +\RequirePackage{lstdoc} +\RequirePackage{pgfkeys} +\RequirePackage{forest-index} +% if you want index support, load package "forest-index", but later + +\lstset{language={[LaTeX]TeX},tabsize=4,gobble=2,% + basicstyle=\small\ttfamily,basewidth=0.51em,boxpos=c,pointstyle=\pstyle,moredelim=[is][\pstyle]{~}{~}} +%\lst@InstallKeywords{p}{point}{pointstyle}\relax{keywordstyle}{}ld +\def\pstyle{\color{darkgreen}} +\def\itemnosep{\vspace{-1.4ex}} +\lstset{ + rangebeginprefix=\ \ \%\%\%\ begin\ listing\ region:\ , + rangebeginsuffix=, + rangeendprefix=\ \ \%\%\%\ end\ listing\ region:\ , + rangeendsuffix=, + includerangemarker=false, + keepspaces=true, +} +\newcommand\lstinputregion[3][]{\lstinputlisting[linerange=#3-#3,#1]{#2}} +\def\lst@outputspace{{\ifx\lst@bkgcolor\empty\color{white}\else\lst@bkgcolor\fi\lst@visiblespace}}% this works for acroread, but not for atril :-( + +\lstnewenvironment{forestexample}[1][]{% + \PackageWarning{forest-doc}{Compiling example}{}% + \global\let\lst@intname\@empty + \gdef\lst@sample{}% + \def\forestexample@layout{tree on left}% + \def\forestexample@treebin{box}% + \pgfqkeys{/forestexample}{label format,#1}% + \pgfkeysgetvalue{/forestexample/counter}\forestexample@temp + \ifdefempty\forestexample@temp{}{\addtocounter{\forestexample@temp}{1}}% + \setbox\lst@samplebox=\hbox\bgroup + \pgfkeysvalueof{/forestexample/tree prefix}% + \lst@BeginAlsoWriteFile{\jobname.tmp}% +}{% + \lst@EndWriteFile + \pgfkeysvalueof{/forestexample/tree suffix}% + \egroup + \global\setbox\codebox=\box\lst@samplebox + \global\setbox + \treebox + \csname forestexample@treebin@\forestexample@treebin\endcsname + \pgfkeys{/forestexample/do layout/.expanded=\forestexample@layout}% +} +\pgfqkeys{/forestexample}{% + .unknown/.code={\lstset{\pgfkeyscurrentname={#1}}}, + index/.code={\indexex[not print]{#1}}, + index>/.code={\indexex[not print]>{#1}}, + code prefix/.code={\gdef\lst@sample{#1}}, + tree prefix/.initial={}, + tree suffix/.initial={}, + counter/.initial=lstlisting, + no label/.style={counter={}}, + label format/.store in=\@currentlabel, + label format/.default={\arabic{\pgfkeysvalueof{/forestexample/counter}}}, + tree width/.initial={\dimexpr\linewidth-\wd\codebox- + \glueexpr\pgfkeysvalueof{/forestexample/center skip}\relax\relax}, + layout/.store in=\forestexample@layout, + tree bin/.store in=\forestexample@treebin, + do layout/.is choice, + do layout/export/.code={% + \pgfkeysgetvalue{/forestexample/counter}\forestexample@temp + \ifdefempty\forestexample@temp{}{\addtocounter{\forestexample@temp}{-1}}% + }, + left skip/.initial={\glueexpr 0pt plus .4\linewidth minus \marginparsep + 0pt minus \@totalleftmargin + 0pt minus .75\marginparwidth}, + center skip/.initial={3em plus 0.1\linewidth minus 2em}, + right skip/.initial={0pt plus .4\linewidth}, + tree left skip/.initial=0pt, + tree right skip/.initial=0pt, + code left skip/.initial=0pt, + code right skip/.initial=0pt, + label y offset/.initial={\height-1ex}, % looks better to me this way + do layout/tree on left/.code={% + \begin{list}{}{\leftmargin 0pt} + \item + \@tempdima=\ifdim\totalht\treebox>\totalht\codebox + \dimexpr0.5 \totalht\treebox\relax + \else + \dimexpr0.5 \totalht\codebox\relax + \fi + \mbox{% + \mbox{\hbox to \linewidth{% + \hskip\pgfkeysvalueof{/forestexample/left skip}\relax + \textvcenter{\box\treebox}% + \hskip\pgfkeysvalueof{/forestexample/center skip}\relax + \hbox{\hskip-\@totalleftmargin\box\codebox\hskip\@totalleftmargin}% + \hskip\pgfkeysvalueof{/forestexample/right skip}\relax + }}% + \forestexample@label + }% + \end{list} + }, + v sep/.initial={1ex}, + align/.initial=center, + do layout/tree on top/.code={% + \begin{list}{}{\leftmargin 0pt \parsep 0pt \itemsep \pgfkeysvalueof{/forestexample/v sep}\relax} + \item \forestexample@align{tree}\forestexample@label + \item \forestexample@align{code} + \end{list} + }, + do layout/tree on bottom/.code={% + \begin{list}{}{\leftmargin 0pt \parsep 0pt \itemsep \pgfkeysvalueof{/forestexample/v sep}\relax} + \item \forestexample@align{code}\forestexample@label + \item \forestexample@align{tree} + \end{list} + }, + do layout/only tree/.code={% + \forestexample@align{tree}\forestexample@label + }, + do layout/only code/.code={% + \forestexample@align{code}\forestexample@label + }, +} +\newbox\treebox +\newbox\codebox +\def\forestexample@treebin@box{% + \hbox{\lst@sampleInput}% +} +\def\forestexample@treebin@minipage{% + \hbox{% + \begin{minipage}{\pgfkeysvalueof{/forestexample/tree width}}% + \lst@sampleInput + \end{minipage}% + }% +} +\def\forestexample@label{% + \pgfkeysgetvalue{/forestexample/counter}\forestexample@temp + \ifdefempty\forestexample@temp{}{% + \makebox[0pt][l]{% + \hskip-\linewidth + \hskip-\@totalleftmargin + \hskip\textwidth + \hskip\marginparsep + \raisebox + {\dimexpr\@tempdima+\depth-\pgfkeysvalueof{/forestexample/label y offset}}% + {\hbox to 0pt{\scriptsize(\@currentlabel)}}% + }% + }% +} +\def\forestexample@align#1{% + \pgfkeysgetvalue{/forestexample/align}\forestexample@temp + \mbox{\hbox to \linewidth{% + \csname forestexample@align@left@\forestexample@temp\endcsname + \hspace*{\pgfkeysvalueof{/forestexample/#1 left skip}}% + \mbox{\expandafter\box\csname #1box\endcsname}% + \hspace*{\pgfkeysvalueof{/forestexample/#1 right skip}}% + \csname forestexample@align@right@\forestexample@temp\endcsname + }}% +} +\def\forestexample@align@left@left{} +\def\forestexample@align@right@left{} +\def\forestexample@align@left@right{\hfill} +\def\forestexample@align@right@right{} +\def\forestexample@align@left@center{\hfill} +\def\forestexample@align@right@center{\hfill} +\newcommand\forestexampleimport[1][]{% + \def\forestexample@layout{tree on left}% + \pgfkeysgetvalue{/forestexample/counter}\forestexample@temp + \ifdefempty\forestexample@temp{}{\addtocounter{\forestexample@temp}{1}}% + \pgfqkeys{/forestexample}{% + label format, + do layout/.expanded=\forestexample@layout + }% +} + +\def\totalht#1{\dimexpr\ht#1 + \dp#1\relax} +\def\textvcenter#1{\raisebox{\dimexpr .5\depth-.5\height}{#1}} + +% For some reason, lstdoc's version kills all spaces in defaults ... +\def\lst@syntaxlabel@#1>#2\relax + %{\edef\lst@temp{\zap@space#2 \@empty}} + {\edef\lst@temp{#2}} + + + + +\def\getforestversion#1/#2/#3 v#4 #5\getforestversion{v#4} +\edef\forestversion{% +\expandafter\expandafter\expandafter\getforestversion + \csname ver@forest.sty\endcsname\getforestversion} + +\def\settodayfromforestdateA#1/#2/#3 v#4 #5\settodayfromforestdateA{\def\year{#1}\def\month{#2}\def\day{#3}} +\def\settodayfromforestdate{\expandafter\expandafter\expandafter\settodayfromforestdateA\csname ver@forest.sty\endcsname\settodayfromforestdateA} + +\def\TikZ;{{\rm Ti\emph{k}Z}} +\def\PGF;{\textsc{pgf}} +\def\foRest;{\textsc{Forest}} +\def\FoRest;{\textsc{Forest}} + +\let\keyname\texttt +\newcommand\cmdname[1]{\texttt{\char\escapechar#1}} + +\gdef\greaterthan{>} +\def\gobbleone#1{} + +\newcommand{\Repeat}[1]{% from tex.se http://tex.stackexchange.com/a/16194/16819 + \expandafter\@Repeat\expandafter{\the\numexpr #1\relax}% +} +\def\@Repeat#1{% + \ifnum#1>0 + \expandafter\@@Repeat\expandafter{\the\numexpr #1-1\expandafter\relax\expandafter}% + \else + \expandafter\@gobble + \fi +} +\def\@@Repeat#1#2{% + \@Repeat{#1}{#2}#2% +} +\def\spaces#1{\Repeat{#1}\space} + + +%%% Local Variables: +%%% mode: latex +%%% fill-column: 100 +%%% TeX-command-default: "Make PDF" +%%% TeX-master: "forest-doc" +%%% End: diff --git a/forest-lib-edges.sty b/forest-lib-edges.sty new file mode 100755 index 0000000..5c737aa --- /dev/null +++ b/forest-lib-edges.sty @@ -0,0 +1,74 @@ +%% +%% This is file `forest-lib-edges.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% forest-libs.dtx (with options: `edges') +%% +%% `forest-libs' is a collection of libraries for package `forest'. +%% +%% Copyright (c) 2015 Saso Zivanovic +%% (Sa\v{s}o \v{Z}ivanovi\'{c}) +%% saso.zivanovic@guest.arnes.si +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% +%% http://www.latex-project.org/lppl.txt +%% +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `author-maintained'. +%% +%% This file is a part of package `forest'. For the list of files +%% constituting the package see main source file of the package, +%% `forest.dtx', or the derived `forest.sty'. +%% +\RequirePackage{forest} +\ProvidesForestLibrary{edges}[2015/11/14 v0.1] +\forestset{ + declare dimen={fork sep}{0.5em}, + forked edge/.style={ + edge={rotate/.pgfmath=grow()}, + edge path'={(!u.parent anchor) -- ++(\forestoption{fork sep},0) |- (.child anchor)}, + }, + forked edges/.style={ + for tree={parent anchor=children}, + for descendants={child anchor=parent,forked edge} + }, +} +\forestset{ + declare dimen register=folder indent, + folder indent=.45em, + folder/.style={ + parent anchor=parent last, + anchor=parent first, + calign=child, + calign primary child=1, + for children={ + child anchor=parent, + anchor=parent first, + edge={rotate/.pgfmath=grow()}, + edge path'/.expanded={ + ([xshift=\forestregister{folder indent}]!u.parent anchor) |- (.child anchor) + }, + }, + after packing node={ + if n children=0{}{ + tempdiml=l_sep()-l("!1"), + tempdims={-abs(max_s("","")-min_s("",""))-s_sep()}, + for children={ + l+=tempdiml, + s+=tempdims()*(reversed()-0.5)*2, + }, + }, + }, + } +} +\endinput +%% +%% End of file `forest-lib-edges.sty'. diff --git a/forest-lib-linguistics.sty b/forest-lib-linguistics.sty new file mode 100755 index 0000000..9632361 --- /dev/null +++ b/forest-lib-linguistics.sty @@ -0,0 +1,133 @@ +%% +%% This is file `forest-lib-linguistics.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% forest-libs.dtx (with options: `linguistics') +%% +%% `forest-libs' is a collection of libraries for package `forest'. +%% +%% Copyright (c) 2015 Saso Zivanovic +%% (Sa\v{s}o \v{Z}ivanovi\'{c}) +%% saso.zivanovic@guest.arnes.si +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% +%% http://www.latex-project.org/lppl.txt +%% +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `author-maintained'. +%% +%% This file is a part of package `forest'. For the list of files +%% constituting the package see main source file of the package, +%% `forest.dtx', or the derived `forest.sty'. +%% +\RequirePackage{forest} +\ProvidesForestLibrary{linguistics}[2015/11/14 v0.1] +\forestset{ + libraries/linguistics/defaults/.style={ + default preamble={ + sn edges, + baseline, + for tree={align=center}, + }, + }, +} +\forestset{ + define long step={c-commanded}{style}{branch'={siblings,descendants}}, + define long step={c-commanders}{style}{while nodewalk valid={parent}{siblings,fake=parent}}, +} +\forestset{ + sn edges/.style={ + for tree={ + parent anchor=children, child anchor=parent + } + }, +} +\forestset{ + roof/.style={edge path'={% + (.parent first)--(!u.children)--(.parent last)--cycle + } + }, +} +\forestset{ + nice empty nodes/.style={ + for tree={calign=fixed edge angles}, + delay={where content={}{shape=coordinate,for parent={ + for children={anchor=north}}}{}} + }, +} +\providecommand\text[1]{\mbox{\scriptsize#1}} +\forestset{ + draw brackets compact/.code={\let\drawbracketsspace\relax}, + draw brackets wide/.code={\let\drawbracketsspace\space}, + draw brackets/.style={ + for tree'={ + TeX={[% + \edef\forestdrawbracketscontentformat{\foresteoption{content format}}% + }, + if n children=0{ + TeX={\drawbracketsspace\forestdrawbracketscontentformat\drawbracketsspace} + }{ + TeX={\textsubscript{\text{\forestdrawbracketscontentformat}}\drawbracketsspace} + }, + }{ + TeX={]\drawbracketsspace}, + } + }, + draw brackets wide +} +\newbox\standardnodestrutbox +\setbox\standardnodestrutbox=\hbox to 0pt{\phantom{\forestOve{standard node}{content}}} +\def\standardnodestrut{\copy\standardnodestrutbox} +\forestset{ + GP1/.style 2 args={ + for n={1}{baseline}, + s sep=0pt, l sep=0pt, + for descendants={ + l sep=0pt, l={#1}, + anchor=base,calign=first,child anchor=north, + inner xsep=1pt,inner ysep=2pt,outer sep=0pt,s sep=0pt, + }, + delay={ + if content={}{phantom}{for children={no edge}}, + for tree={ + if content={O}{tier=OR}{}, + if content={R}{tier=OR}{}, + if content={N}{tier=N}{}, + if content={x}{ + tier=x,content={$\times$},outer xsep={#2}, + for tree={calign=center}, + for descendants={content format={\noexpand\standardnodestrut\forestoption{content}}}, + before drawing tree={outer xsep=0pt,delay={typeset node}}, + s sep=4pt + }{}, + }, + }, + before drawing tree={where content={}{parent anchor=center,child anchor=center}{}}, + }, + GP1/.default={5ex}{8.0pt}, + associate/.style={% + tikz+={\draw[densely dotted](!)--(!#1);}}, + spread/.style={ + before drawing tree={tikz+={\draw[dotted](!)--(!#1);}}}, + govern/.style={ + before drawing tree={tikz+={\draw[->](!)--(!#1);}}}, + p-govern/.style={ + before drawing tree={tikz+={\draw[->](.north) to[out=150,in=30] (!#1.north);}}}, + no p-govern/.style={ + before drawing tree={tikz+={\draw[->,loosely dashed](.north) to[out=150,in=30] (!#1.north);}}}, + encircle/.style={before drawing tree={circle,draw,inner sep=0pt}}, + fen/.style={pin={[font=\footnotesize,inner sep=1pt,pin edge=<-]10:\textsc{Fen}}}, + el/.style={content=\textsc{\textbf{##1}}}, + head/.style={content=\textsc{\textbf{\underline{##1}}}} +} +\endinput +%% +%% End of file `forest-lib-linguistics.sty'. diff --git a/forest.sty b/forest.sty new file mode 100755 index 0000000..80f5b98 --- /dev/null +++ b/forest.sty @@ -0,0 +1,7497 @@ +%% +%% This is file `forest.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% forest.dtx +%% +%% `forest' is a `pgf/tikz'-based package for drawing (linguistic) trees. +%% +%% Copyright (c) 2015 Saso Zivanovic +%% (Sa\v{s}o \v{Z}ivanovi\'{c}) +%% saso.zivanovic@guest.arnes.si +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% +%% http://www.latex-project.org/lppl.txt +%% +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `author-maintained'. +%% +%% This work consists of the following files: +%% - forest.dtx: central sources (with rudimentary implementation documentation) +%% - forest-libs.dtx: sources and documentation for libraries +%% + forest-compat.sty: sources/runtime for compatibility mode +%% - forest.ins: produces derived runtime .sty files +%% + forest.sty: main package +%% + forest-lib-*.sty: libraries (for the list, see forest.ins) +%% - forest-doc.tex: central documentation +%% - forest-doc.sty: private package needed to compile the documentation +%% - forest-index.dtx: sources of indexing package used in the documentation, +%% and also part of the documentation itself +%% - forest-doc.ins: produces derived .sty files needed to compile the documentation +%% - forest-index.sty +%% - forest-doc.ist: index style file needed to compile the documentation +%% - forest.pdf: documentation of core package implementation +%% - forest-doc.pdf: user's guide +%% - README +%% - LICENCE +%% To use the package, only the files marked with + need to be installed. +%% +\ProvidesPackage{forest}[2016/04/09 v2.0.3 Drawing (linguistic) trees] + +\RequirePackage{tikz}[2013/12/13] +\usetikzlibrary{shapes} +\usetikzlibrary{fit} +\usetikzlibrary{calc} +\usepgflibrary{intersections} + +\RequirePackage{pgfopts} +\RequirePackage{etoolbox}[2010/08/21] +\RequirePackage{elocalloc}% for \locbox +\RequirePackage{environ} +\RequirePackage{xparse} + + +\pgfkeys{/forest/.is family} +\def\forestset#1{\pgfqkeys{/forest}{#1}} +\newif\ifforest@external@ +\newif\ifforesttikzcshack +\newif\ifforest@install@keys@to@tikz@path@ +\newif\ifforestdebugnodewalks +\newif\ifforestdebugdynamics +\def\forest@compat{} +\forestset{package@options/.cd, + external/.is if=forest@external@, + tikzcshack/.is if=foresttikzcshack, + tikzinstallkeys/.is if=forest@install@keys@to@tikz@path@, + compat/.store in=\forest@compat, + compat/.default=most, + .unknown/.code={% load library + \eappto\forest@loadlibrarieslater{% + \noexpand\useforestlibrary{\pgfkeyscurrentname}% + \noexpand\forestapplylibrarydefaults{\pgfkeyscurrentname}% + }% + }, + debug/.code={\pgfqkeys{/forest/package@options/debug}{#1}}, + debug/.default={nodewalks,dynamics}, + debug/nodewalks/.is if=forestdebugnodewalks, + debug/dynamics/.is if=forestdebugdynamics, +} +\forest@install@keys@to@tikz@path@true +\foresttikzcshacktrue +\def\forest@loadlibrarieslater{} +\AtEndOfPackage{\forest@loadlibrarieslater} +\NewDocumentCommand\useforestlibrary{s O{} m}{% + \def\useforestlibrary@@##1{\useforestlibrary@{#2}{##1}}% + \forcsvlist\useforestlibrary@@{#3}% + \IfBooleanT{#1}{\forestapplylibrarydefaults{#3}}% +} +\def\useforestlibrary@#1#2{\RequirePackage[#1]{forest-lib-#2}} +\def\forestapplylibrarydefaults#1{\forcsvlist\forestapplylibrarydefaults@{#1}} +\def\forestapplylibrarydefaults@#1{\forestset{libraries/#1/defaults/.try}} +\NewDocumentCommand\ProvidesForestLibrary{m O{}}{\ProvidesPackage{forest-lib-#1}[#2]} +\ProcessPgfPackageOptions{/forest/package@options} +\def\forest@patch#1#2#3#4#5{% + % #1 = cs to be patched + % %2 = purpose of the patch + % #3 = macro arguments + % #4 = original code + % #5 = patched code + \csdef{forest@original@#1}#3{#4}% + \csdef{forest@patched@#1}#3{#5}% + \ifcsequal{#1}{forest@original@#1}{% + \csletcs{#1}{forest@patched@#1}% + }{% + \ifcsequal{#1}{forest@patched@#1}{% all is good, the patch is in! + }{% + \PackageWarning{forest}{Failed patching '\expandafter\string\csname #1\endcsname'. Purpose of the patch: #2}% + }% + }% +} +\forest@patch{pgfgettransform}{fix a leaking space}{#1}{% + \edef#1{{\pgf@pt@aa}{\pgf@pt@ab}{\pgf@pt@ba}{\pgf@pt@bb}{\the\pgf@pt@x}{\the\pgf@pt@y}} +}{% + \edef#1{{\pgf@pt@aa}{\pgf@pt@ab}{\pgf@pt@ba}{\pgf@pt@bb}{\the\pgf@pt@x}{\the\pgf@pt@y}}% +} +\long\def\@escapeif#1#2\fi{\fi#1} +\long\def\@escapeifif#1#2\fi#3\fi{\fi\fi#1} +\long\def\@escapeififif#1#2\fi#3\fi#4\fi{\fi\fi\fi#1} +\def\newloop#1{% + \count@=\escapechar + \escapechar=-1 + \expandafter\newloop@parse@loopname\string#1\newloop@end + \escapechar=\count@ +}% +{\lccode`7=`l \lccode`8=`o \lccode`9=`p + \lowercase{\gdef\newloop@parse@loopname#17889#2\newloop@end{% + \edef\newloop@marshal{% + \noexpand\csdef{#1loop#2}####1\expandafter\noexpand\csname #1repeat#2\endcsname{% + \noexpand\csdef{#1iterate#2}{####1\relax\noexpand\expandafter\expandafter\noexpand\csname#1iterate#2\endcsname\noexpand\fi}% + \expandafter\noexpand\csname#1iterate#2\endcsname + \let\expandafter\noexpand\csname#1iterate#2\endcsname\relax + }% + }% + \newloop@marshal + }% + }% +}% +\def\newsafeloop#1{% + \csdef{safeloop@#1}##1\saferepeat{% + \edef\safeloop@marshal{% + \noexpand\csdef{safeiterate@#1}{% + \unexpanded{##1}\relax + \noexpand\expandafter + \expandonce{\csname safeiterate@#1\endcsname}% + \noexpand\fi + }% + }\safeloop@marshal + \csuse{safeiterate@#1}% + \advance\noexpand\safeloop@depth-1\relax + \cslet{safeiterate@#1}\relax + }% +}% +\newcount\safeloop@depth +\def\safeloop{% + \advance\safeloop@depth1 + \ifcsdef{safeloop@\the\safeloop@depth}{}{\expandafter\newsafeloop\expandafter{\the\safeloop@depth}}% + \csdef{safeloopn@\the\safeloop@depth}{0}% + \csuse{safeloop@\the\safeloop@depth}% + \csedef{safeloopn@\the\safeloop@depth}{\number\numexpr\csuse{safeloopn@\the\safeloop@depth}+1}% +} +\let\saferepeat\fi +\def\safeloopn{\csuse{safeloopn@\the\safeloop@depth}}% +\def\newsafeRKloop#1{% + \csdef{safeRKloop@#1}##1\safeRKrepeat{% + \edef\safeRKloop@marshal{% + \noexpand\csdef{safeRKiterate@#1}{% + \unexpanded{##1}\relax + \noexpand\expandafter + \expandonce{\csname safeRKiterate@#1\endcsname}% + \noexpand\fi + }% + }\safeRKloop@marshal + \csuse{safeRKiterate@#1}% + \advance\noexpand\safeRKloop@depth-1\relax + \cslet{safeRKiterate@#1}\relax + }% + \expandafter\newif\csname ifsafeRKbreak@\the\safeRKloop@depth\endcsname +}% +\newcount\safeRKloop@depth +\def\safeRKloop{% + \advance\safeRKloop@depth1 + \ifcsdef{safeRKloop@\the\safeRKloop@depth}{}{\expandafter\newsafeRKloop\expandafter{\the\safeRKloop@depth}}% + \csdef{safeRKloopn@\the\safeRKloop@depth}{0}% + \csuse{safeRKbreak@\the\safeRKloop@depth false}% + \csuse{safeRKloop@\the\safeRKloop@depth}% + \csedef{safeRKloopn@\the\safeRKloop@depth}{\number\numexpr\csuse{safeRKloopn@\the\safeRKloop@depth}+1}% +} +\let\safeRKrepeat\fi +\def\safeRKloopn{\csuse{safeRKloopn@\the\safeRKloop@depth}}% +\newloop\forest@loop +\newdimen\forest@temp@dimen +\newcount\forest@temp@count +\newcount\forest@n +\newif\ifforest@temp +\newcount\forest@temp@global@count +\newtoks\forest@temp@toks +\def\etotoks#1#2{\edef\pot@temp{#2}\expandafter#1\expandafter{\pot@temp}} +\def\apptotoks#1#2{\expandafter#1\expandafter{\the#1#2}} +\long\def\lapptotoks#1#2{\expandafter#1\expandafter{\the#1#2}} +\def\eapptotoks#1#2{\edef\pot@temp{#2}\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{\expandafter\the\expandafter#1\pot@temp}} +\def\pretotoks#1#2{\toks@={#2}\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{\expandafter\the\expandafter\toks@\the#1}} +\def\epretotoks#1#2{\edef\pot@temp{#2}\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{\expandafter\pot@temp\the#1}} +\def\gapptotoks#1#2{\expandafter\global\expandafter#1\expandafter{\the#1#2}} +\def\xapptotoks#1#2{\edef\pot@temp{#2}\expandafter\expandafter\expandafter\global\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{\expandafter\the\expandafter#1\pot@temp}} +\def\gpretotoks#1#2{\toks@={#2}\expandafter\expandafter\expandafter\global\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{\expandafter\the\expandafter\toks@\the#1}} +\def\xpretotoks#1#2{\edef\pot@temp{#2}\expandafter\expandafter\expandafter\global\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{\expandafter\pot@temp\the#1}} +\def\expandnumberarg#1#2{\expandafter#1\expandafter{\number#2}} +\def\expandtwonumberargs#1#2#3{% + \expandafter\expandtwonumberargs@\expandafter#1\expandafter{\number#3}{#2}} +\def\expandtwonumberargs@#1#2#3{% + \expandafter#1\expandafter{\number#3}{#2}} +\def\expandthreenumberargs#1#2#3#4{% + \expandafter\expandthreenumberargs@\expandafter#1\expandafter{\number#4}{#2}{#3}} +\def\expandthreenumberargs@#1#2#3#4{% + \expandafter\expandthreenumberargs@@\expandafter#1\expandafter{\number#4}{#2}{#3}} +\def\expandthreenumberargs@@#1#2#3#4{% + \expandafter#1\expandafter{\number#4}{#2}{#3}} +\def\forest@convert@others@to@underscores#1#2{% + \def\forest@cotu@result{}% + \forest@cotu@first#1\forest@end + \let#2\forest@cotu@result +} +\def\forest@cotu{% + \let\forest@cotu@have@num\forest@cotu@have@alpha + \futurelet\forest@cotu@nextchar\forest@cotu@checkforspace +} +\def\forest@cotu@first{% + \let\forest@cotu@have@num\forest@cotu@haveother + \futurelet\forest@cotu@nextchar\forest@cotu@checkforspace +} +\def\forest@cotu@checkforspace{% + \expandafter\ifx\space\forest@cotu@nextchar + \let\forest@cotu@next\forest@cotu@havespace + \else + \let\forest@cotu@next\forest@cotu@nospace + \fi + \forest@cotu@next +} +\def\forest@cotu@havespace#1{% + \appto\forest@cotu@result{_}% + \forest@cotu#1% +} +\def\forest@cotu@nospace{% + \ifx\forest@cotu@nextchar\forest@end + \@escapeif\@gobble + \else + \@escapeif\forest@cotu@nospaceB + \fi +} +\def\forest@cotu@nospaceB#1{% + \ifcat#1a% + \let\forest@cotu@next\forest@cotu@have@alpha + \else + \if!\ifnum9<1#1!\fi + \let\forest@cotu@next\forest@cotu@have@num + \else + \let\forest@cotu@next\forest@cotu@haveother + \fi + \fi + \forest@cotu@next#1% +} +\def\forest@cotu@have@alpha#1{% + \appto\forest@cotu@result{#1}% + \forest@cotu +} +\def\forest@cotu@haveother#1{% + \appto\forest@cotu@result{_}% + \forest@cotu +} +\def\forest@listedel#1#2{% #1 = list, #2 = item + \edef\forest@marshal{\noexpand\forest@listdel\noexpand#1{#2}}% + \forest@marshal +} +\def\forest@listcsdel#1#2{% + \expandafter\forest@listdel\csname #1\endcsname{#2}% +} +\def\forest@listcsedel#1#2{% + \expandafter\forest@listedel\csname #1\endcsname{#2}% +} +\edef\forest@restorelistsepcatcode{\noexpand\catcode`|\the\catcode`|\relax}% +\catcode`\|=3 +\gdef\forest@listdel#1#2{% + \def\forest@listedel@A##1|#2|##2\forest@END{% + \forest@listedel@B##1|##2\forest@END%| + }% + \def\forest@listedel@B|##1\forest@END{%| + \def#1{##1}% + }% + \expandafter\forest@listedel@A\expandafter|#1\forest@END%| +} +\forest@restorelistsepcatcode +\def\forest@strip@braces#1{% + \forest@strip@braces@A#1\forest@strip@braces@preend\forest@strip@braces@end +} +\def\forest@strip@braces@A#1#2\forest@strip@braces@end{% + #1\ifx\forest@strip@braces@preend#2\else\@escapeif{\forest@strip@braces@A#2\forest@strip@braces@end}\fi +} +\def\forest@copycommandkey#1#2{% copies command of #1 into #2 + \pgfkeysifdefined{#1/.@cmd}{}{% + \PackageError{forest}{Key #1 is not a command key}{}% + }% + \pgfkeysgetvalue{#1/.@cmd}\forest@temp + \pgfkeyslet{#2/.@cmd}\forest@temp + \pgfkeysifdefined{#1/.@args}{% + \pgfkeysgetvalue{#1/.@args}\forest@temp + \pgfkeyslet{#2/.@args}\forest@temp + }{}% + \pgfkeysifdefined{#1/.@body}{% + \pgfkeysgetvalue{#1/.@body}\forest@temp + \pgfkeyslet{#2/.@body}\forest@temp + }{}% + \pgfkeysifdefined{#1/.@@body}{% + \pgfkeysgetvalue{#1/.@@body}\forest@temp + \pgfkeyslet{#2/.@@body}\forest@temp + }{}% + \pgfkeysifdefined{#1/.@def}{% + \pgfkeysgetvalue{#1/.@def}\forest@temp + \pgfkeyslet{#2/.@def}\forest@temp + }{}% +} +\forestset{ + copy command key/.code 2 args={\forest@copycommandkey{#1}{#2}}, + autoforward/.code 2 args={\forest@autoforward{#1}{#2={#1={##1}}}{true}}, + autoforward'/.code 2 args={\forest@autoforward{#1}{#2-=#1,#2={#1={##1}}}{true}}, + Autoforward/.code 2 args={\forest@autoforward{#1}{#2}{true}}, + autoforward register/.code 2 args={\forest@autoforward{#1}{#2={#1={##1}}}{false}}, + autoforward register'/.code 2 args={\forest@autoforward{#1}{#2-=#1,#2={#1={##1}}}{false}}, + Autoforward register/.code 2 args={\forest@autoforward{#1}{#2}{false}}, + copy command key@if it exists/.code 2 args={% + \pgfkeysifdefined{#1/.@cmd}{% + \forest@copycommandkey{#1}{#2}% + }{}% + }, + unautoforward/.style={ + typeout={unautoforwarding #1}, + copy command key@if it exists={/forest/autoforwarded #1}{/forest/#1}, + copy command key@if it exists={/forest/autoforwarded #1+}{/forest/#1+}, + copy command key@if it exists={/forest/autoforwarded #1-}{/forest/#1-}, + copy command key@if it exists={/forest/autoforwarded #1*}{/forest/#1*}, + copy command key@if it exists={/forest/autoforwarded #1:}{/forest/#1:}, + copy command key@if it exists={/forest/autoforwarded #1'}{/forest/#1'}, + copy command key@if it exists={/forest/autoforwarded #1+'}{/forest/#1+'}, + copy command key@if it exists={/forest/autoforwarded #1-'}{/forest/#1-'}, + copy command key@if it exists={/forest/autoforwarded #1*'}{/forest/#1*'}, + copy command key@if it exists={/forest/autoforwarded #1:'}{/forest/#1:'}, + copy command key@if it exists={/forest/autoforwarded +#1}{/forest/+#1}, + }, + /handlers/.undef/.code={\csundef{pgfk@\pgfkeyscurrentpath}}, + undef option/.style={ + /forest/#1/.undef, + /forest/#1/.@cmd/.undef, + /forest/#1+/.@cmd/.undef, + /forest/#1-/.@cmd/.undef, + /forest/#1*/.@cmd/.undef, + /forest/#1:/.@cmd/.undef, + /forest/#1'/.@cmd/.undef, + /forest/#1+'/.@cmd/.undef, + /forest/#1-'/.@cmd/.undef, + /forest/#1*'/.@cmd/.undef, + /forest/#1:'/.@cmd/.undef, + /forest/+#1/.@cmd/.undef, + /forest/TeX={\patchcmd{\forest@node@init}{\forestoinit{#1}}{}{}{}}, + }, + undef register/.style={undef option={#1}}, +} +\def\forest@autoforward#1#2#3{% + % #1 = option name + % #2 = code of a style taking one arg (new option value), + % which expands to whatever should be done with the new value + % autoforward(') adds to the keylist (arg#2) + % #3 = true=option, false=register + \forest@autoforward@createforwarder{}{#1}{}{#2}{#3}% + \forest@autoforward@createforwarder{}{#1}{+}{#2}{#3}% + \forest@autoforward@createforwarder{}{#1}{-}{#2}{#3}% + \forest@autoforward@createforwarder{}{#1}{*}{#2}{#3}% + \forest@autoforward@createforwarder{}{#1}{:}{#2}{#3}% + \forest@autoforward@createforwarder{}{#1}{'}{#2}{#3}% + \forest@autoforward@createforwarder{}{#1}{+'}{#2}{#3}% + \forest@autoforward@createforwarder{}{#1}{-'}{#2}{#3}% + \forest@autoforward@createforwarder{}{#1}{*'}{#2}{#3}% + \forest@autoforward@createforwarder{}{#1}{:'}{#2}{#3}% + \forest@autoforward@createforwarder{+}{#1}{}{#2}{#3}% +} +\def\forest@autoforward@createforwarder#1#2#3#4#5{% + % #1=prefix, #2=option name, #3=suffix, #4=macro code (#2 above), #5=option or register + \pgfkeysifdefined{/forest/#1#2#3/.@cmd}{% + \forest@copycommandkey{/forest/#1#2#3}{/forest/autoforwarded #1#2#3}% + \pgfkeyssetvalue{/forest/autoforwarded #1#2#3/option@name}{#2}% + \pgfkeysdef{/forest/#1#2#3}{% + \pgfkeysalso{autoforwarded #1#2#3={##1}}% + \def\forest@temp@macro####1{#4}% + \csname forest@temp#5\endcsname + \edef\forest@temp@value{\ifforest@temp\expandafter\forestOv\expandafter{\expandafter\forest@setter@node\expandafter}\else\expandafter\forestrv\fi{#2}}% + \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\pgfkeysalso\expandafter\expandafter\expandafter{\expandafter\forest@temp@macro\expandafter{\forest@temp@value}}% + }% + }{}% +} +\def\forest@node@removekeysfromkeylist#1#2{% #1 = keys to remove, #2 = option name + \edef\forest@marshal{% + \noexpand\forest@removekeysfromkeylist{\unexpanded{#1}}{\forestov{#2}}\noexpand\forest@temp@toks}\forest@marshal + \forestoeset{#2}{\the\forest@temp@toks}% +} +\def\forest@removekeysfromkeylist#1#2#3{% + % #1 = keys to remove (a keylist: an empty value means remove a key with any value) + % #2 = keylist + % #3 = toks cs for result + \forest@temp@toks{}% + \def\forestnovalue{\forestnovalue}% + \pgfqkeys{/forest/remove@key@installer}{#1}% + \let\forestnovalue\pgfkeysnovaluetext + \pgfqkeys{/forest/remove@key}{#2}% + \pgfqkeys{/forest/remove@key@uninstaller}{#1}% + #3\forest@temp@toks +} +\def\forest@remove@key@novalue{\forest@remove@key@novalue}% +\forestset{ + remove@key@installer/.unknown/.code={% #1 = (outer) value + \def\forest@temp{#1}% + \ifx\forest@temp\pgfkeysnovalue@text + \pgfkeysdef{/forest/remove@key/\pgfkeyscurrentname}{}% + \else + \ifx\forest@temp\forestnovalue + \expandafter\forest@remove@key@installer@defwithvalue\expandafter{\pgfkeyscurrentname}{\pgfkeysnovalue}% + \else + \expandafter\forest@remove@key@installer@defwithvalue\expandafter{\pgfkeyscurrentname}{#1}% + \fi + \fi + }, + remove@key/.unknown/.code={% #1 = (inner) value + \expandafter\apptotoks\expandafter\forest@temp@toks\expandafter{\pgfkeyscurrentname={#1},}% + }, + remove@key@uninstaller/.unknown/.code={% + \pgfkeyslet{/forest/remove@key/\pgfkeyscurrentname/.@cmd}\@undefined}, +} +\def\forest@remove@key@installer@defwithvalue#1#2{% #1=key name, #2 = outer value + \pgfkeysdef{/forest/remove@key/#1}{% ##1 = inner value + \def\forest@temp@outer{#2}% + \def\forest@temp@inner{##1}% + \ifx\forest@temp@outer\forest@temp@inner + \else + \apptotoks\forest@temp@toks{#1={##1},}% + \fi + }% +} +\def\forest@sort#1#2#3#4#5{% + \let\forest@sort@cmp#1\relax + \let\forest@sort@let#2\relax + \let\forest@sort@direction#3\relax + \forest@@sort{#4}{#5}% +} +\def\forest@quicksort@minarraylength{10000} +\def\forest@@sort#1#2{% + \ifnum#1<#2\relax\@escapeif{% + \forest@sort@m=#2 + \advance\forest@sort@m -#1 + \ifnum\forest@sort@m>\forest@quicksort@minarraylength\relax\@escapeif{% + \forest@quicksort{#1}{#2}% + }\else\@escapeif{% + \forest@insertionsort{#1}{#2}% + }\fi + }\fi +} +\newcount\forest@sort@m\newcount\forest@sort@k\newcount\forest@sort@p +\def\forest@sort@ascending{>} +\def\forest@sort@descending{<} +\def\forest@sort@cmp{% + \PackageError{sort}{You must define forest@sort@cmp function before calling + sort}{The macro must take two arguments, indices of the array + elements to be compared, and return '=' if the elements are equal + and '>'/'<' if the first is greater /less than the secong element.}% +} +\def\forest@sort@cmp@gt{\def\forest@sort@cmp@result{>}} +\def\forest@sort@cmp@lt{\def\forest@sort@cmp@result{<}} +\def\forest@sort@cmp@eq{\def\forest@sort@cmp@result{=}} +\def\forest@sort@let{% + \PackageError{sort}{You must define forest@sort@let function before calling + sort}{The macro must take two arguments, indices of the array: + element 2 must be copied onto element 1.}% +} +\newloop\forest@sort@loop +\newloop\forest@sort@loopA +\def\forest@quicksort#1#2{% + \forest@sort@m=#2 + \advance\forest@sort@m -#1 + \ifodd\forest@sort@m\relax\advance\forest@sort@m1 \fi + \divide\forest@sort@m 2 + \advance\forest@sort@m #1 + \forest@sort@cmp{#1}{#2}% + \if\forest@sort@cmp@result=% + \forest@sort@p=#1 + \else + \if\forest@sort@cmp@result>% + \forest@sort@p=#1\relax + \else + \forest@sort@p=#2\relax + \fi + \forest@sort@cmp{\the\forest@sort@p}{\the\forest@sort@m}% + \if\forest@sort@cmp@result<% + \else + \forest@sort@p=\the\forest@sort@m + \fi + \fi + \forest@sort@xch{#1}{\the\forest@sort@p}% + \forest@sort@m=#1\relax + \forest@sort@k=#1\relax + \forest@sort@loop + \ifnum\forest@sort@k<#2\relax + \advance\forest@sort@k 1 + \forest@sort@cmp{#1}{\the\forest@sort@k}% + \ifx\forest@sort@direction\forest@sort@cmp@result + \advance\forest@sort@m 1 + \forest@sort@xch{\the\forest@sort@m}{\the\forest@sort@k} + \fi + \forest@sort@repeat + \forest@sort@xch{#1}{\the\forest@sort@m}% + \forest@sort@k=\forest@sort@m + \advance\forest@sort@k -1 + \advance\forest@sort@m 1 + \edef\forest@sort@marshal{% + \noexpand\forest@@sort{#1}{\the\forest@sort@k}% + \noexpand\forest@@sort{\the\forest@sort@m}{#2}% + }% + \forest@sort@marshal +} +\def\forest@sort@aux{aux} +\def\forest@sort@xch#1#2{% + \forest@sort@let{\forest@sort@aux}{#1}% + \forest@sort@let{#1}{#2}% + \forest@sort@let{#2}{\forest@sort@aux}% +} +\def\forest@insertionsort#1#2{% + \forest@sort@m=#1 + \edef\forest@insertionsort@low{#1}% + \forest@sort@loopA + \ifnum\forest@sort@m<#2 + \advance\forest@sort@m 1 + \forest@insertionsort@Qbody + \forest@sort@repeatA +} +\newif\ifforest@insertionsort@loop +\def\forest@insertionsort@Qbody{% + \forest@sort@let{\forest@sort@aux}{\the\forest@sort@m}% + \forest@sort@k\forest@sort@m + \advance\forest@sort@k -1 + \forest@insertionsort@looptrue + \forest@sort@loop + \ifforest@insertionsort@loop + \forest@insertionsort@qbody + \forest@sort@repeat + \advance\forest@sort@k 1 + \forest@sort@let{\the\forest@sort@k}{\forest@sort@aux}% +} +\def\forest@insertionsort@qbody{% + \forest@sort@cmp{\the\forest@sort@k}{\forest@sort@aux}% + \ifx\forest@sort@direction\forest@sort@cmp@result\relax + \forest@sort@p=\forest@sort@k + \advance\forest@sort@p 1 + \forest@sort@let{\the\forest@sort@p}{\the\forest@sort@k}% + \advance\forest@sort@k -1 + \ifnum\forest@sort@k<\forest@insertionsort@low\relax + \forest@insertionsort@loopfalse + \fi + \else + \forest@insertionsort@loopfalse + \fi +} +\def\forest@sort@cmpnumcs#1#2{% + \ifnum\csname#1\endcsname>\csname#2\endcsname\relax + \forest@sort@cmp@gt + \else + \ifnum\csname#1\endcsname<\csname#2\endcsname\relax + \forest@sort@cmp@lt + \else + \forest@sort@cmp@eq + \fi + \fi +} +\def\forest@sort@cmpdimcs#1#2{% + \ifdim\csname#1\endcsname>\csname#2\endcsname\relax + \forest@sort@cmp@gt + \else + \ifdim\csname#1\endcsname<\csname#2\endcsname\relax + \forest@sort@cmp@lt + \else + \forest@sort@cmp@eq + \fi + \fi +} +\def\forest@sort@cmptwodimcs#1#2#3#4{% + \ifdim\csname#1\endcsname>\csname#3\endcsname\relax + \forest@sort@cmp@gt + \else + \ifdim\csname#1\endcsname<\csname#3\endcsname\relax + \forest@sort@cmp@lt + \else + \ifdim\csname#2\endcsname>\csname#4\endcsname\relax + \forest@sort@cmp@gt + \else + \ifdim\csname#2\endcsname<\csname#4\endcsname\relax + \forest@sort@cmp@lt + \else + \forest@sort@cmp@eq + \fi + \fi + \fi + \fi +} +\def\forest@reversearray#1#2#3{% + \let\forest@sort@let#1% + \c@pgf@countc=#2 + \c@pgf@countd=#3 + \advance\c@pgf@countd -1 + \safeloop + \ifnum\c@pgf@countc<\c@pgf@countd\relax + \forest@sort@xch{\the\c@pgf@countc}{\the\c@pgf@countd}% + \advance\c@pgf@countc 1 + \advance\c@pgf@countd -1 + \saferepeat +} +\def\bracketset#1{\pgfqkeys{/bracket}{#1}}% +\bracketset{% + /bracket/.is family, + /handlers/.let/.style={\pgfkeyscurrentpath/.code={\let#1##1}}, + opening bracket/.let=\bracket@openingBracket, + closing bracket/.let=\bracket@closingBracket, + action character/.let=\bracket@actionCharacter, + opening bracket=[, + closing bracket=], + action character, + new node/.code n args={3}{% #1=preamble, #2=node spec, #3=cs receiving the id + \forest@node@new#3% + \forestOeset{#3}{given options}{\forest@contentto=\unexpanded{#2}}% + \ifblank{#1}{}{% + \forestrset{preamble}{#1}% + }% + }, + set afterthought/.code 2 args={% #1=node id, #2=afterthought + \ifblank{#2}{}{\forestOappto{#1}{given options}{,afterthought={#2}}}% + } +} +\newtoks\bracket@content +\newtoks\bracket@afterthought +\def\bracketParse#1#2={% + \def\bracketEndParsingHook{#1}% + \def\bracket@saveRootNodeTo{#2}% + \bracket@content={}% + \bracket@afterthought={}% + \let\bracket@state\bracket@state@starting + \bracket@ignorespacestrue + \bracket@expandtokensfalse + \def\bracket@parentNode{0}% + \def\bracket@rootNode{0}% + \def\bracket@newNode{0}% + \def\bracket@afterthoughtNode{0}% + \bracket@Parse +} +\def\bracketResume{\bracket@Parse}% +\def\bracket@Parse{% + \futurelet\bracket@next@token\bracket@Parse@checkForSpace +} +\def\bracket@Parse@checkForSpace{% + \expandafter\ifx\space\bracket@next@token\@escapeif{% + \ifbracket@ignorespaces\else + \bracket@haveSpacetrue + \fi + \expandafter\bracket@Parse\romannumeral-`0% + }\else\@escapeif{% + \bracket@Parse@maybeexpand + }\fi +} +\newif\ifbracket@expandtokens +\def\bracket@Parse@maybeexpand{% + \ifbracket@expandtokens\@escapeif{% + \expandafter\bracket@Parse@peekAhead\romannumeral-`0% + }\else\@escapeif{% + \bracket@Parse@peekAhead + }\fi +} +\def\bracket@Parse@peekAhead{% + \futurelet\bracket@next@token\bracket@Parse@checkForTeXGroup +} +\def\bracket@Parse@checkForTeXGroup{% + \ifx\bracket@next@token\bgroup% + \@escapeif{\bracket@Parse@appendGroup}% + \else + \@escapeif{\bracket@Parse@token}% + \fi +} +\long\def\bracket@Parse@token#1{% + \ifx#1\bracket@openingBracket + \@escapeif{\bracket@Parse@openingBracketFound}% + \else + \@escapeif{% + \ifx#1\bracket@closingBracket + \@escapeif{\bracket@Parse@closingBracketFound}% + \else + \@escapeif{% + \ifx#1\bracket@actionCharacter + \@escapeif{\futurelet\bracket@next@token\bracket@Parse@actionCharacterFound}% + \else + \@escapeif{\bracket@Parse@appendToken#1}% + \fi + }% + \fi + }% + \fi +} +\newif\ifbracket@haveSpace +\newif\ifbracket@ignorespaces +\def\bracket@Parse@appendSpace{% + \ifbracket@haveSpace + \ifcase\bracket@state\relax + \eapptotoks\bracket@content\space + \or + \eapptotoks\bracket@afterthought\space + \or + \eapptotoks\bracket@afterthought\space + \fi + \bracket@haveSpacefalse + \fi +} +\long\def\bracket@Parse@appendToken#1{% + \bracket@Parse@appendSpace + \ifcase\bracket@state\relax + \lapptotoks\bracket@content{#1}% + \or + \lapptotoks\bracket@afterthought{#1}% + \or + \lapptotoks\bracket@afterthought{#1}% + \fi + \bracket@ignorespacesfalse + \bracket@Parse +} +\def\bracket@Parse@appendGroup#1{% + \bracket@Parse@appendSpace + \ifcase\bracket@state\relax + \apptotoks\bracket@content{{#1}}% + \or + \apptotoks\bracket@afterthought{{#1}}% + \or + \apptotoks\bracket@afterthought{{#1}}% + \fi + \bracket@ignorespacesfalse + \bracket@Parse +} +\def\bracket@state@inContent{0} +\def\bracket@state@inAfterthought{1} +\def\bracket@state@starting{2} +\def\bracket@Parse@openingBracketFound{% + \bracket@haveSpacefalse + \ifcase\bracket@state\relax% in content [ ... [ + \@escapeif{% + \bracket@createNode + \ifnum\bracket@parentNode=0 \else + \forest@node@Append{\bracket@parentNode}{\bracket@newNode}% + \fi + \let\bracket@parentNode\bracket@newNode + \bracket@Parse + }% + \or % in afterthought ] ... [ + \@escapeif{% + \bracket@addAfterthought + \let\bracket@state\bracket@state@inContent + \bracket@Parse + }% + \else % starting + \@escapeif{% + \let\bracket@state\bracket@state@inContent + \bracket@Parse + }% + \fi +} +\def\bracket@Parse@closingBracketFound{% + \bracket@haveSpacefalse + \ifcase\bracket@state\relax % in content [ ... ] + \@escapeif{% + \bracket@createNode + \ifnum\bracket@parentNode=0 + \@escapeif\bracketEndParsingHook + \else + \@escapeif{% + \let\bracket@afterthoughtNode\bracket@newNode + \let\bracket@state\bracket@state@inAfterthought + \forest@node@Append{\bracket@parentNode}{\bracket@newNode}% + \bracket@Parse + }% + \fi + }% + \or % in afterthought ] ... ] + \@escapeif{% + \bracket@addAfterthought + \let\bracket@afterthoughtNode\bracket@parentNode + \edef\bracket@parentNode{\forestOve{\bracket@parentNode}{@parent}}% + \ifnum\bracket@parentNode=0 + \expandafter\bracketEndParsingHook + \else + \expandafter\bracket@Parse + \fi + }% + \else % starting + \PackageError{forest}{You're attempting to start a bracket representation + with a closing bracket}{}% + \fi +} +\def\bracket@Parse@actionCharacterFound{% + \ifx\bracket@next@token\bgroup\@escapeif{% + \bracket@Parse@action@expandgroup + }\else\@escapeif{% + \bracket@Parse@action@notagroup + }\fi +} +\def\bracket@Parse@action@expandgroup#1{% + \edef\bracket@Parse@action@expandgroup@macro{#1}% + \expandafter\bracket@Parse\bracket@Parse@action@expandgroup@macro +} +\let\bracket@action@fullyexpandCharacter+ +\let\bracket@action@dontexpandCharacter- +\let\bracket@action@executeCharacter! +\def\bracket@Parse@action@notagroup#1{% + \ifx#1\bracket@action@fullyexpandCharacter\@escapeif{% + \bracket@expandtokenstrue\bracket@Parse + }\else\@escapeif{% + \ifx#1\bracket@action@dontexpandCharacter\@escapeif{% + \bracket@expandtokensfalse\bracket@Parse + }\else\@escapeif{% + \ifx#10\@escapeif{% + \bracket@Parse@appendToken + }\else\@escapeif{% + \ifx#1\bracket@actionCharacter + \else\@escapeif{% + \expandafter\bracket@Parse#1% + }\fi + }\fi + }\fi + }\fi +} +\def\bracket@createNode{% + \ifnum\bracket@rootNode=0 + % root node + \bracketset{new node/.expanded=% + {\the\bracket@afterthought}% + {\the\bracket@content}% + \noexpand\bracket@newNode + }% + \bracket@afterthought={}% + \let\bracket@rootNode\bracket@newNode + \expandafter\let\bracket@saveRootNodeTo\bracket@newNode + \else + % other nodes + \bracketset{new node/.expanded=% + {}% + {\the\bracket@content}% + \noexpand\bracket@newNode + }% + \fi + \bracket@content={}% +} +\def\bracket@addAfterthought{% + \bracketset{% + set afterthought/.expanded={\bracket@afterthoughtNode}{\the\bracket@afterthought}% + }% + \bracket@afterthought={}% +} + % full expansion expands precisely to the value +\def\forestov#1{\expandafter\expandafter\expandafter\expandonce + \pgfkeysvalueof{/forest/@node/\forest@cn/#1}} + % full expansion expands all the way +\def\forestove#1{\pgfkeysvalueof{/forest/@node/\forest@cn/#1}} + % full expansion expands to the cs holding the value +\def\forestom#1{\expandafter\expandonce\expandafter{\pgfkeysvalueof{/forest/@node/\forest@cn/#1}}} +\def\forestoget#1#2{\pgfkeysgetvalue{/forest/@node/\forest@cn/#1}{#2}} +\def\forestolet#1#2{\pgfkeyslet{/forest/@node/\forest@cn/#1}{#2}} +\def\forestocslet#1#2{% + \edef\forest@marshal{% + \noexpand\pgfkeyslet{/forest/@node/\forest@cn/#1}{\expandonce{\csname#2\endcsname}}% + }\forest@marshal +} +\def\forestoset#1#2{\pgfkeyssetvalue{/forest/@node/\forest@cn/#1}{#2}} +\def\forestoeset#1#2{% + \edef\forest@option@temp{% + \noexpand\pgfkeyssetvalue{/forest/@node/\forest@cn/#1}{#2}% + }\forest@option@temp +} +\def\forestoappto#1#2{% + \forestoeset{#1}{\forestov{#1}\unexpanded{#2}}% +} +\def\forestoifdefined#1#2#3{% + \pgfkeysifdefined{/forest/@node/\forest@cn/#1}{#2}{#3}% +} +\let\forestoption\forestov +\let\foresteoption\forestove +\def\forestOv#1#2{\expandafter\expandafter\expandafter\expandonce + \pgfkeysvalueof{/forest/@node/#1/#2}} +\def\forestOve#1#2{\pgfkeysvalueof{/forest/@node/#1/#2}} + % full expansion expands to the cs holding the value +\def\forestOm#1#2{\expandafter\expandonce\expandafter{\pgfkeysvalueof{/forest/@node/#1/#2}}} +\def\forestOget#1#2#3{\pgfkeysgetvalue{/forest/@node/#1/#2}{#3}} +\def\forestOget#1#2#3{\pgfkeysgetvalue{/forest/@node/#1/#2}{#3}} +\def\forestOlet#1#2#3{\pgfkeyslet{/forest/@node/#1/#2}{#3}} +\def\forestOcslet#1#2#3{% + \edef\forest@marshal{% + \noexpand\pgfkeyslet{/forest/@node/#1/#2}{\expandonce{\csname#3\endcsname}}% + }\forest@marshal +} +\def\forestOset#1#2#3{\pgfkeyssetvalue{/forest/@node/#1/#2}{#3}} +\def\forestOeset#1#2#3{% + \edef\forestoption@temp{% + \noexpand\pgfkeyssetvalue{/forest/@node/#1/#2}{#3}% + }\forestoption@temp +} +\def\forestOappto#1#2#3{% + \forestOeset{#1}{#2}{\forestOv{#1}{#2}\unexpanded{#3}}% +} +\def\forestOeappto#1#2#3{% + \forestOeset{#1}{#2}{\forestOv{#1}{#2}#3}% +} +\def\forestOpreto#1#2#3{% + \forestOeset{#1}{#2}{\unexpanded{#3}\forestOv{#1}{#2}}% +} +\def\forestOepreto#1#2#3{% + \forestOeset{#1}{#2}{#3\forestOv{#1}{#2}}% +} +\def\forestOifdefined#1#2#3#4{% + \pgfkeysifdefined{/forest/@node/#1/#2}{#3}{#4}% +} +\def\forestOletO#1#2#3#4{% option #2 of node #1 <-- option #4 of node #3 + \forestOget{#3}{#4}\forestoption@temp + \forestOlet{#1}{#2}\forestoption@temp} +\def\forestOleto#1#2#3{% + \forestoget{#3}\forestoption@temp + \forestOlet{#1}{#2}\forestoption@temp} +\def\forestoletO#1#2#3{% + \forestOget{#2}{#3}\forestoption@temp + \forestolet{#1}\forestoption@temp} +\def\forestoleto#1#2{% + \forestoget{#2}\forestoption@temp + \forestolet{#1}\forestoption@temp} + % full expansion expands precisely to the value +\def\forestrv#1{\expandafter\expandafter\expandafter\expandonce + \pgfkeysvalueof{/forest/@node/register/#1}} + % full expansion expands all the way +\def\forestrve#1{\pgfkeysvalueof{/forest/@node/register/#1}} + % full expansion expands to the cs holding the value +\def\forestrm#1{\expandafter\expandonce\expandafter{\pgfkeysvalueof{/forest/@node/register/#1}}} +\def\forestrget#1#2{\pgfkeysgetvalue{/forest/@node/register/#1}{#2}} +\def\forestrlet#1#2{\pgfkeyslet{/forest/@node/register/#1}{#2}} +\def\forestrcslet#1#2{% + \edef\forest@marshal{% + \noexpand\pgfkeyslet{/forest/@node/register/#1}{\expandonce{\csname#2\endcsname}}% + }\forest@marshal +} +\def\forestrset#1#2{\pgfkeyssetvalue{/forest/@node/register/#1}{#2}} +\def\forestreset#1#2{% + \edef\forest@option@temp{% + \noexpand\pgfkeyssetvalue{/forest/@node/register/#1}{#2}% + }\forest@option@temp +} +\def\forestrappto#1#2{% + \forestreset{#1}{\forestrv{#1}\unexpanded{#2}}% +} +\def\forestrpreto#1#2{% + \forestreset{#1}{\unexpanded{#2}\forestrv{#1}}% +} +\def\forestrifdefined#1#2#3{% + \pgfkeysifdefined{/forest/@node/register/#1}{#2}{#3}% +} +\def\forestregister#1{\forestrv{#1}} +\def\foresteregister#1{\forestrve{#1}} +\def\forest@node@init{% + \forestoset{@parent}{0}% + \forestoset{@previous}{0}% previous sibling + \forestoset{@next}{0}% next sibling + \forestoset{@first}{0}% primary child + \forestoset{@last}{0}% last child +} +\def\forestoinit#1{% + \pgfkeysgetvalue{/forest/#1}\forestoinit@temp + \forestolet{#1}\forestoinit@temp +} +\newcount\forest@node@maxid +\def\forest@node@new#1{% #1 = cs receiving the new node id + \advance\forest@node@maxid1 + \forest@fornode{\the\forest@node@maxid}{% + \forest@node@init + \forestoeset{id}{\forest@cn}% + \forest@node@setname{node@\forest@cn}% + \forest@initializefromstandardnode + \edef#1{\forest@cn}% + }% +} +\let\forestoinit@orig\forestoinit +\def\forest@node@copy#1#2{% #1=from node id, cs receiving the new node id + \advance\forest@node@maxid1 + \def\forestoinit##1{\ifstrequal{##1}{name}{\forestoset{name}{node@\forest@cn}}{\forestoletO{##1}{#1}{##1}}}% + \forest@fornode{\the\forest@node@maxid}{% + \forest@node@init + \forestoeset{id}{\forest@cn}% + \forest@node@setname{\forest@copy@name@template{\forestOve{#1}{name}}}% + \edef#2{\forest@cn}% + }% + \let\forestoinit\forestoinit@orig +} +\forestset{ + copy name template/.code={\def\forest@copy@name@template##1{#1}}, + copy name template/.default={node@\the\forest@node@maxid}, + copy name template +} +\def\forest@tree@copy#1#2{% #1=from node id, #2=cs receiving the new node id + \forest@node@copy{#1}\forest@node@copy@temp@id + \forest@fornode{\forest@node@copy@temp@id}{% + \expandafter\forest@tree@copy@\expandafter{\forest@node@copy@temp@id}{#1}% + \edef#2{\forest@cn}% + }% +} +\def\forest@tree@copy@#1#2{% + \forest@node@Foreachchild{#2}{% + \expandafter\forest@tree@copy\expandafter{\forest@cn}\forest@node@copy@temp@childid + \forest@node@Append{#1}{\forest@node@copy@temp@childid}% + }% +} +\def\forest@cn{0} +\forest@node@init +\def\forest@node@append#1{\expandtwonumberargs\forest@node@Append{\forest@cn}{#1}} +\def\forest@node@prepend#1{\expandtwonumberargs\forest@node@Insertafter{\forest@cn}{#1}{0}} +\def\forest@node@insertafter#1#2{% + \expandthreenumberargs\forest@node@Insertafter{\forest@cn}{#1}{#2}} +\def\forest@node@insertbefore#1#2{% + \expandthreenumberargs\forest@node@Insertafter{\forest@cn}{#1}{\forestOve{#2}{@previous}}% +} +\def\forest@node@remove{\expandnumberarg\forest@node@Remove{\forest@cn}} +\def\forest@node@Append#1#2{\expandtwonumberargs\forest@node@Append@{#1}{#2}} +\def\forest@node@Prepend#1#2{\expandtwonumberargs\forest@node@Insertafter{#1}{#2}{0}} +\def\forest@node@Insertafter#1#2#3{% #2 is inserted after #3 + \expandthreenumberargs\forest@node@Insertafter@{#1}{#2}{#3}% +} +\def\forest@node@Insertbefore#1#2#3{% #2 is inserted before #3 + \expandthreenumberargs\forest@node@Insertafter{#1}{#2}{\forestOve{#3}{@previous}}% +} +\def\forest@node@Remove#1{\expandnumberarg\forest@node@Remove@{#1}} +\def\forest@node@Insertafter@#1#2#3{% + \ifnum\forestOve{#2}{@parent}=0 + \else + \PackageError{forest}{Insertafter(#1,#2,#3): + node #2 already has a parent (\forestOve{#2}{@parent})}{}% + \fi + \ifnum#3=0 + \else + \ifnum#1=\forestOve{#3}{@parent} + \else + \PackageError{forest}{Insertafter(#1,#2,#3): node #1 is not the parent of the + intended sibling #3 (with parent \forestOve{#3}{@parent})}{}% + \fi + \fi + \forestOeset{#2}{@parent}{#1}% + \forestOeset{#2}{@previous}{#3}% + \ifnum#3=0 + \forestOget{#1}{@first}\forest@node@temp + \forestOeset{#1}{@first}{#2}% + \else + \forestOget{#3}{@next}\forest@node@temp + \forestOeset{#3}{@next}{#2}% + \fi + \forestOeset{#2}{@next}{\forest@node@temp}% + \ifnum\forest@node@temp=0 + \forestOeset{#1}{@last}{#2}% + \else + \forestOeset{\forest@node@temp}{@previous}{#2}% + \fi +} +\def\forest@node@Append@#1#2{% + \ifnum\forestOve{#2}{@parent}=0 + \else + \PackageError{forest}{Append(#1,#2): + node #2 already has a parent (\forestOve{#2}{@parent})}{}% + \fi + \forestOeset{#2}{@parent}{#1}% + \forestOget{#1}{@last}\forest@node@temp + \forestOeset{#1}{@last}{#2}% + \forestOeset{#2}{@previous}{\forest@node@temp}% + \ifnum\forest@node@temp=0 + \forestOeset{#1}{@first}{#2}% + \else + \forestOeset{\forest@node@temp}{@next}{#2}% + \fi +} +\def\forest@node@Remove@#1{% + \forestOget{#1}{@parent}\forest@node@temp@parent + \ifnum\forest@node@temp@parent=0 + \else + \forestOget{#1}{@previous}\forest@node@temp@previous + \forestOget{#1}{@next}\forest@node@temp@next + \ifnum\forest@node@temp@previous=0 + \forestOeset{\forest@node@temp@parent}{@first}{\forest@node@temp@next}% + \else + \forestOeset{\forest@node@temp@previous}{@next}{\forest@node@temp@next}% + \fi + \ifnum\forest@node@temp@next=0 + \forestOeset{\forest@node@temp@parent}{@last}{\forest@node@temp@previous}% + \else + \forestOeset{\forest@node@temp@next}{@previous}{\forest@node@temp@previous}% + \fi + \forestOset{#1}{@parent}{0}% + \forestOset{#1}{@previous}{0}% + \forestOset{#1}{@next}{0}% + \fi +} +\def\forest@forthis#1{% + \edef\forest@node@marshal{\unexpanded{#1}\def\noexpand\forest@cn}% + \expandafter\forest@node@marshal\expandafter{\forest@cn}% +} +\def\forest@fornode#1#2{% + \edef\forest@node@marshal{\edef\noexpand\forest@cn{#1}\unexpanded{#2}\def\noexpand\forest@cn}% + \expandafter\forest@node@marshal\expandafter{\forest@cn}% +} +\def\forest@node@foreachchild#1{\forest@node@Foreachchild{\forest@cn}{#1}} +\def\forest@node@Foreachchild#1#2{% + \forest@fornode{\forestOve{#1}{@first}}{\forest@node@@forselfandfollowingsiblings{#2}}% +} +\def\forest@node@@forselfandfollowingsiblings#1{% + \ifnum\forest@cn=0 + \else + \forest@forthis{#1}% + \@escapeif{% + \edef\forest@cn{\forestove{@next}}% + \forest@node@@forselfandfollowingsiblings{#1}% + }% + \fi +} +\def\forest@node@@forselfandfollowingsiblings@reversed#1{% + \ifnum\forest@cn=0 + \else + \@escapeif{% + \edef\forest@marshal{% + \noexpand\def\noexpand\forest@cn{\forestove{@next}}% + \noexpand\forest@node@@forselfandfollowingsiblings@reversed{\unexpanded{#1}}% + \noexpand\forest@fornode{\forest@cn}{\unexpanded{#1}}% + }\forest@marshal + }% + \fi +} +\def\forest@node@foreachchild@reversed#1{\forest@node@Foreachchild@reversed{\forest@cn}{#1}} +\def\forest@node@Foreachchild@reversed#1#2{% + \forest@fornode{\forestOve{#1}{@last}}{\forest@node@@forselfandprecedingsiblings@reversed{#2}}% +} +\def\forest@node@@forselfandprecedingsiblings@reversed#1{% + \ifnum\forest@cn=0 + \else + \forest@forthis{#1}% + \@escapeif{% + \edef\forest@cn{\forestove{@previous}}% + \forest@node@@forselfandprecedingsiblings@reversed{#1}% + }% + \fi +} +\def\forest@node@@forselfandprecedingsiblings#1{% + \ifnum\forest@cn=0 + \else + \@escapeif{% + \edef\forest@marshal{% + \noexpand\def\noexpand\forest@cn{\forestove{@previous}}% + \noexpand\forest@node@@forselfandprecedingsiblings{\unexpanded{#1}}% + \noexpand\forest@fornode{\forest@cn}{\unexpanded{#1}}% + }\forest@marshal + }% + \fi +} +\def\forest@node@@foreach#1#2#3#4{% + % #1 = do what + % #2 = do that -1=before,1=after processing children + % #3 & #4: normal or reversed order of children? + % #3 = @first/@last + % #4 = \forest@node@@forselfandfollowingsiblings / \forest@node@@forselfandprecedingsiblings@reversed + \ifnum#2<0 \forest@forthis{#1}\fi + \ifnum\forestove{#3}=0 + \else\@escapeif{% + \forest@forthis{% + \edef\forest@cn{\forestove{#3}}% + #4{\forest@node@@foreach{#1}{#2}{#3}{#4}}% + }% + }\fi + \ifnum#2>0 \forest@forthis{#1}\fi +} +\def\forest@node@foreach#1{% + \forest@node@@foreach{#1}{-1}{@first}{\forest@node@@forselfandfollowingsiblings}} +\def\forest@node@Foreach#1#2{% + \forest@fornode{#1}{\forest@node@@foreach{#2}{-1}{@first}{\forest@node@@forselfandfollowingsiblings}}} +\def\forest@node@foreach@reversed#1{% + \forest@node@@foreach{#1}{-1}{@last}{\forest@node@@forselfandprecedingsiblings@reversed}} +\def\forest@node@Foreach@reversed#1#2{% + \forest@fornode{#1}{\forest@node@@foreach{#2}{-1}{@last}{\forest@node@@forselfandprecedingsiblings@reversed}}} +\def\forest@node@foreach@childrenfirst#1{% + \forest@node@@foreach{#1}{1}{@first}{\forest@node@@forselfandfollowingsiblings}} +\def\forest@node@Foreach@childrenfirst#1#2{% + \forest@fornode{#1}{\forest@node@@foreach{#2}{1}{@first}{\forest@node@@forselfandfollowingsiblings}}} +\def\forest@node@foreach@childrenfirst@reversed#1{% + \forest@node@@foreach{#1}{1}{@last}{\forest@node@@forselfandprecedingsiblings@reversed}} +\def\forest@node@Foreach@childrenfirst@reversed#1#2{% + \forest@fornode{#1}{\forest@node@@foreach{#2}{1}{@last}{\forest@node@@forselfandprecedingsiblings@reversed}}} +\def\forest@node@foreachdescendant#1{% + \forest@node@foreachchild{\forest@node@@foreach{#1}{-1}{@first}{\forest@node@@forselfandfollowingsiblings}}} +\def\forest@node@Foreachdescendant#1#2{% + \forest@node@Foreachchild{#1}{\forest@node@@foreach{#2}{-1}{@first}{\forest@node@@forselfandfollowingsiblings}}} +\def\forest@node@foreachdescendant@reversed#1{% + \forest@node@foreachchild@reversed{\forest@node@@foreach{#1}{-1}{@last}{\forest@node@@forselfandprecedingsiblings@reversed}}} +\def\forest@node@Foreachdescendant@reversed#1#2{% + \forest@node@Foreachchild@reversed{#1}{\forest@node@@foreach{#2}{-1}{@last}{\forest@node@@forselfandprecedingsiblings@reversed}}} +\def\forest@node@foreachdescendant@childrenfirst#1{% + \forest@node@foreachchild{\forest@node@@foreach{#1}{1}{@first}{\forest@node@@forselfandfollowingsiblings}}} +\def\forest@node@Foreachdescendant@childrenfirst#1#2{% + \forest@node@Foreachchild{#1}{\forest@node@@foreach{#2}{1}{@first}{\forest@node@@forselfandfollowingsiblings}}} +\def\forest@node@foreachdescendant@childrenfirst@reversed#1{% + \forest@node@foreachchild@reversed{\forest@node@@foreach{#1}{1}{@last}{\forest@node@@forselfandprecedingsiblings@reversed}}} +\def\forest@node@Foreachdescendant@childrenfirst@reversed#1#2{% + \forest@node@Foreachchild@reversed{#1}{\forest@node@@foreach{#2}{1}{@last}{\forest@node@@forselfandprecedingsiblings@reversed}}} +\def\forest@node@foreach@breadthfirst#1#2{% #1 = max level, #2 = code + \forest@node@Foreach@breadthfirst@{\forest@cn}{@first}{@next}{#1}{#2}} +\def\forest@node@foreach@breadthfirst@reversed#1#2{% #1 = max level, #2 = code + \forest@node@Foreach@breadthfirst@{\forest@cn}{@last}{@previous}{#1}{#2}} +\def\forest@node@Foreach@breadthfirst#1#2#3{% #1 = node id, #2 = max level, #3 = code + \forest@node@Foreach@breadthfirst@{#1}{@first}{@next}{#2}{#3}} +\def\forest@node@Foreach@breadthfirst@reversed#1#2#3{% #1 = node id, #2 = max level, #3 = code + \forest@node@Foreach@breadthfirst@{#1}{@last}{@previous}{#2}{#3}} +\def\forest@node@Foreach@breadthfirst@#1#2#3#4#5{% + % #1 = root node, + % #2 = @first/@last, #3 = @next/@previous (must be in sync with #2), + % #4 = max level (< 0 means infinite) + % #5 = code to execute at each node + \forest@node@Foreach@breadthfirst@processqueue{#1,}{#2}{#3}{#4}{#5}% +} +\def\forest@node@Foreach@breadthfirst@processqueue#1#2#3#4#5{% + % #1 = queue, + % #2 = @first/@last, #3 = @next/@previous (must be in sync with #2), + % #4 = max level (< 0 means infinite) + % #5 = code to execute at each node + \ifstrempty{#1}{}{% + \forest@node@Foreach@breadthfirst@processqueue@#1\forest@node@Foreach@breadthfirst@processqueue@ + {#2}{#3}{#4}{#5}% + }% +} +\def\forest@node@Foreach@breadthfirst@processqueue@#1,#2\forest@node@Foreach@breadthfirst@processqueue@#3#4#5#6{% + % #1 = first, + % #2 = rest, + % #3 = @first/@last, #4 = next/previous (must be in sync with #2), + % #5 = max level (< 0 means infinite) + % #6 = code to execute at each node + \forest@fornode{#1}{% + #6% + \ifnum#5<0 + \forest@node@getlistofchildren\forest@temp{#3}{#4}% + \else + \ifnum\forestove{level}>#5\relax + \def\forest@temp{}% + \else + \forest@node@getlistofchildren\forest@temp{#3}{#4}% + \fi + \fi + \edef\forest@marshal{% + \noexpand\forest@node@Foreach@breadthfirst@processqueue{\unexpanded{#2}\forest@temp}% + {#3}{#4}{#5}{\unexpanded{#6}}% + }\forest@marshal + }% +} +\def\forest@node@getlistofchildren#1#2#3{% #1 = list cs, #2 = @first/@last, #3 = @next/@previous + \forest@node@Getlistofchildren{\forest@cn}{#1}{#2}{#3}% +} +\def\forest@node@Getlistofchildren#1#2#3#4{% #1 = node, #2 = list cs, #3 = @first/@last, #4 = @next/@previous + \def#2{}% + \ifnum\forestove{#3}=0 + \else + \eappto#2{\forestOve{#1}{#3},}% + \@escapeif{% + \edef\forest@marshal{% + \noexpand\forest@node@Getlistofchildren@{\forestOve{#1}{#3}}\noexpand#2{#4}% + }\forest@marshal + }% + \fi +} +\def\forest@node@Getlistofchildren@#1#2#3{% #1 = node, #2 = list cs, #3 = @next/@previous + \ifnum\forestOve{#1}{#3}=0 + \else + \eappto#2{\forestOve{#1}{#3},}% + \@escapeif{% + \edef\forest@marshal{% + \noexpand\forest@node@Getlistofchildren@{\forestOve{#1}{#3}}\noexpand#2{#3}% + }\forest@marshal + }% + \fi +} +\def\forest@node@Compute@numeric@ts@info@#1{% + \forest@node@Foreach{#1}{\forest@node@@compute@numeric@ts@info}% + \ifnum\forestOve{#1}{@parent}=0 + \else + \forest@fornode{#1}{\forest@node@@compute@numeric@ts@info@nbar}% + % hack: the parent of the node we called the update for gets +1 for n_children + \edef\forest@node@temp{\forestOve{#1}{@parent}}% + \forestOeset{\forest@node@temp}{n children}{% + \number\numexpr\forestOve{\forest@node@temp}{n children}-1% + }% + \fi + \forest@node@Foreachdescendant{#1}{\forest@node@@compute@numeric@ts@info@nbar}% +} +\def\forest@node@@compute@numeric@ts@info{% + \forestoset{n children}{0}% + % + \edef\forest@node@temp{\forestove{@previous}}% + \ifnum\forest@node@temp=0 + \forestoset{n}{1}% + \else + \forestoeset{n}{\number\numexpr\forestOve{\forest@node@temp}{n}+1}% + \fi + % + \edef\forest@node@temp{\forestove{@parent}}% + \ifnum\forest@node@temp=0 + \forestoset{n}{0}% + \forestoset{n'}{0}% + \forestoset{level}{0}% + \else + \forestOeset{\forest@node@temp}{n children}{% + \number\numexpr\forestOve{\forest@node@temp}{n children}+1% + }% + \forestoeset{level}{% + \number\numexpr\forestOve{\forest@node@temp}{level}+1% + }% + \fi +} +\def\forest@node@@compute@numeric@ts@info@nbar{% + \forestoeset{n'}{\number\numexpr\forestOve{\forestove{@parent}}{n children}-\forestove{n}+1}% +} +\def\forest@node@compute@numeric@ts@info#1{% + \expandnumberarg\forest@node@Compute@numeric@ts@info@{\forest@cn}% +} +\def\forest@node@Compute@numeric@ts@info#1{% + \expandnumberarg\forest@node@Compute@numeric@ts@info@{#1}% +} +\def\forest@node@rootid{% + \expandnumberarg\forest@node@Rootid{\forest@cn}% +} +\def\forest@node@Rootid#1{% #1=node + \ifnum\forestOve{#1}{@parent}=0 + #1% + \else + \@escapeif{\expandnumberarg\forest@node@Rootid{\forestOve{#1}{@parent}}}% + \fi +} +\def\forest@node@nthchildid#1{% #1=n + \ifnum#1<1 + 0% + \else + \expandnumberarg\forest@node@nthchildid@{\number\forestove{@first}}{#1}% + \fi +} +\def\forest@node@nthchildid@#1#2{% + \ifnum#1=0 + 0% + \else + \ifnum#2>1 + \@escapeifif{\expandtwonumberargs + \forest@node@nthchildid@{\forestOve{#1}{@next}}{\numexpr#2-1}}% + \else + #1% + \fi + \fi +} +\def\forest@node@nbarthchildid#1{% #1=n + \expandnumberarg\forest@node@nbarthchildid@{\number\forestove{@last}}{#1}% +} +\def\forest@node@nbarthchildid@#1#2{% + \ifnum#1=0 + 0% + \else + \ifnum#2>1 + \@escapeifif{\expandtwonumberargs + \forest@node@nbarthchildid@{\forestOve{#1}{@previous}}{\numexpr#2-1}}% + \else + #1% + \fi + \fi +} +\def\forest@node@nornbarthchildid#1{% + \ifnum#1>0 + \forest@node@nthchildid{#1}% + \else + \ifnum#1<0 + \forest@node@nbarthchildid{-#1}% + \else + \forest@node@nornbarthchildid@error + \fi + \fi +} +\def\forest@node@nornbarthchildid@error{% + \PackageError{forest}{In \string\forest@node@nornbarthchildid, n should !=0}{}% +} +\def\forest@node@previousleafid{% + \expandnumberarg\forest@node@Previousleafid{\forest@cn}% +} +\def\forest@node@Previousleafid#1{% + \ifnum\forestOve{#1}{@previous}=0 + \@escapeif{\expandnumberarg\forest@node@previousleafid@Goup{#1}}% + \else + \expandnumberarg\forest@node@previousleafid@Godown{\forestOve{#1}{@previous}}% + \fi +} +\def\forest@node@previousleafid@Goup#1{% + \ifnum\forestOve{#1}{@parent}=0 + \PackageError{forest}{get previous leaf: this is the first leaf}{}% + \else + \@escapeif{\expandnumberarg\forest@node@Previousleafid{\forestOve{#1}{@parent}}}% + \fi +} +\def\forest@node@previousleafid@Godown#1{% + \ifnum\forestOve{#1}{@last}=0 + #1% + \else + \@escapeif{\expandnumberarg\forest@node@previousleafid@Godown{\forestOve{#1}{@last}}}% + \fi +} +\def\forest@node@nextleafid{% + \expandnumberarg\forest@node@Nextleafid{\forest@cn}% +} +\def\forest@node@Nextleafid#1{% + \ifnum\forestOve{#1}{@next}=0 + \@escapeif{\expandnumberarg\forest@node@nextleafid@Goup{#1}}% + \else + \expandnumberarg\forest@node@nextleafid@Godown{\forestOve{#1}{@next}}% + \fi +} +\def\forest@node@nextleafid@Goup#1{% + \ifnum\forestOve{#1}{@parent}=0 + \PackageError{forest}{get next leaf: this is the last leaf}{}% + \else + \@escapeif{\expandnumberarg\forest@node@Nextleafid{\forestOve{#1}{@parent}}}% + \fi +} +\def\forest@node@nextleafid@Godown#1{% + \ifnum\forestOve{#1}{@first}=0 + #1% + \else + \@escapeif{\expandnumberarg\forest@node@nextleafid@Godown{\forestOve{#1}{@first}}}% + \fi +} + +\def\forest@node@linearnextid{% + \ifnum\forestove{@first}=0 + \expandafter\forest@node@linearnextnotdescendantid + \else + \forestove{@first}% + \fi +} +\def\forest@node@linearnextnotdescendantid{% + \expandnumberarg\forest@node@Linearnextnotdescendantid{\forest@cn}% +} +\def\forest@node@Linearnextnotdescendantid#1{% + \ifnum\forestOve{#1}{@next}=0 + \ifnum\forestOve{#1}{@parent}=0 + 0% + \else + \@escapeifif{\expandnumberarg\forest@node@Linearnextnotdescendantid{\forestOve{#1}{@parent}}}% + \fi + \else + \forestOve{#1}{@next}% + \fi +} +\def\forest@node@linearpreviousid{% + \ifnum\forestove{@previous}=0 + \forestove{@parent}% + \else + \forest@node@previousleafid + \fi +} + +\def\forest@ifancestorof#1{% is the current node an ancestor of #1? Yes: #2, no: #3 + \begingroup + \expandnumberarg\forest@ifancestorof@{\forestOve{#1}{@parent}}% +} +\def\forest@ifancestorof@#1{% + \ifnum#1=0 + \def\forest@ifancestorof@next{\expandafter\endgroup\@secondoftwo}% + \else + \ifnum\forest@cn=#1 + \def\forest@ifancestorof@next{\expandafter\endgroup\@firstoftwo}% + \else + \ifcsdef{forest@circularity@used#1}{% + \def\forest@ifancestorof@next{\expandafter\endgroup\@secondoftwo}% + }{% + \csdef{forest@circularity@used#1}{}% + \def\forest@ifancestorof@next{\expandnumberarg\forest@ifancestorof@{\forestOve{#1}{@parent}}}% + }% + \fi + \fi + \forest@ifancestorof@next +} +\NewDocumentCommand\forestdebugtypeouttrees{o}{% + \forestdebug@typeouttrees\forest@temp + \typeout{\IfValueTF{#1}{#1: }{}\forest@temp}% +} +\def\forestdebug@typeouttrees#1{% #1 = cs to store the result + \begingroup + \edef\forest@temp@message{}% + \def\forestdebug@typeouttrees@n{0}% + \loop + \ifnum\forestdebug@typeouttrees@n<\forest@node@maxid + \edef\forestdebug@typeouttrees@n{\number\numexpr\forestdebug@typeouttrees@n+1}% + \ifcsdef{forestdebug@typeouttree@used@\forestdebug@typeouttrees@n}{}{% + \forest@fornode{\forestdebug@typeouttrees@n}{% + \begingroup + \forestdebug@typeouttrees@findroot + \expandafter\endgroup + \expandafter\edef\expandafter\forest@cn\expandafter{\forest@cn}% + \forestdebug@typeouttree@build + \appto\forest@temp@message{\space}% + }% + }% + \repeat + \expandafter\endgroup + \expandafter\edef\expandafter#1\expandafter{\forest@temp@message}% +} +\def\forestdebug@typeouttrees@findroot{% + \let\forestdebug@typeouttrees@next\relax + \edef\forestdebug@typeouttrees@parent{\forestOve{\forest@cn}{@parent}}% + \ifnum\forestdebug@typeouttrees@parent=0 + \else + \ifcsdef{forestdebug@typeouttree@used@\forest@cn}{}{% + \csdef{forestdebug@typeouttree@used@\forest@cn}{}% + \edef\forest@cn{\forestdebug@typeouttrees@parent}% + \let\forestdebug@typeouttrees@next\forestdebug@typeouttrees@findroot + }% + \fi + \forestdebug@typeouttrees@next +} +\def\forestdebug@typeouttree#1#2{% #1=root id, #2=cs to receive result + \begingroup + \edef\forest@temp@message{}% + \forest@fornode{#1}{\forestdebug@typeouttree@build}% + \expandafter\endgroup + \expandafter\edef\expandafter#2\expandafter{\forest@temp@message}% +} +\NewDocumentCommand\forestdebugtypeouttree{o m}{% + \forestdebug@typeouttree{#1}\forest@temp + \typeout{\IfValueTF{#1}{#1: }{}\forest@temp}% +} +\def\forestdebug@typeouttree@build{% + \eappto\forest@temp@message{[\forest@cn%] + \ifcsdef{forestdebug@typeouttree@used@\forest@cn}{*}{}% + }% + \ifcsdef{forestdebug@typeouttree@used@\forest@cn}{}{% + \csdef{forestdebug@typeouttree@used@\forest@cn}{}% + \forest@node@foreachchild{\forestdebug@typeouttree@build}% + }% + \eappto\forest@temp@message{%[ + ]}% +} +\def\forest@declarehandler#1#2#3{%#1=handler for specific type,#2=option name,#3=default value + \pgfkeyssetvalue{/forest/#2}{#3}% + \appto\forest@node@init{\forestoinit{#2}}% + \pgfkeyssetvalue{/forest/#2/node@or@reg}{\forest@cn}% + \forest@convert@others@to@underscores{#2}\forest@pgfmathoptionname + \edef\forest@marshal{% + \noexpand#1{/forest/#2}{/forest}{#2}{\forest@pgfmathoptionname}% + }\forest@marshal +} +\def\forest@def@with@pgfeov#1#2{% \pgfeov mustn't occur in the arg of the .code handler!!! + \long\def#1##1\pgfeov{#2}% +} +\def\forest@declaretoks@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \forest@declaretoks@handler@A{#1}{#2}{#3}{#4}{}% +} +\def\forest@declarekeylist@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \forest@declaretoks@handler@A{#1}{#2}{#3}{#4}{,}% + \forest@copycommandkey{#1}{#1'}% + \pgfkeyssetvalue{#1'/option@name}{#3}% + \forest@copycommandkey{#1+}{#1}% + \pgfkeysalso{#1-/.code={% + \forest@fornode{\forest@setter@node}{% + \forest@node@removekeysfromkeylist{##1}{#3}% + }}}% + \pgfkeyssetvalue{#1-/option@name}{#3}% +} +\def\forest@declaretoks@handler@A#1#2#3#4#5{% #1=key,#2=path,#3=name,#4=pgfmathname,#5=infix + \pgfkeysalso{% + #1/.code={\forestOset{\forest@setter@node}{#3}{##1}}, + #2/if #3/.code n args={3}{% + \forestoget{#3}\forest@temp@option@value + \edef\forest@temp@compared@value{\unexpanded{##1}}% + \ifx\forest@temp@option@value\forest@temp@compared@value + \pgfkeysalso{##2}% + \else + \pgfkeysalso{##3}% + \fi + }, + #2/if in #3/.code n args={3}{% + \forestoget{#3}\forest@temp@option@value + \edef\forest@temp@compared@value{\unexpanded{##1}}% + \expandafter\expandafter\expandafter\pgfutil@in@\expandafter\expandafter\expandafter{\expandafter\forest@temp@compared@value\expandafter}\expandafter{\forest@temp@option@value}% + \ifpgfutil@in@ + \pgfkeysalso{##2}% + \else + \pgfkeysalso{##3}% + \fi + }, + #2/where #3/.style n args={3}{for tree={#2/if #3={##1}{##2}{##3}}}, + #2/where in #3/.style n args={3}{for tree={#2/if in #3={##1}{##2}{##3}}} + }% + \ifstrempty{#5}{% + \pgfkeysalso{% + #1+/.code={\forestOappto{\forest@setter@node}{#3}{#5##1}}, + #2/+#3/.code={\forestOpreto{\forest@setter@node}{#3}{##1#5}}, + }% + }{% + \pgfkeysalso{% + #1+/.code={% + \forestOget{\forest@setter@node}{#3}\forest@temp + \ifdefempty{\forest@temp}{% + \forestOset{\forest@setter@node}{#3}{##1}% + }{% + \forestOappto{\forest@setter@node}{#3}{#5##1}% + }% + }, + #2/+#3/.code={% + \forestOget{\forest@setter@node}{#3}\forest@temp + \ifdefempty{\forest@temp}{% + \forestOset{\forest@setter@node}{#3}{##1}% + }{% + \forestOpreto{\forest@setter@node}{#3}{##1#5}% + }% + }% + }% + }% + \pgfkeyssetvalue{#1/option@name}{#3}% + \pgfkeyssetvalue{#1+/option@name}{#3}% + \pgfkeyssetvalue{#2/+#3/option@name}{#3}% + \pgfmathdeclarefunction{#4}{1}{\forest@pgfmathhelper@attribute@toks{##1}{#3}}% +} +\def\forest@declareautowrappedtoks@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname,#5=infix + \forest@declaretoks@handler{#1}{#2}{#3}{#4}% + \forest@copycommandkey{#1}{#1'}% + \pgfkeysalso{#1/.style={#1'/.wrap value={##1}}}% + \pgfkeyssetvalue{#1'/option@name}{#3}% + \forest@copycommandkey{#1+}{#1+'}% + \pgfkeysalso{#1+/.style={#1+'/.wrap value={##1}}}% + \pgfkeyssetvalue{#1+'/option@name}{#3}% + \forest@copycommandkey{#2/+#3}{#2/+#3'}% + \pgfkeysalso{#2/+#3/.style={#2/+#3'/.wrap value={##1}}}% + \pgfkeyssetvalue{#2/+#3'/option@name}{#3}% +} +\def\forest@declarereadonlydimen@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + % this is to have `pt` with the correct category code + \pgfutil@tempdima=\pgfkeysvalueof{/forest/#3}\relax + \edef\forest@marshal{% + \noexpand\pgfkeyssetvalue{/forest/#3}{\the\pgfutil@tempdima}% + }\forest@marshal + \pgfkeysalso{% + #2/if #3/.code n args={3}{% + \forestoget{#3}\forest@temp@option@value + \ifdim\forest@temp@option@value=##1\relax + \pgfkeysalso{##2}% + \else + \pgfkeysalso{##3}% + \fi + }, + #2/where #3/.style n args={3}{for tree={#2/if #3={##1}{##2}{##3}}}, + }% + \pgfmathdeclarefunction{#4}{1}{\forest@pgfmathhelper@attribute@dimen{##1}{#3}}% +} +\def\forest@declaredimen@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \forest@declarereadonlydimen@handler{#1}{#2}{#3}{#4}% + \pgfkeysalso{% + #1/.code={% + \pgfmathsetlengthmacro\forest@temp{##1}% + \forestOlet{\forest@setter@node}{#3}\forest@temp + }, + #1+/.code={% + \pgfmathsetlengthmacro\forest@temp{##1}% + \pgfutil@tempdima=\forestove{#3} + \advance\pgfutil@tempdima\forest@temp\relax + \forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% + }, + #1-/.code={% + \pgfmathsetlengthmacro\forest@temp{##1}% + \pgfutil@tempdima=\forestove{#3} + \advance\pgfutil@tempdima-\forest@temp\relax + \forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% + }, + #1*/.style={% + #1={#4()*(##1)}% + }, + #1:/.style={% + #1={#4()/(##1)}% + }, + #1'/.code={% + \pgfutil@tempdima=##1\relax + \forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% + }, + #1'+/.code={% + \pgfutil@tempdima=\forestove{#3}\relax + \advance\pgfutil@tempdima##1\relax + \forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% + }, + #1'-/.code={% + \pgfutil@tempdima=\forestove{#3}\relax + \advance\pgfutil@tempdima-##1\relax + \forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% + }, + #1'*/.style={% + \pgfutil@tempdima=\forestove{#3}\relax + \multiply\pgfutil@tempdima##1\relax + \forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% + }, + #1':/.style={% + \pgfutil@tempdima=\forestove{#3}\relax + \divide\pgfutil@tempdima##1\relax + \forestOeset{\forest@setter@node}{#3}{\the\pgfutil@tempdima}% + }, + }% + \pgfkeyssetvalue{#1/option@name}{#3}% + \pgfkeyssetvalue{#1+/option@name}{#3}% + \pgfkeyssetvalue{#1-/option@name}{#3}% + \pgfkeyssetvalue{#1*/option@name}{#3}% + \pgfkeyssetvalue{#1:/option@name}{#3}% + \pgfkeyssetvalue{#1'/option@name}{#3}% + \pgfkeyssetvalue{#1'+/option@name}{#3}% + \pgfkeyssetvalue{#1'-/option@name}{#3}% + \pgfkeyssetvalue{#1'*/option@name}{#3}% + \pgfkeyssetvalue{#1':/option@name}{#3}% +} +\def\forest@declarereadonlycount@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \pgfkeysalso{ + #2/if #3/.code n args={3}{% + \forestoget{#3}\forest@temp@option@value + \ifnum\forest@temp@option@value=##1\relax + \pgfkeysalso{##2}% + \else + \pgfkeysalso{##3}% + \fi + }, + #2/where #3/.style n args={3}{for tree={#2/if #3={##1}{##2}{##3}}}, + }% + \pgfmathdeclarefunction{#4}{1}{\forest@pgfmathhelper@attribute@count{##1}{#3}}% +} +\def\forest@declarecount@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \forest@declarereadonlycount@handler{#1}{#2}{#3}{#4}% + \pgfkeysalso{ + #1/.code={% + \pgfmathtruncatemacro\forest@temp{##1}% + \forestOlet{\forest@setter@node}{#3}\forest@temp + }, + #1+/.code={% + \pgfmathtruncatemacro\forest@temp{##1}% + \c@pgf@counta=\forestove{#3}\relax + \advance\c@pgf@counta\forest@temp\relax + \forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% + }, + #1-/.code={% + \pgfmathtruncatemacro\forest@temp{##1}% + \c@pgf@counta=\forestove{#3}\relax + \advance\c@pgf@counta-\forest@temp\relax + \forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% + }, + #1*/.code={% + \pgfmathtruncatemacro\forest@temp{##1}% + \c@pgf@counta=\forestove{#3}\relax + \multiply\c@pgf@counta\forest@temp\relax + \forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% + }, + #1:/.code={% + \pgfmathtruncatemacro\forest@temp{##1}% + \c@pgf@counta=\forestove{#3}\relax + \divide\c@pgf@counta\forest@temp\relax + \forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% + }, + #1'/.code={% + \c@pgf@counta=##1\relax + \forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% + }, + #1'+/.code={% + \c@pgf@counta=\forestove{#3}\relax + \advance\c@pgf@counta##1\relax + \forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% + }, + #1'-/.code={% + \c@pgf@counta=\forestove{#3}\relax + \advance\c@pgf@counta-##1\relax + \forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% + }, + #1'*/.style={% + \c@pgf@counta=\forestove{#3}\relax + \multiply\c@pgf@counta##1\relax + \forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% + }, + #1':/.style={% + \c@pgf@counta=\forestove{#3}\relax + \divide\c@pgf@counta##1\relax + \forestOeset{\forest@setter@node}{#3}{\the\c@pgf@counta}% + }, + }% + \pgfkeyssetvalue{#1/option@name}{#3}% + \pgfkeyssetvalue{#1+/option@name}{#3}% + \pgfkeyssetvalue{#1-/option@name}{#3}% + \pgfkeyssetvalue{#1*/option@name}{#3}% + \pgfkeyssetvalue{#1:/option@name}{#3}% + \pgfkeyssetvalue{#1'/option@name}{#3}% + \pgfkeyssetvalue{#1'+/option@name}{#3}% + \pgfkeyssetvalue{#1'-/option@name}{#3}% + \pgfkeyssetvalue{#1'*/option@name}{#3}% + \pgfkeyssetvalue{#1':/option@name}{#3}% +} +\def\forest@declareboolean@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \pgfkeysalso{% + #1/.code={% + \ifstrequal{##1}{1}{% + \forestOset{\forest@setter@node}{#3}{1}% + }{% + \ifstrequal{##1}{0}{% + \forestOset{\forest@setter@node}{#3}{0}% + }{% + \pgfmathifthenelse{##1}{1}{0}% + \forestOlet{\forest@setter@node}{#3}\pgfmathresult + }% + }% + }, + #1/.default=1, + #2/not #3/.code={\forestOset{\forest@setter@node}{#3}{0}}, + #2/if #3/.code 2 args={% + \forestoget{#3}\forest@temp@option@value + \ifnum\forest@temp@option@value=1 + \pgfkeysalso{##1}% + \else + \pgfkeysalso{##2}% + \fi + }, + #2/where #3/.style 2 args={for tree={#2/if #3={##1}{##2}}} + }% + \pgfkeyssetvalue{#1/option@name}{#3}% + \pgfmathdeclarefunction{#4}{1}{\forest@pgfmathhelper@attribute@count{##1}{#3}}% +} +\forestset{ + declare toks/.code 2 args={% + \forest@declarehandler\forest@declaretoks@handler{#1}{#2}% + }, + declare autowrapped toks/.code 2 args={% + \forest@declarehandler\forest@declareautowrappedtoks@handler{#1}{#2}% + }, + declare keylist/.code 2 args={% + \forest@declarehandler\forest@declarekeylist@handler{#1}{#2}% + }, + declare readonly dimen/.code 2 args={% + \pgfmathsetlengthmacro\forest@temp{#2}% + \edef\forest@marshal{% + \unexpanded{\forest@declarehandler\forest@declarereadonlydimen@handler{#1}}{\forest@temp}% + }\forest@marshal + }, + declare dimen/.code 2 args={% + \pgfmathsetlengthmacro\forest@temp{#2}% + \edef\forest@marshal{% + \unexpanded{\forest@declarehandler\forest@declaredimen@handler{#1}}{\forest@temp}% + }\forest@marshal + }, + declare readonly count/.code 2 args={% + \pgfmathtruncatemacro\forest@temp{#2}% + \edef\forest@marshal{% + \unexpanded{\forest@declarehandler\forest@declarereadonlycount@handler{#1}}{\forest@temp}% + }\forest@marshal + }, + declare count/.code 2 args={% + \pgfmathtruncatemacro\forest@temp{#2}% + \edef\forest@marshal{% + \unexpanded{\forest@declarehandler\forest@declarecount@handler{#1}}{\forest@temp}% + }\forest@marshal + }, + declare boolean/.code 2 args={% + \pgfmathtruncatemacro\forest@temp{#2}% + \edef\forest@marshal{% + \unexpanded{\forest@declarehandler\forest@declareboolean@handler{#1}}{\forest@temp}% + }\forest@marshal + }, + /handlers/.restore default value/.code={% + \edef\forest@handlers@currentpath{\pgfkeyscurrentpath}% + \pgfkeysgetvalue{\pgfkeyscurrentpath/option@name}\forest@currentoptionname + \pgfkeysgetvalue{/forest/\forest@currentoptionname}\forest@temp + \expandafter\pgfkeysalso\expandafter{\forest@handlers@currentpath/.expand once=\forest@temp}% + }, + /handlers/.pgfmath/.code={% + \pgfmathparse{#1}% + \pgfkeysalso{\pgfkeyscurrentpath/.expand once=\pgfmathresult}% + }, + /handlers/.wrap value/.code={% + \edef\forest@handlers@wrap@currentpath{\pgfkeyscurrentpath}% + \pgfkeysgetvalue{\forest@handlers@wrap@currentpath/option@name}\forest@currentoptionname + \forestOget{\pgfkeysvalueof{/forest/\forest@currentoptionname/node@or@reg}}{\forest@currentoptionname}\forest@option@value + \forest@def@with@pgfeov\forest@wrap@code{#1}% + \expandafter\edef\expandafter\forest@wrapped@value\expandafter{\expandafter\expandonce\expandafter{\expandafter\forest@wrap@code\forest@option@value\pgfeov}}% + \pgfkeysalso{\forest@handlers@wrap@currentpath/.expand once=\forest@wrapped@value}% + }, + /handlers/.option/.code={% + \edef\forest@marshal{% + \noexpand\pgfkeysalso{\pgfkeyscurrentpath={\forestoption{#1}}}% + }\forest@marshal + }, + /handlers/.register/.code={% + \edef\forest@marshal{% + \noexpand\pgfkeysalso{\pgfkeyscurrentpath={\forestregister{#1}}}% + }\forest@marshal + }, + /handlers/.wrap pgfmath arg/.code 2 args={% + \pgfmathparse{#2}\let\forest@wrap@arg@i\pgfmathresult + \edef\forest@wrap@args{{\expandonce\forest@wrap@arg@i}}% + \def\forest@wrap@code##1{#1}% + % here we don't call \forest@wrap@pgfmath@args@@@wrapandpasson, as compat-2.0.2-wrappgfmathargs changes that to achieve the old, confusing state of affairs, which *didn't* apply at *1*-arg pgfmath wrapping + \expandafter\expandafter\expandafter\forest@temp@toks\expandafter\expandafter\expandafter{\expandafter\forest@wrap@code\forest@wrap@args}% + \expandafter\pgfkeysalso\expandafter{\expandafter\pgfkeyscurrentpath\expandafter=\expandafter{\the\forest@temp@toks}}% + }, + /handlers/.wrap 2 pgfmath args/.code n args={3}{% + \pgfmathparse{#2}\let\forest@wrap@arg@i\pgfmathresult + \pgfmathparse{#3}\let\forest@wrap@arg@ii\pgfmathresult + \edef\forest@wrap@args{{\expandonce\forest@wrap@arg@i}{\expandonce\forest@wrap@arg@ii}}% + \def\forest@wrap@code##1##2{#1}% + \forest@wrap@pgfmath@args@@@wrapandpasson + }, + /handlers/.wrap 3 pgfmath args/.code n args={4}{% + \forest@wrap@n@pgfmath@args{#2}{#3}{#4}{}{}{}{}{}{3}% + \forest@wrap@n@pgfmath@do{#1}{3}}, + /handlers/.wrap 4 pgfmath args/.code n args={5}{% + \forest@wrap@n@pgfmath@args{#2}{#3}{#4}{#5}{}{}{}{}{4}% + \forest@wrap@n@pgfmath@do{#1}{4}}, + /handlers/.wrap 5 pgfmath args/.code n args={6}{% + \forest@wrap@n@pgfmath@args{#2}{#3}{#4}{#5}{#6}{}{}{}{5}% + \forest@wrap@n@pgfmath@do{#1}{5}}, + /handlers/.wrap 6 pgfmath args/.code n args={7}{% + \forest@wrap@n@pgfmath@args{#2}{#3}{#4}{#5}{#6}{#7}{}{}{6}% + \forest@wrap@n@pgfmath@do{#1}{6}}, + /handlers/.wrap 7 pgfmath args/.code n args={8}{% + \forest@wrap@n@pgfmath@args{#2}{#3}{#4}{#5}{#6}{#7}{#8}{}{7}% + \forest@wrap@n@pgfmath@do{#1}{7}}, + /handlers/.wrap 8 pgfmath args/.code n args={9}{% + \forest@wrap@n@pgfmath@args{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}{8}% + \forest@wrap@n@pgfmath@do{#1}{8}}, + /handlers/.process args/.code={% + \forest@processargs#1\forest@eov\forest@END + }, +} +\def\forest@wrap@n@pgfmath@args#1#2#3#4#5#6#7#8#9{% + \pgfmathparse{#1}\let\forest@wrap@arg@i\pgfmathresult + \ifnum#9>1 \pgfmathparse{#2}\let\forest@wrap@arg@ii\pgfmathresult\fi + \ifnum#9>2 \pgfmathparse{#3}\let\forest@wrap@arg@iii\pgfmathresult\fi + \ifnum#9>3 \pgfmathparse{#4}\let\forest@wrap@arg@iv\pgfmathresult\fi + \ifnum#9>4 \pgfmathparse{#5}\let\forest@wrap@arg@v\pgfmathresult\fi + \ifnum#9>5 \pgfmathparse{#6}\let\forest@wrap@arg@vi\pgfmathresult\fi + \ifnum#9>6 \pgfmathparse{#7}\let\forest@wrap@arg@vii\pgfmathresult\fi + \ifnum#9>7 \pgfmathparse{#8}\let\forest@wrap@arg@viii\pgfmathresult\fi + \edef\forest@wrap@args{% + {\expandonce\forest@wrap@arg@i} + \ifnum#9>1 {\expandonce\forest@wrap@arg@ii}\fi + \ifnum#9>2 {\expandonce\forest@wrap@arg@iii}\fi + \ifnum#9>3 {\expandonce\forest@wrap@arg@iv}\fi + \ifnum#9>4 {\expandonce\forest@wrap@arg@v}\fi + \ifnum#9>5 {\expandonce\forest@wrap@arg@vi}\fi + \ifnum#9>6 {\expandonce\forest@wrap@arg@vii}\fi + \ifnum#9>7 {\expandonce\forest@wrap@arg@viii}\fi + }% +} +\def\forest@wrap@n@pgfmath@do#1#2{% + \ifcase#2\relax + \or\def\forest@wrap@code##1{#1}% + \or\def\forest@wrap@code##1##2{#1}% + \or\def\forest@wrap@code##1##2##3{#1}% + \or\def\forest@wrap@code##1##2##3##4{#1}% + \or\def\forest@wrap@code##1##2##3##4##5{#1}% + \or\def\forest@wrap@code##1##2##3##4##5##6{#1}% + \or\def\forest@wrap@code##1##2##3##4##5##6##7{#1}% + \or\def\forest@wrap@code##1##2##3##4##5##6##7##8{#1}% + \fi + \forest@wrap@pgfmath@args@@@wrapandpasson +} +\def\forest@wrap@pgfmath@args@@@wrapandpasson{% + \expandafter\expandafter\expandafter\forest@temp@toks + \expandafter\expandafter\expandafter{% + \expandafter\forest@wrap@code\forest@wrap@args}% + \expandafter\pgfkeysalso\expandafter{% + \expandafter\pgfkeyscurrentpath\expandafter=\expandafter{% + \the\forest@temp@toks}}% +} +\newtoks\forest@processargs@result +\newtoks\forest@processargs@current +\newif\ifforest@processargs@append +\def\forest@eov{\forest@eov} +\def\forest@processargs#1#2\forest@END{% #1 = processing instructions, #2 = args + \forest@processargs@result{}% + \forest@processargs@current{}% + \forest@processargs@appendfalse + \forest@processargs@getins#1.\forest@END#2\forest@END +} +\def\forest@processargs@maybeappend{% + \ifforest@processargs@append + \eapptotoks\forest@processargs@result{{\the\forest@processargs@current}}% + \forest@processargs@current{}% + \fi +} +\def\forest@processargs@getins#1#2\forest@END#3\forest@END{% #1 = first instruction, #2 = rest of instructions, #3 = args + \csname forest@processargs@ins@#1\endcsname#2\forest@END#3\forest@END +} +\csdef{forest@processargs@ins@.}\forest@END#1\forest@END{% + \forest@processargs@maybeappend + \forest@processargs@appremainingargs#1\forest@END +} +\def\forest@processargs@appremainingargs#1#2\forest@END{% + \edef\forest@temp{\unexpanded{#1}}% + \ifx\forest@temp\forest@eov + \let\forest@processargs@next\forest@processargs@done + \else + \apptotoks\forest@processargs@result{{#1}}% + \let\forest@processargs@next\forest@processargs@appremainingargs + \fi + \forest@processargs@next#2\forest@END +} +\def\forest@processargs@done#1\forest@END{% + \pgfkeysalso{\pgfkeyscurrentpath/.expanded=\the\forest@processargs@result}% +} +\csdef{forest@processargs@ins@_}#1\forest@END#2#3\forest@END{% no processing + % #1 = rest of ins, #2 = first arg, #3 = rest of args + \forest@processargs@maybeappend + \forest@processargs@current{#2}% + \forest@processargs@appendtrue + \forest@processargs@getins#1\forest@END#3\forest@END +} +\csdef{forest@processargs@ins@x}#1\forest@END#2#3\forest@END{% expand + % #1 = rest of ins, #2 = first arg, #3 = rest of args + \forest@processargs@maybeappend + \etotoks\forest@processargs@current{#2}% + \forest@processargs@appendtrue + \forest@processargs@getins#1\forest@END#3\forest@END +} +\csdef{forest@processargs@ins@o}#1\forest@END#2#3\forest@END{% expand once + % #1 = rest of ins, #2 = first arg, #3 = rest of args + \forest@processargs@maybeappend + \expandafter\forest@processargs@current\expandafter{#2}% + \forest@processargs@appendtrue + \forest@processargs@getins#1\forest@END#3\forest@END +} +\csdef{forest@processargs@ins@O}#1\forest@END#2#3\forest@END{% option + % #1 = rest of ins, #2 = first arg, #3 = rest of args + \forest@processargs@maybeappend + \etotoks\forest@processargs@current{\forestoption{#2}}% + \forest@processargs@appendtrue + \forest@processargs@getins#1\forest@END#3\forest@END +} +\csdef{forest@processargs@ins@R}#1\forest@END#2#3\forest@END{% register + % #1 = rest of ins, #2 = first arg, #3 = rest of args + \forest@processargs@maybeappend + \etotoks\forest@processargs@current{\forestregister{#2}}% + \forest@processargs@appendtrue + \forest@processargs@getins#1\forest@END#3\forest@END +} +\csdef{forest@processargs@ins@P}#1\forest@END#2#3\forest@END{% pgfmath expression + % #1 = rest of ins, #2 = first arg, #3 = rest of args + \forest@processargs@maybeappend + \pgfmathparse{#2}% + \expandafter\forest@processargs@current\expandafter{\pgfmathresult}% + \forest@processargs@appendtrue + \forest@processargs@getins#1\forest@END#3\forest@END +} +\csdef{forest@processargs@ins@+}#1\forest@END#2\forest@END{% join processors + \forest@processargs@appendfalse + \edef\forest@marshal{% + \unexpanded{\forest@processargs@getins#1\forest@END}{\the\forest@processargs@current}\unexpanded{#2\forest@END}% + }\forest@marshal +} +\csdef{forest@processargs@ins@r}#1\forest@END#2#3\forest@END{% reverse keylist + % #1 = rest of ins, #2 = first arg, #3 = rest of args + \forest@processargs@maybeappend + \forest@processargs@current{}% + \pgfqkeys{/forest}{split={#2}{,}{reverse@keylist}}% + \forest@processargs@appendtrue + \forest@processargs@getins#1\forest@END#3\forest@END +} +\forestset{% + reverse@keylist/.code={% + \epretotoks\forest@processargs@current{#1,}% + }, +} +\def\forest@pgfmathhelper@register@toks#1#2{% #1 is discarded: it is present only for analogy with options + \forestrget{#2}\pgfmathresult +} +\def\forest@pgfmathhelper@register@dimen#1#2{% + \forestrget{#2}\forest@temp + \pgfmathparse{+\forest@temp}% +} +\def\forest@pgfmathhelper@register@count#1#2{% + \forestrget{#2}\forest@temp + \pgfmathtruncatemacro\pgfmathresult{\forest@temp}% +} +\def\forest@declareregisterhandler#1#2{%#1=handler for specific type,#2=option name + \pgfkeyssetvalue{/forest/#2/node@or@reg}{register}% + \forest@convert@others@to@underscores{#2}\forest@pgfmathoptionname + \edef\forest@marshal{% + \noexpand#1{/forest/#2}{/forest}{#2}{\forest@pgfmathoptionname}% + }\forest@marshal +} +\def\forest@declaretoksregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \forest@declaretoksregister@handler@A{#1}{#2}{#3}{#4}{}% +} +\def\forest@declarekeylistregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \forest@declaretoksregister@handler@A{#1}{#2}{#3}{#4}{,}% + \forest@copycommandkey{#1}{#1'}% + \pgfkeyssetvalue{#1'/option@name}{#3}% + \forest@copycommandkey{#1+}{#1}% + \pgfkeysalso{#1-/.code={% + \forest@fornode{register}{% + \forest@node@removekeysfromkeylist{##1}{#3}% + }}}% + \pgfkeyssetvalue{#1-/option@name}{#3}% +} +\def\forest@declaretoksregister@handler@A#1#2#3#4#5{% #1=key,#2=path,#3=name,#4=pgfmathname,#5=infix + \pgfkeysalso{% + #1/.code={\forestrset{#3}{##1}}, + #2/if #3/.code n args={3}{% + \forestrget{#3}\forest@temp@option@value + \edef\forest@temp@compared@value{\unexpanded{##1}}% + \ifx\forest@temp@option@value\forest@temp@compared@value + \pgfkeysalso{##2}% + \else + \pgfkeysalso{##3}% + \fi + }, + #2/if in #3/.code n args={3}{% + \forestrget{#3}\forest@temp@option@value + \edef\forest@temp@compared@value{\unexpanded{##1}}% + \expandafter\expandafter\expandafter\pgfutil@in@\expandafter\expandafter\expandafter{\expandafter\forest@temp@compared@value\expandafter}\expandafter{\forest@temp@option@value}% + \ifpgfutil@in@ + \pgfkeysalso{##2}% + \else + \pgfkeysalso{##3}% + \fi + }, + }% + \ifstrempty{#5}{% + \pgfkeysalso{% + #1+/.code={\forestrappto{#3}{#5##1}}, + #2/+#3/.code={\forestrpreto{#3}{##1#5}}, + }% + }{% + \pgfkeysalso{% + #1+/.code={% + \forestrget{#3}\forest@temp + \ifdefempty{\forest@temp}{% + \forestrset{#3}{##1}% + }{% + \forestrappto{#3}{#5##1}% + }% + }, + #2/+#3/.code={% + \forestrget{#3}\forest@temp + \ifdefempty{\forest@temp}{% + \forestrset{#3}{##1}% + }{% + \forestrpreto{#3}{##1#5}% + }% + }% + }% + }% + \pgfkeyssetvalue{#1/option@name}{#3}% + \pgfkeyssetvalue{#1+/option@name}{#3}% + \pgfkeyssetvalue{#2/+#3/option@name}{#3}% + \pgfmathdeclarefunction{#4}{1}{\forest@pgfmathhelper@register@toks{##1}{#3}}% +} +\def\forest@declareautowrappedtoksregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname,#5=infix + \forest@declaretoksregister@handler{#1}{#2}{#3}{#4}% + \forest@copycommandkey{#1}{#1'}% + \pgfkeysalso{#1/.style={#1'/.wrap value={##1}}}% + \pgfkeyssetvalue{#1'/option@name}{#3}% + \forest@copycommandkey{#1+}{#1+'}% + \pgfkeysalso{#1+/.style={#1+'/.wrap value={##1}}}% + \pgfkeyssetvalue{#1+'/option@name}{#3}% + \forest@copycommandkey{#2/+#3}{#2/+#3'}% + \pgfkeysalso{#2/+#3/.style={#2/+#3'/.wrap value={##1}}}% + \pgfkeyssetvalue{#2/+#3'/option@name}{#3}% +} +\def\forest@declarereadonlydimenregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \pgfkeysalso{% + #2/if #3/.code n args={3}{% + \forestrget{#3}\forest@temp@option@value + \ifdim\forest@temp@option@value=##1\relax + \pgfkeysalso{##2}% + \else + \pgfkeysalso{##3}% + \fi + }, + }% + \pgfmathdeclarefunction{#4}{1}{\forest@pgfmathhelper@register@dimen{##1}{#3}}% +} +\def\forest@declaredimenregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \forest@declarereadonlydimenregister@handler{#1}{#2}{#3}{#4}% + \pgfkeysalso{% + #1/.code={% + \pgfmathsetlengthmacro\forest@temp{##1}% + \forestrlet{#3}\forest@temp + }, + #1+/.code={% + \pgfmathsetlengthmacro\forest@temp{##1}% + \pgfutil@tempdima=\forestrve{#3} + \advance\pgfutil@tempdima\forest@temp\relax + \forestreset{#3}{\the\pgfutil@tempdima}% + }, + #1-/.code={% + \pgfmathsetlengthmacro\forest@temp{##1}% + \pgfutil@tempdima=\forestrve{#3} + \advance\pgfutil@tempdima-\forest@temp\relax + \forestreset{#3}{\the\pgfutil@tempdima}% + }, + #1*/.style={% + #1={#4()*(##1)}% + }, + #1:/.style={% + #1={#4()/(##1)}% + }, + #1'/.code={% + \pgfutil@tempdima=##1\relax + \forestreset{#3}{\the\pgfutil@tempdima}% + }, + #1'+/.code={% + \pgfutil@tempdima=\forestrve{#3}\relax + \advance\pgfutil@tempdima##1\relax + \forestreset{#3}{\the\pgfutil@tempdima}% + }, + #1'-/.code={% + \pgfutil@tempdima=\forestrve{#3}\relax + \advance\pgfutil@tempdima-##1\relax + \forestreset{#3}{\the\pgfutil@tempdima}% + }, + #1'*/.style={% + \pgfutil@tempdima=\forestrve{#3}\relax + \multiply\pgfutil@tempdima##1\relax + \forestreset{#3}{\the\pgfutil@tempdima}% + }, + #1':/.style={% + \pgfutil@tempdima=\forestrve{#3}\relax + \divide\pgfutil@tempdima##1\relax + \forestreset{#3}{\the\pgfutil@tempdima}% + }, + }% + \pgfkeyssetvalue{#1/option@name}{#3}% + \pgfkeyssetvalue{#1+/option@name}{#3}% + \pgfkeyssetvalue{#1-/option@name}{#3}% + \pgfkeyssetvalue{#1*/option@name}{#3}% + \pgfkeyssetvalue{#1:/option@name}{#3}% + \pgfkeyssetvalue{#1'/option@name}{#3}% + \pgfkeyssetvalue{#1'+/option@name}{#3}% + \pgfkeyssetvalue{#1'-/option@name}{#3}% + \pgfkeyssetvalue{#1'*/option@name}{#3}% + \pgfkeyssetvalue{#1':/option@name}{#3}% +} +\def\forest@declarereadonlycountregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \pgfkeysalso{ + #2/if #3/.code n args={3}{% + \forestrget{#3}\forest@temp@option@value + \ifnum\forest@temp@option@value=##1\relax + \pgfkeysalso{##2}% + \else + \pgfkeysalso{##3}% + \fi + }, + }% + \pgfmathdeclarefunction{#4}{1}{\forest@pgfmathhelper@register@count{##1}{#3}}% +} +\def\forest@declarecountregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \forest@declarereadonlycountregister@handler{#1}{#2}{#3}{#4}% + \pgfkeysalso{ + #1/.code={% + \pgfmathtruncatemacro\forest@temp{##1}% + \forestrlet{#3}\forest@temp + }, + #1+/.code={% + \pgfmathtruncatemacro\forest@temp{##1}% + \c@pgf@counta=\forestrve{#3}\relax + \advance\c@pgf@counta\forest@temp\relax + \forestreset{#3}{\the\c@pgf@counta}% + }, + #1-/.code={% + \pgfmathtruncatemacro\forest@temp{##1}% + \c@pgf@counta=\forestrve{#3}\relax + \advance\c@pgf@counta-\forest@temp\relax + \forestreset{#3}{\the\c@pgf@counta}% + }, + #1*/.code={% + \pgfmathtruncatemacro\forest@temp{##1}% + \c@pgf@counta=\forestrve{#3}\relax + \multiply\c@pgf@counta\forest@temp\relax + \forestreset{#3}{\the\c@pgf@counta}% + }, + #1:/.code={% + \pgfmathtruncatemacro\forest@temp{##1}% + \c@pgf@counta=\forestrve{#3}\relax + \divide\c@pgf@counta\forest@temp\relax + \forestreset{#3}{\the\c@pgf@counta}% + }, + #1'/.code={% + \c@pgf@counta=##1\relax + \forestreset{#3}{\the\c@pgf@counta}% + }, + #1'+/.code={% + \c@pgf@counta=\forestrve{#3}\relax + \advance\c@pgf@counta##1\relax + \forestreset{#3}{\the\c@pgf@counta}% + }, + #1'-/.code={% + \c@pgf@counta=\forestrve{#3}\relax + \advance\c@pgf@counta-##1\relax + \forestreset{#3}{\the\c@pgf@counta}% + }, + #1'*/.style={% + \c@pgf@counta=\forestrve{#3}\relax + \multiply\c@pgf@counta##1\relax + \forestreset{#3}{\the\c@pgf@counta}% + }, + #1':/.style={% + \c@pgf@counta=\forestrve{#3}\relax + \divide\c@pgf@counta##1\relax + \forestreset{#3}{\the\c@pgf@counta}% + }, + }% + \pgfkeyssetvalue{#1/option@name}{#3}% + \pgfkeyssetvalue{#1+/option@name}{#3}% + \pgfkeyssetvalue{#1-/option@name}{#3}% + \pgfkeyssetvalue{#1*/option@name}{#3}% + \pgfkeyssetvalue{#1:/option@name}{#3}% + \pgfkeyssetvalue{#1'/option@name}{#3}% + \pgfkeyssetvalue{#1'+/option@name}{#3}% + \pgfkeyssetvalue{#1'-/option@name}{#3}% + \pgfkeyssetvalue{#1'*/option@name}{#3}% + \pgfkeyssetvalue{#1':/option@name}{#3}% +} +\def\forest@declarebooleanregister@handler#1#2#3#4{% #1=key,#2=path,#3=name,#4=pgfmathname + \pgfkeysalso{% + #1/.code={% + \ifstrequal{##1}{1}{% + \forestrset{#3}{1}% + }{% + \ifstrequal{##1}{0}{% + \forestrset{#3}{0}% + }{% + \pgfmathifthenelse{##1}{1}{0}% + \forestrlet{#3}\pgfmathresult + }% + }% + }, + #1/.default=1, + #2/not #3/.code={\forestrset{#3}{0}}, + #2/if #3/.code 2 args={% + \forestrget{#3}\forest@temp@option@value + \ifnum\forest@temp@option@value=1 + \pgfkeysalso{##1}% + \else + \pgfkeysalso{##2}% + \fi + }, + }% + \pgfkeyssetvalue{#1/option@name}{#3}% + \pgfmathdeclarefunction{#4}{1}{\forest@pgfmathhelper@register@count{##1}{#3}}% +} +\forestset{ + declare toks register/.code={% + \forest@declareregisterhandler\forest@declaretoksregister@handler{#1}% + \forestset{#1={}}% + }, + declare autowrapped toks register/.code={% + \forest@declareregisterhandler\forest@declareautowrappedtoksregister@handler{#1}% + \forestset{#1={}}% + }, + declare keylist register/.code={% + \forest@declareregisterhandler\forest@declarekeylistregister@handler{#1}% + \forestset{#1'={}}% + }, + declare dimen register/.code={% + \forest@declareregisterhandler\forest@declaredimenregister@handler{#1}% + \forestset{#1'=0pt}% + }, + declare count register/.code={% + \forest@declareregisterhandler\forest@declarecountregister@handler{#1}% + \forestset{#1'=0}% + }, + declare boolean register/.code={% + \forest@declareregisterhandler\forest@declarebooleanregister@handler{#1}% + \forestset{#1=0}% + }, +} +\forestset{ + declare toks register=temptoksa,temptoksa={}, + declare toks register=temptoksb,temptoksb={}, + declare toks register=temptoksc,temptoksc={}, + declare toks register=temptoksd,temptoksd={}, + declare keylist register=tempkeylista,tempkeylista'={}, + declare keylist register=tempkeylistb,tempkeylistb'={}, + declare keylist register=tempkeylistc,tempkeylistc'={}, + declare keylist register=tempkeylistd,tempkeylistd'={}, + declare dimen register=tempdima,tempdima'={0pt}, + declare dimen register=tempdimb,tempdimb'={0pt}, + declare dimen register=tempdimc,tempdimc'={0pt}, + declare dimen register=tempdimd,tempdimd'={0pt}, + declare dimen register=tempdimx,tempdimx'={0pt}, + declare dimen register=tempdimxa,tempdimxa'={0pt}, + declare dimen register=tempdimxb,tempdimxb'={0pt}, + declare dimen register=tempdimy,tempdimy'={0pt}, + declare dimen register=tempdimya,tempdimya'={0pt}, + declare dimen register=tempdimyb,tempdimyb'={0pt}, + declare dimen register=tempdiml,tempdiml'={0pt}, + declare dimen register=tempdimla,tempdimla'={0pt}, + declare dimen register=tempdimlb,tempdimlb'={0pt}, + declare dimen register=tempdims,tempdims'={0pt}, + declare dimen register=tempdimsa,tempdimsa'={0pt}, + declare dimen register=tempdimsb,tempdimsb'={0pt}, + declare count register=tempcounta,tempcounta'={0}, + declare count register=tempcountb,tempcountb'={0}, + declare count register=tempcountc,tempcountc'={0}, + declare count register=tempcountd,tempcountd'={0}, + declare boolean register=tempboola,tempboola={0}, + declare boolean register=tempboolb,tempboolb={0}, + declare boolean register=tempboolc,tempboolc={0}, + declare boolean register=tempboold,tempboold={0}, +} +\def\forest@node@Nametoid#1{% #1 = name + \csname forest@id@of@#1\endcsname +} +\def\forest@node@Ifnamedefined#1#2#3{% #1 = name, #2=true,#3=false + \ifcsvoid{forest@id@of@#1}{#3}{#2}% +} +\def\forest@node@setname#1{% + \def\forest@temp@setname{y}% + \def\forest@temp@silent{n}% + \def\forest@temp@propagating{n}% + \forest@node@setnameoralias{#1}% +} +\def\forest@node@setname@silent#1{% + \def\forest@temp@setname{y}% + \def\forest@temp@silent{y}% + \def\forest@temp@propagating{n}% + \forest@node@setnameoralias{#1}% +} +\def\forest@node@setalias#1{% + \def\forest@temp@setname{n}% + \def\forest@temp@silent{n}% + \def\forest@temp@propagating{n}% + \forest@node@setnameoralias{#1}% +} +\def\forest@node@setalias@silent#1{% + \def\forest@temp@setname{n}% + \def\forest@temp@silent{y}% + \def\forest@temp@propagating{n}% + \forest@node@setnameoralias{#1}% +} +\def\forest@node@setnameoralias#1{% + \ifstrempty{#1}{% + \forest@node@setnameoralias{node@\forest@cn}% + }{% + \forest@node@Ifnamedefined{#1}{% + \if y\forest@temp@propagating + % this will find a unique name, eventually: + \@escapeif{\forest@node@setnameoralias{#1@\forest@cn}}% + \else\@escapeif{% + \if y\forest@temp@setname + \edef\forest@marshal{% + \ifstrequal{\forestove{name}}{#1}% + }\forest@marshal{% + % same name, no problem + }{% + \@escapeif{\forest@node@setnameoralias@nameclash{#1}}% + }% + \else\@escapeif{% setting an alias: clashing with alias is not a problem + \forestOget{\forest@node@Nametoid{#1}}{name}\forest@temp + \expandafter\ifstrequal\expandafter{\forest@temp}{#1}{% + \forest@node@setnameoralias@nameclash{#1}% + }{% + \forest@node@setnameoralias@do{#1}% + }% + }\fi + }\fi + }{% + \forest@node@setnameoralias@do{#1}% + }% + }% +} +\def\forest@node@setnameoralias@nameclash#1{% + \if y\forest@temp@silent + \forest@fornode{\forest@node@Nametoid{#1}}{% + \def\forest@temp@propagating{y}% + \forest@node@setnameoralias{}% + }% + \forest@node@setnameoralias@do{#1}% + \else + \PackageError{forest}{Node name "#1" is already used}{}% + \fi +} +\def\forest@node@setnameoralias@do#1{% + \if y\forest@temp@setname + \csdef{forest@id@of@\forestove{name}}{}% + \forestoeset{name}{#1}% + \fi + \csedef{forest@id@of@#1}{\forest@cn}% +} +\forestset{ + TeX/.code={#1}, + TeX'/.code={\appto\forest@externalize@loadimages{#1}#1}, + TeX''/.code={\appto\forest@externalize@loadimages{#1}}, + options/.code={\forestset{#1}}, + typeout/.style={TeX={\typeout{#1}}}, + declare toks={name}{}, + name/.code={% override the default setter + \forest@fornode{\forest@setter@node}{\forest@node@setname{#1}}% + }, + name/.default={}, + name'/.code={% override the default setter + \forest@fornode{\forest@setter@node}{\forest@node@setname@silent{#1}}% + }, + name'/.default={}, + alias/.code={\forest@fornode{\forest@setter@node}{\forest@node@setalias{#1}}}, + alias'/.code={\forest@fornode{\forest@setter@node}{\forest@node@setalias@silent{#1}}}, + begin draw/.code={\begin{tikzpicture}}, + end draw/.code={\end{tikzpicture}}, + declare keylist register=default preamble, + default preamble'={}, + declare keylist register=preamble, + preamble'={}, + declare autowrapped toks={content}{}, + % #1 = which option to split, #2 = separator (one char!), #3 = receiving options + %%% begin listing region: split_option + split option/.style n args=3{split/.process args={O}{#1}{#2}{#3}} + %%% end listing region: split_option + , + split register/.style n args=3{% #1 = which register to split, #2 = separator (one char!), #3 = receiving options + split/.process args={R}{#1}{#2}{#3}, + }, + TeX={% + \def\forest@split@sourcevalues{}% + \def\forest@split@sourcevalue{}% + \def\forest@split@receivingoptions{}% + \def\forest@split@receivingoption{}% + }, + split/.code n args=3{% #1 = string to split, #2 = separator (one char!), #3 = receiving options + \forest@saveandrestoremacro\forest@split@sourcevalues{% + \forest@saveandrestoremacro\forest@split@sourcevalue{% + \forest@saveandrestoremacro\forest@split@receivingoptions{% + \forest@saveandrestoremacro\forest@split@receivingoption{% + \def\forest@split@sourcevalues{#1#2}% + \edef\forest@split@receivingoptions{#3,}% + \def\forest@split@receivingoption{}% + \safeloop + \expandafter\forest@split\expandafter{\forest@split@sourcevalues}{#2}\forest@split@sourcevalue\forest@split@sourcevalues + \ifdefempty\forest@split@receivingoptions{}{% + \expandafter\forest@split\expandafter{\forest@split@receivingoptions}{,}\forest@temp\forest@split@receivingoptions + \ifdefempty\forest@temp{}{\let\forest@split@receivingoption\forest@temp\def\forest@temp{}}% + }% + \edef\forest@marshal{% + \noexpand\pgfkeysalso{\forest@split@receivingoption={\expandonce{\forest@split@sourcevalue}}}% + }\forest@marshal + \ifdefempty\forest@split@sourcevalues{\forest@tempfalse}{\forest@temptrue}% + \ifforest@temp + \saferepeat + }}}}% + }, + declare count={grow}{270}, + TeX={% a hack for grow-reversed connection, and compass-based grow specification + \forest@copycommandkey{/forest/grow}{/forest/grow@@}% + %\pgfkeysgetvalue{/forest/grow/.@cmd}\forest@temp + %\pgfkeyslet{/forest/grow@@/.@cmd}\forest@temp + }, + grow/.style={grow@={#1},reversed=0}, + grow'/.style={grow@={#1},reversed=1}, + grow''/.style={grow@={#1}}, + grow@/.is choice, + grow@/east/.style={/forest/grow@@=0}, + grow@/north east/.style={/forest/grow@@=45}, + grow@/north/.style={/forest/grow@@=90}, + grow@/north west/.style={/forest/grow@@=135}, + grow@/west/.style={/forest/grow@@=180}, + grow@/south west/.style={/forest/grow@@=225}, + grow@/south/.style={/forest/grow@@=270}, + grow@/south east/.style={/forest/grow@@=315}, + grow@/.unknown/.code={\let\forest@temp@grow\pgfkeyscurrentname + \pgfkeysalso{/forest/grow@@/.expand once=\forest@temp@grow}}, + declare boolean={reversed}{0}, + declare toks={parent anchor}{}, + declare toks={child anchor}{}, + declare toks={anchor}{base}, + Autoforward={anchor}{ + node options-=anchor, + node options+={anchor={##1}} + }, + anchor'/.style={anchor@no@compass=true,anchor=#1}, + anchor+'/.style={anchor@no@compass=true,anchor+=#1}, + anchor-'/.style={anchor@no@compass=true,anchor-=#1}, + anchor*'/.style={anchor@no@compass=true,anchor*=#1}, + anchor:'/.style={anchor@no@compass=true,anchor:=#1}, + anchor'+'/.style={anchor@no@compass=true,anchor'+=#1}, + anchor'-'/.style={anchor@no@compass=true,anchor'-=#1}, + anchor'*'/.style={anchor@no@compass=true,anchor'*=#1}, + anchor':'/.style={anchor@no@compass=true,anchor':=#1}, + % /tikz/forest anchor/.style={ + % /forest/TeX={\forestanchortotikzanchor{#1}\forest@temp@anchor}, + % anchor/.expand once=\forest@temp@anchor + % }, + declare toks={calign}{midpoint}, + TeX={% + \forest@copycommandkey{/forest/calign}{/forest/calign'}% + }, + calign/.is choice, + calign/child/.style={calign'=child}, + calign/first/.style={calign'=child,calign primary child=1}, + calign/last/.style={calign'=child,calign primary child=-1}, + calign with xshift code/.code={ + \ifx#1\relax\else + \forestset{for parent={calign xshift=#1}} + \fi + }, + calign with current/.style={for parent/.wrap pgfmath arg={calign=child,calign primary child=##1}{n}, calign with xshift code=#1,}, + calign with current/.default={\relax}, + calign with current edge/.style={for parent/.wrap pgfmath arg={calign=child edge,calign primary child=##1}{n}}, + calign/child edge/.style={calign'=child edge}, + calign/midpoint/.style={calign'=midpoint}, + calign/center/.style={calign'=midpoint,calign primary child=1,calign secondary child=-1}, + calign/edge midpoint/.style={calign'=edge midpoint}, + calign/fixed angles/.style={calign'=fixed angles}, + calign/fixed edge angles/.style={calign'=fixed edge angles}, + calign/.unknown/.code={\PackageError{forest}{unknown calign '\pgfkeyscurrentname'}{}}, + declare count={calign primary child}{1}, + declare count={calign secondary child}{-1}, + declare count={calign primary angle}{-35}, + declare count={calign secondary angle}{35}, + calign child/.style={calign primary child={#1}}, + calign angle/.style={calign primary angle={-#1},calign secondary angle={#1}}, + declare toks={calign xshift}{0pt}, + % calign with xshift/.style={for parent/.wrap pgfmath arg={calign xshift=##1}{n}}, + % calign with xshift/.style={calign with current, for parent={calign xshift=#1}}, + declare toks={tier}{}, + declare toks={fit}{tight}, + declare boolean={ignore}{0}, + declare boolean={ignore edge}{0}, + no edge/.style={edge'={},ignore edge}, + declare keylist={edge}{draw}, + declare toks={edge path}{% + \noexpand\path[\forestoption{edge}]% + (\forestOve{\forestove{@parent}}{name}.parent anchor)--(\forestove{name}.child anchor) + % = + % (!u.parent anchor)--(.child anchor)\forestoption{edge label}; + \forestoption{edge label};% + }, + edge path'/.style={ + edge path={% + \noexpand\path[\forestoption{edge}]% + #1% + \forestoption{edge label}; + } + }, + declare toks={edge label}{}, + declare boolean={phantom}{0}, + baseline/.style={alias={forest@baseline@node}}, + declare readonly count={id}{0}, + declare readonly count={n}{0}, + declare readonly count={n'}{0}, + declare readonly count={n children}{-1}, + declare readonly count={level}{-1}, + declare dimen=x{0pt}, + declare dimen=y{0pt}, + declare dimen={s}{0pt}, + declare dimen={l}{6ex}, % just in case: should be set by the calibration + declare dimen={s sep}{0.6666em}, + declare dimen={l sep}{1ex}, % just in case: calibration! + declare keylist={node options}{anchor=base}, + declare toks={tikz}{}, + afterthought/.style={tikz+={#1}}, + label/.style={tikz+={\path[late options={% + name=\forestoption{name},label={#1}}];}}, + pin/.style={tikz+={\path[late options={% + name=\forestoption{name},pin={#1}}];}}, + declare toks={content format}{\forestoption{content}}, + plain content/.style={content format={\forestoption{content}}}, + math content/.style={content format={\noexpand\ensuremath{\forestoption{content}}}}, + declare toks={node format}{% + \noexpand\node + (\forestoption{name})% + [\forestoption{node options}]% + {\foresteoption{content format}};% + }, + node format'/.style={ + node format={\noexpand\node(\forestoption{name})#1;} + }, + tabular@environment/.style={content format={% + \noexpand\begin{tabular}[\forestoption{base}]{\forestoption{align}}% + \forestoption{content}% + \noexpand\end{tabular}% + }}, + declare toks={align}{}, + TeX={% + \forest@copycommandkey{/forest/align}{/forest/align'}% + %\pgfkeysgetvalue{/forest/align/.@cmd}\forest@temp + %\pgfkeyslet{/forest/align'/.@cmd}\forest@temp + }, + align/.is choice, + align/.unknown/.code={% + \edef\forest@marshal{% + \noexpand\pgfkeysalso{% + align'={\pgfkeyscurrentname},% + tabular@environment + }% + }\forest@marshal + }, + align/center/.style={align'={@{}c@{}},tabular@environment}, + align/left/.style={align'={@{}l@{}},tabular@environment}, + align/right/.style={align'={@{}r@{}},tabular@environment}, + declare toks={base}{t}, + TeX={% + \forest@copycommandkey{/forest/base}{/forest/base'}% + %\pgfkeysgetvalue{/forest/base/.@cmd}\forest@temp + %\pgfkeyslet{/forest/base'/.@cmd}\forest@temp + }, + base/.is choice, + base/top/.style={base'=t}, + base/bottom/.style={base'=b}, + base/.unknown/.style={base'/.expand once=\pgfkeyscurrentname}, + unknown to/.store in=\forest@unknownto, + unknown to=node options, + unknown key error/.code={\PackageError{forest}{Unknown keyval: \detokenize{#1}}{}}, + content to/.store in=\forest@contentto, + content to=content, + .unknown/.code={% + \expandafter\pgfutil@in@\expandafter.\expandafter{\pgfkeyscurrentname}% + \ifpgfutil@in@ + \expandafter\forest@relatednode@option@setter\pgfkeyscurrentname=#1\forest@END + \else + \edef\forest@marshal{% + \noexpand\pgfkeysalso{\forest@unknownto={\pgfkeyscurrentname=\unexpanded{#1}}}% + }\forest@marshal + \fi + }, + get node boundary/.code={% + \forestoget{@boundary}\forest@node@boundary + \def#1{}% + \forest@extendpath#1\forest@node@boundary{\pgfpoint{\forestove{x}}{\forestove{y}}}% + }, + % get min l tree boundary/.code={% + % \forest@get@tree@boundary{negative}{\the\numexpr\forestove{grow}-90\relax}#1}, + % get max l tree boundary/.code={% + % \forest@get@tree@boundary{positive}{\the\numexpr\forestove{grow}-90\relax}#1}, + get min s tree boundary/.code={% + \forest@get@tree@boundary{negative}{\forestove{grow}}#1}, + get max s tree boundary/.code={% + \forest@get@tree@boundary{positive}{\forestove{grow}}#1}, + use as bounding box/.style={% + before drawing tree={ + tikz+/.expanded={% + \noexpand\pgfresetboundingbox + \noexpand\useasboundingbox + ($(.anchor)+(\forestoption{min x},\forestoption{min y})$) + rectangle + ($(.anchor)+(\forestoption{max x},\forestoption{max y})$) + ; + } + } + }, + use as bounding box'/.style={% + before drawing tree={ + tikz+/.expanded={% + \noexpand\pgfresetboundingbox + \noexpand\useasboundingbox + ($(.anchor)+(\forestoption{min x}+\pgfkeysvalueof{/pgf/outer xsep}/2+\pgfkeysvalueof{/pgf/inner xsep},\forestoption{min y}+\pgfkeysvalueof{/pgf/outer ysep}/2+\pgfkeysvalueof{/pgf/inner ysep})$) + rectangle + ($(.anchor)+(\forestoption{max x}-\pgfkeysvalueof{/pgf/outer xsep}/2-\pgfkeysvalueof{/pgf/inner xsep},\forestoption{max y}-\pgfkeysvalueof{/pgf/outer ysep}/2-\pgfkeysvalueof{/pgf/inner ysep})$) + ; + } + } + }, +}% +\def\forest@iftikzkey#1#2#3{% #1 = key name, #2 = true code, #3 = false code + \forest@temptrue + \pgfkeysifdefined{/tikz/\pgfkeyscurrentname}{}{% + \pgfkeysifdefined{/tikz/\pgfkeyscurrentname/.@cmd}{}{% + \pgfkeysifdefined{/pgf/\pgfkeyscurrentname}{}{% + \pgfkeysifdefined{/pgf/\pgfkeyscurrentname/.@cmd}{}{% + \forest@tempfalse + }}}}% + \ifforest@temp\@escapeif{#2}\else\@escapeif{#3}\fi +} +\def\forest@ifoptionortikzkey#1#2#3{% #1 = key name, #2 = true code, #3 = false code + \forest@temptrue + \pgfkeysifdefined{/forest/\pgfkeyscurrentname}{}{% + \pgfkeysifdefined{/forest/\pgfkeyscurrentname/.@cmd}{}{% + \forest@iftikzkey{#1}{}{}% + }}% + \ifforest@temp\@escapeif{#2}\else\@escapeif{#3}\fi +} +\def\forest@get@tree@boundary#1#2#3{%#1=pos/neg,#2=grow,#3=receiving cs + \def#3{}% + \forest@node@getedge{#1}{#2}\forest@temp@boundary + \forest@extendpath#3\forest@temp@boundary{\pgfpoint{\forestove{x}}{\forestove{y}}}% +} +\def\forest@setter@node{\forest@cn}% +\def\forest@relatednode@option@compat@ignoreinvalidsteps#1{#1} +\def\forest@relatednode@option@setter#1.#2=#3\forest@END{% + \forest@forthis{% + \forest@relatednode@option@compat@ignoreinvalidsteps{% + \forest@nameandgo{#1}% + \let\forest@setter@node\forest@cn + }% + }% + \ifnum\forest@setter@node=0 + \else + \forestset{#2={#3}}% + \fi + \def\forest@setter@node{\forest@cn}% +}% +\def\forest@split#1#2#3#4{% #1=list (assuming that the list is nonempty and finishes with the separator), #2 = sep, #3 = cs receiving first, #4 = cs receiving last + \def\forest@split@@##1#2##2\forest@split@@##3##4{\def##3{##1}\def##4{##2}}% + \forest@split@@#1\forest@split@@{#3}{#4}} +\forestset{ + for tree'/.style 2 args={#1,for children={for tree'={#1}{#2}},#2}, + if/.code n args={3}{% + \pgfmathparse{#1}% + \ifnum\pgfmathresult=0 + \@escapeif{\pgfkeysalso{#3}}% + \else + \@escapeif{\pgfkeysalso{#2}}% + \fi + }, + if nodewalk valid/.code n args={3}{% + \edef\forest@marshal{% + \unexpanded{\forest@forthis{% + \forest@nodewalk{% + on invalid={fake}{#1}, + TeX={\global\let\forest@global@temp\forest@cn} + }{}% + }% + \def\forest@cn}{\forest@cn}\unexpanded{% + \ifnum\forest@global@temp=0 + \@escapeif{\pgfkeysalso{#3}}% + \else + \@escapeif{\pgfkeysalso{#2}}% + \fi}% + }\forest@marshal + }, + if nodewalk empty/.code n args={3}{% + \forest@forthis{% + \forest@nodewalk{% + on invalid={fake}{#1}, + TeX={\global\let\forest@global@temp\forest@nodewalk@n}, + }{}% + }% + \ifnum\forest@global@temp=0 + \@escapeif{\pgfkeysalso{#2}}% + \else + \@escapeif{\pgfkeysalso{#3}}% + \fi + }, + where/.style n args={3}{for tree={if={#1}{#2}{#3}}}, + where nodewalk valid/.style n args={3}{for tree={if nodewalk valid={#1}{#2}{#3}}}, + where nodewalk empty/.style n args={3}{for tree={if nodewalk empty={#1}{#2}{#3}}}, + repeat/.code 2 args={% + \pgfmathtruncatemacro\forest@temp{#1}% + \expandafter\forest@repeatkey\expandafter{\forest@temp}{#2}% + }, + until/.code 2 args={% + \ifstrempty{#1}{% + \forest@untilkey{\ifnum\forest@cn=0\else\relax\forestloopbreak\fi}{on invalid={fake}{#2}}% + }{% + \forest@untilkey{\pgfmathifthenelse{#1}{"\noexpand\forestloopbreak"}{""}\pgfmathresult}{#2}% + }% + }, + while/.code 2 args={% + \ifstrempty{#1}{% + \forest@untilkey{\ifnum\forest@cn=0\relax\forestloopbreak\fi}{on invalid={fake}{#2}}% + }{% + \forest@untilkey{\pgfmathifthenelse{not(#1)}{"\noexpand\forestloopbreak"}{""}\pgfmathresult}{#2}% + }% + }, + do until/.code 2 args={% + \ifstrempty{#1}{% + \forest@dountilkey{\ifnum\forest@cn=0\else\relax\forestloopbreak\fi}{on invalid={fake}{#2}}% + }{% + \forest@dountilkey{\pgfmathifthenelse{#1}{"\noexpand\forestloopbreak"}{""}\pgfmathresult}{#2}% + }% + }, + do while/.code 2 args={% + \ifstrempty{#1}{% + \forest@dountilkey{\ifnum\forest@cn=0\relax\forestloopbreak\fi}{on invalid={fake}{#2}}% + }{% + \forest@dountilkey{\pgfmathifthenelse{not(#1)}{"\noexpand\forestloopbreak"}{""}\pgfmathresult}{#2}% + }% + }, + until nodewalk valid/.code 2 args={% + \forest@untilkey{\forest@forthis{% + \forest@nodewalk{on invalid={fake}{#1},TeX={\ifnum\forest@cn=0\relax\else\forestloopbreak\fi}}{}}}{#2}% + }, + while nodewalk valid/.code 2 args={% + \forest@untilkey{\forest@forthis{% + \forest@nodewalk{on invalid={fake}{#1},TeX={\ifnum\forest@cn=0\relax\forestloopbreak\fi}}{}}}{#2}% + }, + do until nodewalk valid/.code 2 args={% + \forest@dountilkey{\forest@forthis{% + \forest@nodewalk{on invalid={fake}{#1},TeX={\ifnum\forest@cn=0\relax\else\forestloopbreak\fi}}{}}}{#2}% + }, + do while nodewalk valid/.code 2 args={% + \forest@dountilkey{\forest@forthis{% + \forest@nodewalk{on invalid={fake}{#1},TeX={\ifnum\forest@cn=0\relax\forestloopbreak\fi}}{}}}{#2}% + }, + until nodewalk empty/.code 2 args={% + \forest@untilkey{\forest@forthis{% + \forest@nodewalk{on invalid={fake}{#1},TeX={\ifnum\forest@nodewalk@n=0\relax\forestloopbreak\fi}}{}}}{#2}% + }, + while nodewalk empty/.code 2 args={% + \forest@untilkey{\forest@forthis{% + \forest@nodewalk{on invalid={fake}{#1},TeX={\ifnum\forest@nodewalk@n=0\relax\else\forestloopbreak\fi}}{}}}{#2}% + }, + do until nodewalk empty/.code 2 args={% + \forest@dountilkey{\forest@forthis{% + \forest@nodewalk{on invalid={fake}{#1},TeX={\ifnum\forest@nodewalk@n=0\relax\forestloopbreak\fi}}{}}}{#2}% + }, + do while nodewalk empty/.code 2 args={% + \forest@dountilkey{\forest@forthis{% + \forest@nodewalk{on invalid={fake}{#1},TeX={\ifnum\forest@nodewalk@n=0\relax\else\forestloopbreak\fi}}{}}}{#2}% + }, + break/.code={\forestloopBreak{#1}}, + break/.default=0, +} +\def\forest@repeatkey#1#2{% + \safeRKloop + \ifnum\safeRKloopn>#1\relax + \csuse{safeRKbreak@\the\safeRKloop@depth true}% + \fi + \expandafter\unless\csname ifsafeRKbreak@\the\safeRKloop@depth\endcsname + \pgfkeysalso{#2}% + \safeRKrepeat +} +\def\forest@untilkey#1#2{% #1 = condition, #2 = keys + \safeRKloop + #1% + \expandafter\unless\csname ifsafeRKbreak@\the\safeRKloop@depth\endcsname + \pgfkeysalso{#2}% + \safeRKrepeat +} +\def\forest@dountilkey#1#2{% #1 = condition, #2 = keys + \safeRKloop + \pgfkeysalso{#2}% + #1% + \expandafter\unless\csname ifsafeRKbreak@\the\safeRKloop@depth\endcsname + \safeRKrepeat +} +\def\forestloopbreak{% + \csname safeRKbreak@\the\safeRKloop@depth true\endcsname +} +\def\forestloopBreak#1{% + \csname safeRKbreak@\number\numexpr\the\safeRKloop@depth-#1\relax true\endcsname +} +\def\forestloopcount{% + \csname safeRKloopn@\number\numexpr\the\safeRKloop@depth\endcsname +} +\def\forestloopCount#1{% + \csname safeRKloopn@\number\numexpr\the\safeRKloop@depth-#1\endcsname +} +\pgfmathdeclarefunction{forestloopcount}{1}{% + \edef\pgfmathresult{\forestloopCount{\ifstrempty{#1}{0}{#1}}}% +} +\forest@copycommandkey{/forest/repeat}{/forest/nodewalk/repeat} +\forest@copycommandkey{/forest/while}{/forest/nodewalk/while} +\forest@copycommandkey{/forest/do while}{/forest/nodewalk/do while} +\forest@copycommandkey{/forest/until}{/forest/nodewalk/until} +\forest@copycommandkey{/forest/do until}{/forest/nodewalk/do until} +\forest@copycommandkey{/forest/if}{/forest/nodewalk/if} +\forest@copycommandkey{/forest/if nodewalk valid}{/forest/nodewalk/if nodewalk valid} +\forestset{ + aggregate postparse/.is choice, + aggregate postparse/int/.code={% + \let\forest@aggregate@pgfmathpostparse\forest@aggregate@pgfmathpostparse@toint}, + aggregate postparse/none/.code={% + \let\forest@aggregate@pgfmathpostparse\relax}, + aggregate postparse/print/.code={% + \let\forest@aggregate@pgfmathpostparse\forest@aggregate@pgfmathpostparse@print}, + aggregate postparse/macro/.code={% + \let\forest@aggregate@pgfmathpostparse\forest@aggregate@pgfmathpostparse@usemacro}, + aggregate postparse macro/.store in=\forest@aggregate@pgfmathpostparse@macro, +} +\def\forest@aggregate@pgfmathpostparse@print{% + \pgfmathprintnumberto{\pgfmathresult}{\pgfmathresult}% +} +\def\forest@aggregate@pgfmathpostparse@toint{% + \expandafter\forest@split\expandafter{\pgfmathresult.}{.}\pgfmathresult\forest@temp +} +\def\forest@aggregate@pgfmathpostparse@usemacro{% + \forest@aggregate@pgfmathpostparse@macro +} +\let\forest@aggregate@pgfmathpostparse\relax +\pgfkeys{ + /handlers/.aggregate/.code n args=4{% + % #1 = start value + % #2 = pgfmath expression for every step + % #3 = pgfmath expression for after walk + % #4 = nodewalk + \edef\forest@marshal{% + \unexpanded{\forest@aggregate{#1}{#2}{#3}{#4}}{\pgfkeyscurrentpath}% + }\forest@marshal + }, + /handlers/.sum/.style 2 args={/handlers/.aggregate={0}{(##1)+(#1)}{##1}{#2}}, + /handlers/.count/.style={/handlers/.aggregate={0}{1+(##1)}{##1}{#1}}, + /handlers/.average/.style 2 args={/handlers/.aggregate={0}{(##1)+(#1)}{##1/\forestregister{aggregate n}}{#2}}, + /handlers/.product/.style 2 args={/handlers/.aggregate={1}{(#1)*(##1)}{##1}{#2}}, + /handlers/.min/.style 2 args={/handlers/.aggregate={}{min(#1,##1)}{##1}{#2}}, + /handlers/.max/.style 2 args={/handlers/.aggregate={}{max(#1,##1)}{##1}{#2}}, + /forest/declare count register={aggregate n}, +} + +\def\forest@aggregate#1#2#3#4#5{% + % #5 = current path + \def\forest@aggregate@result{#1}% + \forest@forthis{% + \forestrset{aggregate n}{0}% + \forest@nodewalk{#4}{% + TeX={% + \forestreset{aggregate n}{\number\numexpr\forestrv{aggregate n}+1}% + \def\forest@marshal##1{\pgfmathparse{#2}}% + \expandafter\forest@marshal\expandafter{\forest@aggregate@result}% + \let\forest@aggregate@result\pgfmathresult + }% + }{}% + }% + \def\forest@marshal##1{\pgfmathparse{#3}}% + \expandafter\forest@marshal\expandafter{\forest@aggregate@result}% + \let\forest@aggregate@result\pgfmathresult + \let\forest@temp@pgfmathpostparse\pgfmathpostparse + \let\pgfmathpostparse\forest@aggregate@pgfmathpostparse + \pgfmathqparse{\forest@aggregate@result pt}% + \let\pgfmathpostparse\forest@temp@pgfmathpostparse + \let\forest@aggregate@result\pgfmathresult + \pgfkeysalso{#5/.expand once=\forest@aggregate@result}% +} +\pgfmathdeclarefunction{strequal}{2}{% + \ifstrequal{#1}{#2}{\def\pgfmathresult{1}}{\def\pgfmathresult{0}}% +} +\pgfmathdeclarefunction{instr}{2}{% + \pgfutil@in@{#1}{#2}% + \ifpgfutil@in@\def\pgfmathresult{1}\else\def\pgfmathresult{0}\fi +} +\pgfmathdeclarefunction{strcat}{...}{% + \edef\pgfmathresult{\forest@strip@braces{#1}}% +} +\pgfmathdeclarefunction{min_s}{2}{% #1 = node, #2 = context node (for growth rotation) + \forest@forthis{% + \forest@nameandgo{#1}% + \forest@compute@minmax@ls{#2}% + \pgfmathsetmacro\pgfmathresult{\forestove{min@s}}% + }% +} +\pgfmathdeclarefunction{min_l}{2}{% #1 = node, #2 = context node (for growth rotation) + \forest@forthis{% + \forest@nameandgo{#1}% + \forest@compute@minmax@ls{#2}% + \pgfmathsetmacro\pgfmathresult{\forestove{min@l}}% + }% +} +\pgfmathdeclarefunction{max_s}{2}{% #1 = node, #2 = context node (for growth rotation) + \forest@forthis{% + \forest@nameandgo{#1}% + \forest@compute@minmax@ls{#2}% + \pgfmathsetmacro\pgfmathresult{\forestove{max@s}}% + }% +} +\pgfmathdeclarefunction{max_l}{2}{% #1 = node, #2 = context node (for growth rotation) + \forest@forthis{% + \forest@nameandgo{#1}% + \forest@compute@minmax@ls{#2}% + \pgfmathsetmacro\pgfmathresult{\forestove{max@l}}% + }% +} +\def\forest@compute@minmax@ls#1{% #1 = nodewalk; in the context of which node? + {% + \pgftransformreset + \forest@forthis{% + \forest@nameandgo{#1}% + \pgftransformrotate{-\forestove{grow}}% + }% + \forestoget{min x}\forest@temp@minx + \forestoget{min y}\forest@temp@miny + \forestoget{max x}\forest@temp@maxx + \forestoget{max y}\forest@temp@maxy + \pgfpointtransformed{\pgfqpoint{\forest@temp@minx}{\forest@temp@miny}}% + \forestoeset{min@l}{\the\pgf@x}% + \forestoeset{min@s}{\the\pgf@y}% + \forestoeset{max@l}{\the\pgf@x}% + \forestoeset{max@s}{\the\pgf@y}% + \pgfpointtransformed{\pgfqpoint{\forest@temp@minx}{\forest@temp@maxy}}% + \ifdim\pgf@x<\forestove{min@l}\relax\forestoeset{min@l}{\the\pgf@x}\fi + \ifdim\pgf@y<\forestove{min@s}\relax\forestoeset{min@s}{\the\pgf@y}\fi + \ifdim\pgf@x>\forestove{max@l}\relax\forestoeset{max@l}{\the\pgf@x}\fi + \ifdim\pgf@y>\forestove{max@s}\relax\forestoeset{max@s}{\the\pgf@y}\fi + \pgfpointtransformed{\pgfqpoint{\forest@temp@maxx}{\forest@temp@miny}}% + \ifdim\pgf@x<\forestove{min@l}\relax\forestoeset{min@l}{\the\pgf@x}\fi + \ifdim\pgf@y<\forestove{min@s}\relax\forestoeset{min@s}{\the\pgf@y}\fi + \ifdim\pgf@x>\forestove{max@l}\relax\forestoeset{max@l}{\the\pgf@x}\fi + \ifdim\pgf@y>\forestove{max@s}\relax\forestoeset{max@s}{\the\pgf@y}\fi + \pgfpointtransformed{\pgfqpoint{\forest@temp@maxx}{\forest@temp@maxy}}% + \ifdim\pgf@x<\forestove{min@l}\relax\forestoeset{min@l}{\the\pgf@x}\fi + \ifdim\pgf@y<\forestove{min@s}\relax\forestoeset{min@s}{\the\pgf@y}\fi + \ifdim\pgf@x>\forestove{max@l}\relax\forestoeset{max@l}{\the\pgf@x}\fi + \ifdim\pgf@y>\forestove{max@s}\relax\forestoeset{max@s}{\the\pgf@y}\fi + % smuggle out + \edef\forest@marshal{% + \noexpand\forestoeset{min@l}{\forestove{min@l}}% + \noexpand\forestoeset{min@s}{\forestove{min@s}}% + \noexpand\forestoeset{max@l}{\forestove{max@l}}% + \noexpand\forestoeset{max@s}{\forestove{max@s}}% + }\expandafter + }\forest@marshal +} +\def\forest@pgfmathhelper@attribute@toks#1#2{% + \forest@forthis{% + \forest@nameandgo{#1}% + \ifnum\forest@cn=0 + \def\pgfmathresult{}% + \else + \forestoget{#2}\pgfmathresult + \fi + }% +} +\def\forest@pgfmathhelper@attribute@dimen#1#2{% + \forest@forthis{% + \forest@nameandgo{#1}% + \ifnum\forest@cn=0 + \def\pgfmathresult{0pt}% + \else + \forestoget{#2}\forest@temp + \pgfmathparse{+\forest@temp}% + \fi + }% +} +\def\forest@pgfmathhelper@attribute@count#1#2{% + \forest@forthis{% + \forest@nameandgo{#1}% + \ifnum\forest@cn=0 + \def\pgfmathresult{0}% + \else + \forestoget{#2}\forest@temp + \pgfmathtruncatemacro\pgfmathresult{\forest@temp}% + \fi + }% +} +\pgfmathdeclarefunction*{id}{1}{% + \forest@forthis{% + \forest@nameandgo{#1}% + \let\pgfmathresult\forest@cn + }% +} +\def\forest@nodewalk@n{0} +\def\forest@nodewalk@historyback{0,} +\def\forest@nodewalk@historyforward{0,} +\def\forest@nodewalk@origin{0} +\def\forest@nodewalk@config@everystep@independent@before#1{% #1 = every step keylist + \forestrset{every step}{#1}% +} +\def\forest@nodewalk@config@everystep@independent@after{% + \noexpand\forestrset{every step}{\forestrv{every step}}% +} +\def\forest@nodewalk@config@history@independent@before{% + \def\forest@nodewalk@n{0}% + \edef\forest@nodewalk@origin{\forest@cn}% + \def\forest@nodewalk@historyback{0,}% + \def\forest@nodewalk@historyforward{0,}% +} +\def\forest@nodewalk@config@history@independent@after{% + \edef\noexpand\forest@nodewalk@n{\expandonce{\forest@nodewalk@n}}% + \edef\noexpand\forest@nodewalk@origin{\expandonce{\forest@nodewalk@origin}}% + \edef\noexpand\forest@nodewalk@historyback{\expandonce{\forest@nodewalk@historyback}}% + \edef\noexpand\forest@nodewalk@historyforward{\expandonce{\forest@nodewalk@historyforward}}% +} +\def\forest@nodewalk@config@everystep@shared@before#1{}% #1 = every step keylist +\def\forest@nodewalk@config@everystep@shared@after{} +\def\forest@nodewalk@config@history@shared@before{} +\def\forest@nodewalk@config@history@shared@after{} +\def\forest@nodewalk@config@everystep@inherited@before#1{}% #1 = every step keylist +\let\forest@nodewalk@config@everystep@inherited@after\forest@nodewalk@config@everystep@independent@after +\def\forest@nodewalk@config@history@inherited@before{} +\let\forest@nodewalk@config@history@inherited@after\forest@nodewalk@config@history@independent@after +\def\forest@nodewalk#1#2{% #1 = nodewalk, #2 = every step keylist + \def\forest@nodewalk@config@everystep@method{independent}% + \def\forest@nodewalk@config@history@method{independent}% + \def\forest@nodewalk@config@oninvalid{inherited}% + \forest@saveandrestoremacro\forest@nodewalk@oninvalid{% + \forest@Nodewalk{#1}{#2}% + }% +} +\def\forest@Nodewalk#1#2{% #1 = nodewalk, #2 = every step keylist + \edef\forest@marshal{% + \noexpand\pgfqkeys{/forest/nodewalk}{\unexpanded{#1}}% + \csname forest@nodewalk@config@everystep@\forest@nodewalk@config@everystep@method @after\endcsname + \csname forest@nodewalk@config@history@\forest@nodewalk@config@history@method @after\endcsname + }% + \csname forest@nodewalk@config@everystep@\forest@nodewalk@config@everystep@method @before\endcsname{#2}% + \csname forest@nodewalk@config@history@\forest@nodewalk@config@history@method @before\endcsname + \forest@nodewalk@fakefalse + \forest@marshal +} +\pgfmathdeclarefunction{valid}{1}{% + \forest@forthis{% + \forest@nameandgo{#1}% + \edef\pgfmathresult{\ifnum\forest@cn=0 0\else 1\fi}% + }% +} +\pgfmathdeclarefunction{invalid}{1}{% + \forest@forthis{% + \forest@nameandgo{#1}% + \edef\pgfmathresult{\ifnum\forest@cn=0 1\else 0\fi}% + }% +} +\newif\ifforest@nodewalk@fake +\def\forest@nodewalk@oninvalid{error} +\def\forest@nodewalk@makestep{% + \ifnum\forest@cn=0 + \csname forest@nodewalk@makestep@oninvalid@\forest@nodewalk@config@oninvalid\endcsname + \else + \forest@nodewalk@makestep@ + \fi +} +\def\forest@nodewalk@makestep@oninvalid@step{\forest@nodewalk@makestep@} +\def\forest@nodewalk@makestep@oninvalid@error{\PackageError{forest}{nodewalk stepped to the invalid node\MessageBreak nodewalk stack: "\forest@nodewalk@currentstepname"}{}}% +\let\forest@nodewalk@makestep@oninvalid@fake\relax +\def\forest@nodewalk@makestep@oninvalid@compatfake{% + \forest@deprecated{last step in stack "\forest@nodewalk@currentstepname", which stepped on an invalid node; enabled by "compat=ignoreinvalidsteps". Use "on invalid={fake}{...}" or "for Nodewalk={on invalid=fake}{...}{...}" instead.}% +}% +\def\forest@nodewalk@makestep@oninvalid@inherited{\csname forest@nodewalk@makestep@oninvalid@\forest@nodewalk@oninvalid\endcsname} +\def\forest@nodewalk@makestep@{% + \ifforest@nodewalk@fake + \else + \edef\forest@nodewalk@n{\number\numexpr\forest@nodewalk@n+1}% + \epreto\forest@nodewalk@historyback{\forest@cn,}% + \def\forest@nodewalk@historyforward{0,}% + \ifforestdebugnodewalks\forest@nodewalk@makestep@debug\fi + \forest@process@keylist@register{every step}% + \fi +} +\def\forest@nodewalk@makestep@debug{% + \edef\forest@marshal{% + \noexpand\typeout{\ifforest@nodewalk@fake fake \fi "\forest@nodewalk@currentstepname" step to node id=\forest@cn, content=\forestoption{content}}% + }\forest@marshal +}% +\def\forest@handlers@savecurrentpath{% + \edef\pgfkeyscurrentkey{\pgfkeyscurrentpath}% + \let\forest@currentkey\pgfkeyscurrentkey + \pgfkeys@split@path + \edef\forest@currentpath{\pgfkeyscurrentpath}% + \let\forest@currentname\pgfkeyscurrentname +} +\pgfkeys{/handlers/save current path/.code={\forest@handlers@savecurrentpath}} +\newif\ifforest@nodewalkstephandler@style +\newif\ifforest@nodewalkstephandler@autostep +\newif\ifforest@nodewalkstephandler@stripfakesteps +\newif\ifforest@nodewalkstephandler@muststartatvalidnode +\newif\ifforest@nodewalkstephandler@makefor +\let\forest@nodewalkstephandler@styletrueorfalse\forest@nodewalkstephandler@stylefalse +\def\forest@nodewalk@currentstepname{} +\forestset{ + /forest/define@step/style/.is if=forest@nodewalkstephandler@style, + /forest/define@step/autostep/.is if=forest@nodewalkstephandler@autostep, + % the following is useful because some macros use grouping (by \forest@forthis or similar) and therefore, after making the last step, revert \forest@cn to the original value, essentially making a fake step + /forest/define@step/strip fake steps/.is if=forest@nodewalkstephandler@stripfakesteps, + % this can never happen with autosteps ... + /forest/define@step/autostep/.append code={% + \ifforest@nodewalkstephandler@autostep + \forest@nodewalkstephandler@stripfakestepsfalse + \fi + }, + /forest/define@step/must start at valid node/.is if=forest@nodewalkstephandler@muststartatvalidnode, + /forest/define@step/n args/.store in=\forest@nodewalkstephandler@nargs, + /forest/define@step/make for/.is if=forest@nodewalkstephandler@makefor, + /forest/define@step/@bare/.style={strip fake steps=false,must start at valid node=false,make for=false}, + define long step/.code n args=3{% + \forest@nodewalkstephandler@styletrueorfalse % true for end users; but in the package, most of steps are defined by .code + \forest@nodewalkstephandler@autostepfalse + \forest@nodewalkstephandler@stripfakestepstrue + \forest@nodewalkstephandler@muststartatvalidnodetrue % most steps can only start at a valid node + \forest@nodewalkstephandler@makefortrue % make for prefix? + \def\forest@nodewalkstephandler@nargs{0}% + \pgfqkeys{/forest/define@step}{#2}% + \forest@temp@toks{#3}% handler code + \ifforest@nodewalkstephandler@style + \expandafter\forest@temp@toks\expandafter{% + \expandafter\pgfkeysalso\expandafter{\the\forest@temp@toks}% + }% + \fi + \ifforest@nodewalkstephandler@autostep + \apptotoks\forest@temp@toks{\forest@nodewalk@makestep}% + \fi + \ifforest@nodewalkstephandler@stripfakesteps + \expandafter\forest@temp@toks\expandafter{\expandafter\forest@nodewalk@stripfakesteps\expandafter{\the\forest@temp@toks}}% + \fi + \ifforest@nodewalkstephandler@muststartatvalidnode + \edef\forest@marshal{% + \noexpand\forest@temp@toks{% + \unexpanded{% + \ifnum\forest@cn=0 + \csname forest@nodewalk@start@oninvalid@\forest@nodewalk@oninvalid\endcsname{#1}% + \else + }% + \noexpand\@escapeif{\the\forest@temp@toks}% + \noexpand\fi + }% + }\forest@marshal + \fi + \pretotoks\forest@temp@toks{\appto\forest@nodewalk@currentstepname{,#1}}% + \expandafter\forest@temp@toks\expandafter{\expandafter\forest@saveandrestoremacro\expandafter\forest@nodewalk@currentstepname\expandafter{\the\forest@temp@toks}}% + \ifforestdebugnodewalks + \epretotoks\forest@temp@toks{\noexpand\typeout{Starting step "#1" from id=\noexpand\forest@cn + \ifnum\forest@nodewalkstephandler@nargs>0 \space with args ####1\fi + \ifnum\forest@nodewalkstephandler@nargs>1 ,####2\fi + \ifnum\forest@nodewalkstephandler@nargs>2 ,####3\fi + \ifnum\forest@nodewalkstephandler@nargs>3 ,####4\fi + \ifnum\forest@nodewalkstephandler@nargs>4 ,####5\fi + \ifnum\forest@nodewalkstephandler@nargs>5 ,####6\fi + \ifnum\forest@nodewalkstephandler@nargs>6 ,####7\fi + \ifnum\forest@nodewalkstephandler@nargs>7 ,####8\fi + \ifnum\forest@nodewalkstephandler@nargs>8 ,####9\fi + }}% + \fi + \def\forest@temp{/forest/nodewalk/#1/.code}% + \ifnum\forest@nodewalkstephandler@nargs<2 + \eappto\forest@temp{=}% + \else\ifnum\forest@nodewalkstephandler@nargs=2 + \eappto\forest@temp{ 2 args=}% + \else + \eappto\forest@temp{ n args={\forest@nodewalkstephandler@nargs}}% + \fi\fi + \eappto\forest@temp{{\the\forest@temp@toks}}% + \expandafter\pgfkeysalso\expandafter{\forest@temp}% + \ifforest@nodewalkstephandler@makefor + \ifnum\forest@nodewalkstephandler@nargs=0 + \forestset{% + for #1/.code={\forest@forstepwrapper{#1}{##1}}, + }% + \else\ifnum\forest@nodewalkstephandler@nargs=1 + \forestset{% + for #1/.code 2 args={\forest@forstepwrapper{#1={##1}}{##2}}, + }% + \else + \forestset{% + for #1/.code n args/.expanded=% + {\number\numexpr\forest@nodewalkstephandler@nargs+1}% + {\noexpand\forest@forstepwrapper{#1\ifnum\forest@nodewalkstephandler@nargs>0=\fi\forest@util@nargs{####}{\number\numexpr\forest@nodewalkstephandler@nargs}{0}}{####\number\numexpr\forest@nodewalkstephandler@nargs+1}}, + }% + \fi\fi + \fi + }, +} +\pgfqkeys{/handlers}{ + .nodewalk style/.code={\forest@handlers@savecurrentpath\pgfkeysalso{% + \forest@currentpath/nodewalk/\forest@currentname/.style={#1}% + }}, +} +\def\forest@forstepwrapper#1#2{\forest@forthis{\forest@nodewalk{#1}{#2}}} +\def\forest@util@nargs#1#2#3{% #1 = prefix (#, ##, ...), #2 = n args, #3=start; returns {#start}{#start+1}...{#start+n} + \ifnum#2>0 {#1\number\numexpr#3+1}\fi + \ifnum#2>1 {#1\number\numexpr#3+2}\fi + \ifnum#2>2 {#1\number\numexpr#3+3}\fi + \ifnum#2>3 {#1\number\numexpr#3+4}\fi + \ifnum#2>4 {#1\number\numexpr#3+5}\fi + \ifnum#2>5 {#1\number\numexpr#3+6}\fi + \ifnum#2>6 {#1\number\numexpr#3+7}\fi + \ifnum#2>7 {#1\number\numexpr#3+8}\fi + \ifnum#2>8 {#1\number\numexpr#3+9}\fi +} +\def\forest@nodewalk@start@oninvalid@fake#1{} +\def\forest@nodewalk@start@oninvalid@real#1{} +\def\forest@nodewalk@start@oninvalid@error#1{\PackageError{forest}{nodewalk step "#1" cannot start at the invalid node}{}} +\forestset{ + define long step={current}{autostep}{}, + define long step={next}{autostep}{\edef\forest@cn{\forestove{@next}}}, + define long step={previous}{autostep}{\edef\forest@cn{\forestove{@previous}}}, + define long step={parent}{autostep}{\edef\forest@cn{\forestove{@parent}}}, + define long step={first}{autostep}{\edef\forest@cn{\forestove{@first}}}, + define long step={last}{autostep}{\edef\forest@cn{\forestove{@last}}}, + define long step={sibling}{autostep}{% + \edef\forest@cn{% + \ifnum\forestove{@previous}=0 + \forestove{@next}% + \else + \forestove{@previous}% + \fi + }% + }, + define long step={next node}{autostep}{\edef\forest@cn{\forest@node@linearnextid}}, + define long step={previous node}{autostep}{\edef\forest@cn{\forest@node@linearpreviousid}}, + define long step={first leaf}{autostep}{% + \safeloop + \edef\forest@cn{\forestove{@first}}% + \unless\ifnum\forestove{@first}=0 + \saferepeat + }, + define long step={first leaf'}{autostep}{% + \safeloop + \unless\ifnum\forestove{@first}=0 + \edef\forest@cn{\forestove{@first}}% + \saferepeat + }, + define long step={last leaf}{autostep}{% + \safeloop + \edef\forest@cn{\forestove{@last}}% + \unless\ifnum\forestove{@last}=0 + \saferepeat + }, + define long step={last leaf'}{autostep}{% + \safeloop + \unless\ifnum\forestove{@last}=0 + \edef\forest@cn{\forestove{@last}}% + \saferepeat + }, + define long step={next leaf}{style,strip fake steps=false}{group={do until={n_children()==0}{next node}}}, + define long step={previous leaf}{style,strip fake steps=false}{group={do until={n_children()==0}{previous node}}}, + define long step={next on tier}{autostep}{% + \def\forest@temp{#1}% + \ifx\forest@temp\pgfkeysnovalue@text + \forestoget{tier}\forest@nodewalk@giventier + \else + \def\forest@nodewalk@giventier{#1}% + \fi + \edef\forest@cn{\forest@node@linearnextnotdescendantid}% + \safeloop + \forestoget{tier}\forest@nodewalk@tier + \unless\ifx\forest@nodewalk@tier\forest@nodewalk@giventier + \edef\forest@cn{\forest@node@linearnextid}% + \saferepeat + }, + define long step={previous on tier}{autostep}{% + \def\forest@temp{#1}% + \ifx\forest@temp\pgfkeysnovalue@text + \forestoget{tier}\forest@nodewalk@giventier + \else + \def\forest@nodewalk@giventier{#1}% + \fi + \safeloop + \edef\forest@cn{\forest@node@linearpreviousid}% + \forestoget{tier}\forest@nodewalk@tier + \unless\ifx\forest@nodewalk@tier\forest@nodewalk@giventier + \saferepeat + }, + % + define long step={root}{autostep,must start at valid node=false}{% + \edef\forest@cn{\forest@node@rootid}}, + define long step={root'}{autostep,must start at valid node=false}{% + \forestOifdefined{\forest@root}{@parent}{\edef\forest@cn{\forest@root}}{\edef\forest@cn{0}}% + }, + define long step={origin}{autostep,must start at valid node=false}{\edef\forest@cn{\forest@nodewalk@origin}}, + % + define long step={n}{autostep,n args=1}{% + \pgfmathtruncatemacro\forest@temp@n{#1}% + \edef\forest@cn{\forest@node@nthchildid{\forest@temp@n}}% + }, + define long step={n}{autostep,make for=false,n args=1}{% + % Yes, twice. ;-) + % n=1 and n(ext) + \def\forest@nodewalk@temp{#1}% + \ifx\forest@nodewalk@temp\pgfkeysnovalue@text + \edef\forest@cn{\forestove{@next}}% + \else + \pgfmathtruncatemacro\forest@temp@n{#1}% + \edef\forest@cn{\forest@node@nthchildid{\forest@temp@n}}% + \fi + }, + define long step={n'}{autostep,n args=1}{% + \pgfmathtruncatemacro\forest@temp@n{#1}% + \edef\forest@cn{\forest@node@nbarthchildid{\forest@temp@n}}% + }, + define long step={to tier}{autostep,n args=1}{% + \def\forest@nodewalk@giventier{#1}% + \safeloop + \forestoget{tier}\forest@nodewalk@tier + \unless\ifx\forest@nodewalk@tier\forest@nodewalk@giventier + \forestoget{@parent}\forest@cn + \saferepeat + }, + % + define long step={name}{autostep,n args=1,must start at valid node=false}{% + \edef\forest@cn{% + \forest@node@Ifnamedefined{#1}{\forest@node@Nametoid{#1}}{0}% + }% + }, + define long step={id}{autostep,n args=1,must start at valid node=false}{% + \forestOifdefined{#1}{@parent}{\edef\forest@cn{#1}}{\edef\forest@cn{0}}% + }, + define long step={Nodewalk}{n args=3,@bare}{% #1 = config, #2 = nodewalk + \def\forest@nodewalk@config@everystep@method{independent}% + \def\forest@nodewalk@config@history@method{shared}% + \def\forest@nodewalk@config@oninvalid{inherited}% + \forest@saveandrestoremacro\forest@nodewalk@oninvalid{% + \pgfqkeys{/forest/nodewalk@config}{#1}% + \forest@Nodewalk{#2}{#3}% + }% + }, + define long step={nodewalk}{n args=2,@bare}{% #1 = nodewalk, #2 = every step + \forest@nodewalk{#1}{#2}% + }, + define long step={nodewalk'}{n args=1,@bare}{% #1 = nodewalk, #2 = every step + \def\forest@nodewalk@config@everystep@method{inherited}% + \def\forest@nodewalk@config@history@method{independent}% + \def\forest@nodewalk@config@oninvalid{inherited}% + \forest@saveandrestoremacro\forest@nodewalk@oninvalid{% + \forest@Nodewalk{#1}{}% + }% + }, + % these must be defined explicitely, as prefix "for" normally introduces the every-step keylist + for nodewalk/.code 2 args={% + \forest@forthis{\forest@nodewalk{#1}{#2}}}, + for nodewalk'/.code={% + \def\forest@nodewalk@config@everystep@method{inherited}% + \def\forest@nodewalk@config@history@method{independent}% + \def\forest@nodewalk@config@oninvalid{inherited}% + \forest@saveandrestoremacro\forest@nodewalk@oninvalid{% + \forest@forthis{\forest@Nodewalk{#1}{}}% + }% + }, + for Nodewalk/.code n args=3{% #1 = config, #2 = nodewalk, #3 = every-step + \def\forest@nodewalk@config@everystep@method{inherited}% + \def\forest@nodewalk@config@history@method{independent}% + \def\forest@nodewalk@config@oninvalid{inherited}% + \forest@saveandrestoremacro\forest@nodewalk@oninvalid{% + \pgfqkeys{/forest/nodewalk@config}{#1}% + \forest@forthis{\forest@Nodewalk{#2}{#3}}% + }% + }, + copy command key={/forest/for nodewalk}{/forest/nodewalk/for nodewalk}, + copy command key={/forest/for nodewalk'}{/forest/nodewalk/for nodewalk'}, + copy command key={/forest/for Nodewalk}{/forest/nodewalk/for Nodewalk}, + declare keylist register=every step, + every step'={}, + %%% begin nodewalk config + nodewalk@config/.cd, + every@step/.is choice, + every@step/independent/.code={}, + every@step/inherited/.code={}, + every@step/shared/.code={}, + every step/.store in=\forest@nodewalk@config@everystep@method, + every step/.prefix style={every@step=#1}, + @history/.is choice, + @history/independent/.code={}, + @history/inherited/.code={}, + @history/shared/.code={}, + history/.store in=\forest@nodewalk@config@history@method, + history/.prefix style={@history=#1}, + on@invalid/.is choice, + on@invalid/error/.code={}, + on@invalid/fake/.code={}, + on@invalid/step/.code={}, + on@invalid/inherited/.code={}, + on invalid/.store in=\forest@nodewalk@config@oninvalid, + on invalid/.prefix style={on@invalid=#1}, + %%% end nodewalk config +} +\forestset{ + declare toks register=branch@temp@toks, + branch@temp@toks={}, + declare keylist register=branched@nodewalk, + branched@nodewalk={}, + define long step={branch}{n args=1,@bare,style}{@branch={#1}{branch@build@realstep,branch@build@fakestep}}, + define long step={branch'}{n args=1,@bare,style}{@branch={#1}{branch@build@realstep}}, + @branch/.style 2 args={% + save and restore register={branched@nodewalk}{ + branch@temp@toks={}, + split/.process args={r}{#1}{,}{#2}, + branch@temp@style/.style/.register=branch@temp@toks, + branch@temp@style, + branch@temp@style/.style/.register=branched@nodewalk, + branch@temp@style, + } + }, + nodewalk/branch@build@realstep/.style={% #1 = nodewalk for this branch + branch@temp@toks/.expanded={for nodewalk={\unexpanded{#1}}{ + branched@nodewalk+/.expanded={id=\noexpand\forestoption{id}}, + \forestregister{branch@temp@toks}}}, + }, + nodewalk/branch@build@fakestep/.style={% #1 = nodewalk for this branch + branch@temp@toks/.expanded={for nodewalk={\unexpanded{#1}}{ + \forestregister{branch@temp@toks}}}, + }, + define long step={group}{autostep}{\forest@go{#1}}, + nodewalk/fake/.code={% + \forest@saveandrestoreifcs{forest@nodewalk@fake}{% + \forest@nodewalk@faketrue + \pgfkeysalso{#1}% + }% + }, + nodewalk/real/.code={% + \forest@saveandrestoreifcs{forest@nodewalk@fake}{% + \forest@nodewalk@fakefalse + \pgfkeysalso{#1}% + }% + }, + declare keylist register=filtered@nodewalk, + filtered@nodewalk={}, + define long step={filter}{n args=2,@bare,style}{% #1 = nodewalk, #2 = condition + save and restore register={filtered@nodewalk}{ + filtered@nodewalk'={}, + Nodewalk=% + {history=inherited}% + {#1}% + {if={#2}{filtered@nodewalk+/.expanded={id=\forestoption{id}}}{}}, + filtered@nodewalk@style/.style/.register=filtered@nodewalk, + filtered@nodewalk@style + } + }, + on@invalid/.is choice, + on@invalid/error/.code={}, + on@invalid/fake/.code={}, + on@invalid/step/.code={}, + on invalid/.code 2 args={% + \pgfkeysalso{/forest/on@invalid={#1}}% + \forest@saveandrestoremacro\forest@nodewalk@oninvalid{% + \def\forest@nodewalk@oninvalid{#1}% + \pgfkeysalso{#2}% + }% + }, + define long step={strip fake steps}{n args=1,@bare}{% + \forest@nodewalk@stripfakesteps{\pgfkeysalso{#1}}}, + define long step={walk back}{n args=1,@bare}{% + \pgfmathtruncatemacro\forest@temp@n{#1}% + \forest@nodewalk@walklist{\forest@nodewalk@historyforward}{\forest@nodewalk@historyback}{\ifnum\forest@cn=0 0\else1\fi}{\forest@temp@n+\ifnum\forest@cn=0 0\else1\fi}{\let\forest@cn\forest@nodewalk@cn\forest@nodewalk@makestep}% + \forest@nodewalk@back@updatehistory + }, + nodewalk/walk back/.default=1, + define long step={jump back}{n args=1,@bare}{% + \pgfmathtruncatemacro\forest@temp@n{(#1)+\ifnum\forest@cn=0 0\else1\fi}% + \forest@nodewalk@walklist{\forest@nodewalk@historyforward}{\forest@nodewalk@historyback}{\forest@temp@n-1}{\forest@temp@n}{\let\forest@cn\forest@nodewalk@cn\forest@nodewalk@makestep}% + \forest@nodewalk@back@updatehistory + }, + nodewalk/jump back/.default=1, + define long step={back}{n args=1,@bare}{% + \pgfmathtruncatemacro\forest@temp@n{#1}% + \forest@nodewalk@walklist{\forest@nodewalk@historyforward}{\forest@nodewalk@historyback}{\ifnum\forest@cn=0 0\else1\fi}{\forest@temp@n+\ifnum\forest@cn=0 0\else1\fi}{\let\forest@cn\forest@nodewalk@cn\forest@saveandrestoreifcs{forest@nodewalk@fake}{\forest@nodewalk@faketrue\forest@nodewalk@makestep}}% + \forest@nodewalk@back@updatehistory + }, + nodewalk/back/.default=1, + define long step={walk forward}{n args=1,@bare}{% + \pgfmathtruncatemacro\forest@temp@n{#1}% + \forest@nodewalk@walklist{\forest@nodewalk@historyback}{\forest@nodewalk@historyforward}{0}{\forest@temp@n}{\let\forest@cn\forest@nodewalk@cn\forest@nodewalk@makestep}% + \forest@nodewalk@forward@updatehistory + }, + nodewalk/walk forward/.default=1, + define long step={jump forward}{n args=1,@bare}{% + \pgfmathtruncatemacro\forest@temp@n{#1}% + \forest@nodewalk@walklist{\forest@nodewalk@historyback}{\forest@nodewalk@historyforward}{\forest@temp@n-1}{\forest@temp@n}{\let\forest@cn\forest@nodewalk@cn\forest@nodewalk@makestep}% + \forest@nodewalk@forward@updatehistory + }, + nodewalk/jump forward/.default=1, + define long step={forward}{n args=1,@bare}{% + \pgfmathtruncatemacro\forest@temp@n{#1}% + \forest@nodewalk@walklist{\forest@nodewalk@historyback}{\forest@nodewalk@historyforward}{0}{\forest@temp@n}{\let\forest@cn\forest@nodewalk@cn\forest@saveandrestoreifcs{forest@nodewalk@fake}{\forest@nodewalk@faketrue\forest@nodewalk@makestep}}% + \forest@nodewalk@forward@updatehistory + }, + nodewalk/forward/.default=1, + define long step={last valid'}{@bare}{% + \ifnum\forest@cn=0 + \forest@nodewalk@tolastvalid + \forest@nodewalk@makestep + \fi + }, + define long step={last valid}{@bare}{% + \forest@nodewalk@tolastvalid + }, + define long step={reverse}{n args=1,@bare,make for}{% + \forest@nodewalk{#1,TeX={% + \global\let\forest@global@temp\forest@nodewalk@historyback + \global\let\forest@global@tempn\forest@nodewalk@n + }}{}% + \forest@nodewalk@walklist{}{\forest@global@temp}{0}{\forest@global@tempn}{\let\forest@cn\forest@nodewalk@cn\forest@nodewalk@makestep}% + }, + define long step={walk and reverse}{n args=1,@bare,make for}{% + \edef\forest@marshal{% + \noexpand\pgfkeysalso{\unexpanded{#1}}% + \noexpand\forest@nodewalk@walklist{}{\noexpand\forest@nodewalk@historyback}{0}{\noexpand\forest@nodewalk@n-\forest@nodewalk@n}{\let\noexpand\forest@cn\noexpand\forest@nodewalk@cn\noexpand\forest@nodewalk@makestep}% + }\forest@marshal + }, + define long step={sort}{n args=1,@bare,make for}{% + \forest@nodewalk{#1,TeX={% + \global\let\forest@global@temp\forest@nodewalk@historyback + \global\let\forest@global@tempn\forest@nodewalk@n + }}{}% + \forest@nodewalk@sortlist{\forest@global@temp}{\forest@global@tempn}\forest@sort@ascending + }, + define long step={sort'}{n args=1,@bare,make for}{% + \forest@nodewalk{#1,TeX={% + \global\let\forest@global@temp\forest@nodewalk@historyback + \global\let\forest@global@tempn\forest@nodewalk@n + }}{}% + \forest@nodewalk@sortlist{\forest@global@temp}{\forest@global@tempn}\forest@sort@descending + }, + define long step={walk and sort}{n args=1,@bare,make for}{% walk as given, then walk sorted + \edef\forest@marshal{% + \noexpand\pgfkeysalso{\unexpanded{#1}}% + \noexpand\forest@nodewalk@sortlist{\noexpand\forest@nodewalk@historyback}{\noexpand\forest@nodewalk@n-\forest@nodewalk@n}\noexpand\forest@sort@ascending + }\forest@marshal + }, + define long step={walk and sort'}{n args=1,@bare,make for}{% + \edef\forest@marshal{% + \noexpand\pgfkeysalso{\unexpanded{#1}}% + \noexpand\forest@nodewalk@sortlist{\noexpand\forest@nodewalk@historyback}{\noexpand\forest@nodewalk@n-\forest@nodewalk@n}\noexpand\forest@sort@descending + }\forest@marshal + }, + sort by/.store in=\forest@nodesort@by, + define long step={save}{n args=2,@bare,make for}{% #1 = name, #2 = nodewalk + \forest@forthis{% + \forest@nodewalk{#2,TeX={% + \global\let\forest@global@temp\forest@nodewalk@historyback + \global\let\forest@global@tempn\forest@nodewalk@n + }}{}% + }% + \forest@nodewalk@walklist{}{\forest@global@temp}{0}{\forest@global@tempn}\relax + \csedef{forest@nodewalk@saved@#1}{\forest@nodewalk@walklist@walked}% + }, + define long step={walk and save}{n args=2,@bare,make for}{% #1 = name, #2 = nodewalk + \edef\forest@marshal{% + \noexpand\pgfkeysalso{\unexpanded{#2}}% + \noexpand\forest@nodewalk@walklist{}{\noexpand\forest@nodewalk@historyback}{0}{\noexpand\forest@nodewalk@n-\forest@nodewalk@n}\relax + }\forest@marshal + \csedef{forest@nodewalk@saved@#1}{\forest@nodewalk@walklist@walked}% + }, + nodewalk/save history/.code 2 args={% #1 = back, forward + \csedef{forest@nodewalk@saved@#1}{\forest@nodewalk@historyback}% + \csedef{forest@nodewalk@saved@#2}{\forest@nodewalk@historyforward}% + }, + define long step={load}{n args=1,@bare,make for}{% + \forest@nodewalk@walklist{}{\csuse{forest@nodewalk@saved@#1}0,}{0}{-1}{\ifnum\forest@nodewalk@cn=0 \else\let\forest@cn\forest@nodewalk@cn\forest@nodewalk@makestep\fi}% + }, + if in saved nodewalk/.code n args=4{% is node #1 in nodewalk #2; yes: #3, no: #4 + \forest@forthis{% + \forest@go{#1}% + \edef\forest@marshal{% + \noexpand\pgfutil@in@{,\forest@cn,}{,\csuse{forest@nodewalk@saved@#2},}% + }\forest@marshal + }% + \ifpgfutil@in@ + \@escapeif{\pgfkeysalso{#3}}% + \else + \@escapeif{\pgfkeysalso{#4}}% + \fi + }, + where in saved nodewalk/.style n args=4{ + for tree={if in saved nodewalk={#1}{#2}{#3}{#4}} + }, + nodewalk/options/.code={\forestset{#1}}, + nodewalk/TeX/.code={#1}, + nodewalk/TeX'/.code={\appto\forest@externalize@loadimages{#1}#1}, + nodewalk/TeX''/.code={\appto\forest@externalize@loadimages{#1}}, + nodewalk/typeout/.style={TeX={\typeout{#1}}}, + % repeat is taken later from /forest/repeat +} +\def\forest@nodewalk@walklist#1#2#3#4#5{% + % #1 = list of preceding, #2 = list to walk + % #3 = from, #4 = to + % #5 = every step code + \let\forest@nodewalk@cn\forest@cn + \edef\forest@marshal{% + \noexpand\forest@nodewalk@walklist@{#1}{#2}{\number\numexpr#3}{\number\numexpr#4}{1}{0}{\unexpanded{#5}}% + }\forest@marshal +} +\def\forest@nodewalk@walklist@#1#2#3#4#5#6#7{% + % #1 = list of walked, #2 = list to walk + % #3 = from, #4 = to + % #5 = current step n, #6 = steps made + % #7 = every step code + \def\forest@nodewalk@walklist@walked{#1}% + \def\forest@nodewalk@walklist@rest{#2}% + \edef\forest@nodewalk@walklist@stepsmade{#6}% + \ifnum#4<0 + \forest@temptrue + \else + \ifnum#5>#4\relax + \forest@tempfalse + \else + \forest@temptrue + \fi + \fi + \ifforest@temp + \edef\forest@nodewalk@cn{\forest@csvlist@getfirst@{#2}}% + \ifnum\forest@nodewalk@cn=0 + #7% + \else + \ifnum#5>#3\relax + #7% + \edef\forest@nodewalk@walklist@stepsmade{\number\numexpr#6+1}% + \fi + \forest@csvlist@getfirstrest@{#2}\forest@nodewalk@cn\forest@nodewalk@walklist@rest + \@escapeifif{% + \edef\forest@marshal{% + \noexpand\forest@nodewalk@walklist@ + {\forest@nodewalk@cn,#1}{\forest@nodewalk@walklist@rest}{#3}{#4}{\number\numexpr#5+1}{\forest@nodewalk@walklist@stepsmade}{\unexpanded{#7}}% + }\forest@marshal + }% + \fi + \fi +} + +\def\forest@nodewalk@back@updatehistory{% + \ifnum\forest@cn=0 + \let\forest@nodewalk@historyback\forest@nodewalk@walklist@rest + \let\forest@nodewalk@historyforward\forest@nodewalk@walklist@walked + \else + \expandafter\forest@csvlist@getfirstrest@\expandafter{\forest@nodewalk@walklist@walked}\forest@temp\forest@nodewalk@historyforward + \edef\forest@nodewalk@historyback{\forest@temp,\forest@nodewalk@walklist@rest}% + \fi +} +\def\forest@nodewalk@forward@updatehistory{% + \let\forest@nodewalk@historyforward\forest@nodewalk@walklist@rest + \let\forest@nodewalk@historyback\forest@nodewalk@walklist@walked +} +\def\forest@go#1{% + \def\forest@nodewalk@config@everystep@method{independent}% + \def\forest@nodewalk@config@history@method{inherited}% + \def\forest@nodewalk@config@oninvalid{inherited}% + \forest@saveandrestoremacro\forest@nodewalk@oninvalid{% + \forest@Nodewalk{#1}{}% + }% +} +\def\forest@csvlist@getfirst@#1{% assuming that the list is nonempty and finishes with a comma + \forest@csvlist@getfirst@@#1\forest@csvlist@getfirst@@} +\def\forest@csvlist@getfirst@@#1,#2\forest@csvlist@getfirst@@{#1} +\def\forest@csvlist@getrest@#1{% assuming that the list is nonempty and finishes with a comma + \forest@csvlist@getrest@@#1\forest@csvlist@getrest@@} +\def\forest@csvlist@getrest@@#1,#2\forest@csvlist@getrest@@{#2} +\def\forest@csvlist@getfirstrest@#1#2#3{% assuming that the list is nonempty and finishes with a comma + % #1 = list, #2 = cs receiving first, #3 = cs receiving rest + \forest@csvlist@getfirstrest@@#1\forest@csvlist@getfirstrest@@{#2}{#3}} +\def\forest@csvlist@getfirstrest@@#1,#2\forest@csvlist@getfirstrest@@#3#4{% + \def#3{#1}% + \def#4{#2}% +} +\def\forest@nodewalk@stripfakesteps#1{% + % go to the last valid node if the walk contained any nodes, otherwise restore the current node + \edef\forest@marshal{% + \unexpanded{#1}% + \noexpand\ifnum\noexpand\forest@nodewalk@n=\forest@nodewalk@n\relax + \def\noexpand\forest@cn{\forest@cn}% + \noexpand\else + \unexpanded{% + \edef\forest@cn{% + \expandafter\forest@csvlist@getfirst@\expandafter{\forest@nodewalk@historyback}% + }% + }% + \noexpand\fi + }\forest@marshal +} +\def\forest@nodewalk@tolastvalid{% + \ifnum\forest@cn=0 + \edef\forest@cn{\expandafter\forest@csvlist@getfirst@\expandafter{\forest@nodewalk@historyback}}% + \ifnum\forest@cn=0 + \let\forest@cn\forest@nodewalk@origin + \fi + \fi +} +\def\forest@nodewalk@sortlist#1#2#3{%#1=list,#2=to,#3=asc/desc + \edef\forest@nodewalksort@list{#1}% + \expandafter\forest@nodewalk@sortlist@\expandafter{\number\numexpr#2}{#3}% +} +\def\forest@nodewalk@sortlist@#1#2{%#1=to,#2=asc/desc + \safeloop + \unless\ifnum\safeloopn>#1\relax + \expandafter\forest@csvlist@getfirstrest@\expandafter{\forest@nodewalksort@list}\forest@nodewalksort@cn\forest@nodewalksort@list + \csedef{forest@nodesort@\safeloopn}{\forest@nodewalksort@cn}% + \saferepeat + \edef\forest@nodesort@sortkey{\forest@nodesort@by}% + \forest@sort\forest@nodesort@cmpnodes\forest@nodesort@let#2{1}{#1}% + \def\forest@nodewalksort@sorted{}% + \safeloop + \unless\ifnum\safeloopn>#1\relax + \edef\forest@cn{\csname forest@nodesort@\safeloopn\endcsname}% + \forest@nodewalk@makestep + \saferepeat +} +\forestset{ + define long step={min}{n args=1,@bare,make for}{% the first min in the argument nodewalk + \forest@nodewalk{#1,TeX={% + \global\let\forest@global@temp\forest@nodewalk@historyback + }}{}% + \forest@nodewalk@minmax{\forest@global@temp}{-1}{<}{\forest@nodewalk@minmax@node,}% + }, + define long step={mins}{n args=1,@bare,make for}{% all mins in the argument nodewalk + \forest@nodewalk{#1,TeX={% + \global\let\forest@global@temp\forest@nodewalk@historyback + }}{}% + \forest@nodewalk@minmax{\forest@global@temp}{-1}{<}{\forest@nodewalk@minmax@nodes}% + }, + define long step={walk and min}{n args=1,@bare}{% + \edef\forest@marshal{% + \noexpand\pgfkeysalso{\unexpanded{#1}}% + \noexpand\forest@nodewalk@minmax{\noexpand\forest@nodewalk@historyback}{\noexpand\forest@nodewalk@n-\forest@nodewalk@n}{<}{\noexpand\forest@nodewalk@minmax@node,}%% + }\forest@marshal + }, + define long step={walk and mins}{n args=1,@bare}{% + \edef\forest@marshal{% + \noexpand\pgfkeysalso{\unexpanded{#1}}% + \noexpand\forest@nodewalk@minmax{\noexpand\forest@nodewalk@historyback}{\noexpand\forest@nodewalk@n-\forest@nodewalk@n}{<}{\noexpand\forest@nodewalk@minmax@nodes}%% + }\forest@marshal + }, + define long step={min in nodewalk}{@bare}{% find the first min in the preceding nodewalk, step to it + \forest@nodewalk@minmax{\forest@nodewalk@historyback}{-1}{<}{\forest@nodewalk@minmax@node,}% + }, + define long step={mins in nodewalk}{@bare}{% find mins in the preceding nodewalk, step to mins + \forest@nodewalk@minmax{\forest@nodewalk@historyback}{-1}{<}{\forest@nodewalk@minmax@nodes}% + }, + define long step={min in nodewalk'}{@bare}{% find the first min in the preceding nodewalk, step to min in history + \forest@nodewalk@minmax{\forest@nodewalk@historyback}{-1}{<}{}% + }, + % + define long step={max}{n args=1,@bare,make for}{% the first max in the argument nodewalk + \forest@nodewalk{#1,TeX={% + \global\let\forest@global@temp\forest@nodewalk@historyback + }}{}% + \forest@nodewalk@minmax{\forest@global@temp}{-1}{>}{\forest@nodewalk@minmax@node,}% + }, + define long step={maxs}{n args=1,@bare,make for}{% all maxs in the argument nodewalk + \forest@nodewalk{#1,TeX={% + \global\let\forest@global@temp\forest@nodewalk@historyback + }}{}% + \forest@nodewalk@minmax{\forest@global@temp}{-1}{>}{\forest@nodewalk@minmax@nodes}% + }, + define long step={walk and max}{n args=1,@bare}{% + \edef\forest@marshal{% + \noexpand\pgfkeysalso{\unexpanded{#1}}% + \noexpand\forest@nodewalk@minmax{\noexpand\forest@nodewalk@historyback}{\noexpand\forest@nodewalk@n-\forest@nodewalk@n}{>}{\noexpand\forest@nodewalk@minmax@node,}%% + }\forest@marshal + }, + define long step={walk and maxs}{n args=1,@bare}{% + \edef\forest@marshal{% + \noexpand\pgfkeysalso{\unexpanded{#1}}% + \noexpand\forest@nodewalk@minmax{\noexpand\forest@nodewalk@historyback}{\noexpand\forest@nodewalk@n-\forest@nodewalk@n}{>}{\noexpand\forest@nodewalk@minmax@nodes}%% + }\forest@marshal + }, + define long step={max in nodewalk}{@bare}{% find the first max in the preceding nodewalk, step to it + \forest@nodewalk@minmax{\forest@nodewalk@historyback}{-1}{>}{\forest@nodewalk@minmax@node,}% + }, + define long step={maxs in nodewalk}{@bare}{% find maxs in the preceding nodewalk, step to maxs + \forest@nodewalk@minmax{\forest@nodewalk@historyback}{-1}{>}{\forest@nodewalk@minmax@nodes}% + }, + define long step={max in nodewalk'}{@bare}{% find the first max in the preceding nodewalk, step to max in history + \forest@nodewalk@minmax{\forest@nodewalk@historyback}{-1}{>}{}% + }, +} + +\def\forest@nodewalk@minmax#1#2#3#4{% + % #1 = list of nodes + % #2 = max index in list (start with 1) + % #3 = min/max = ascending/descending = + % #4 = how many results? 1 = {\forest@nodewalk@minmax@node,}, all={\forest@nodewalk@minmax@nodes}, walk in history={} + \edef\forest@nodesort@sortkey{\forest@nodesort@by}% + \edef\forest@nodewalk@minmax@N{\number\numexpr#2}% + \edef\forest@nodewalk@minmax@n{}% + \edef\forest@nodewalk@minmax@list{#1}% + \def\forest@nodewalk@minmax@nodes{}% + \def\forest@nodewalk@minmax@node{}% + \ifdefempty{\forest@nodewalk@minmax@list}{% + }{% + \safeloop + \expandafter\forest@csvlist@getfirstrest@\expandafter{\forest@nodewalk@minmax@list}\forest@nodewalk@minmax@cn\forest@nodewalk@minmax@list + \ifnum\forest@nodewalk@minmax@cn=0 \else + \ifdefempty{\forest@nodewalk@minmax@node}{% + \edef\forest@nodewalk@minmax@node{\forest@nodewalk@minmax@cn}% + \edef\forest@nodewalk@minmax@nodes{\forest@nodewalk@minmax@cn,}% + \edef\forest@nodewalk@minmax@n{\safeloopn}% + }{% + \csedef{forest@nodesort@1}{\forest@nodewalk@minmax@node}% + \csedef{forest@nodesort@2}{\forest@nodewalk@minmax@cn}% + \forest@nodesort@cmpnodes{2}{1}% + \if=\forest@sort@cmp@result + \edef\forest@nodewalk@minmax@node{\forest@nodewalk@minmax@cn}% + \epreto\forest@nodewalk@minmax@nodes{\forest@nodewalk@minmax@cn,}% + \edef\forest@nodewalk@minmax@n{\safeloopn}% + \else + \if#3\forest@sort@cmp@result + \edef\forest@nodewalk@minmax@node{\forest@nodewalk@minmax@cn}% + \edef\forest@nodewalk@minmax@nodes{\forest@nodewalk@minmax@cn,}% + \edef\forest@nodewalk@minmax@n{\safeloopn}% + \fi + \fi + }% + \fi + \ifdefempty{\forest@nodewalk@minmax@list}{\forest@tempfalse}{\forest@temptrue}% + \ifnum\safeloopn=\forest@nodewalk@minmax@N\relax\forest@temptrue\fi + \ifforest@temp + \saferepeat + \edef\forest@nodewalk@minmax@list{#4}% + \ifdefempty\forest@nodewalk@minmax@list{% + \forestset{nodewalk/jump back=\forest@nodewalk@minmax@n-1}% CHECK + }{% + \safeloop + \expandafter\forest@csvlist@getfirstrest@\expandafter{\forest@nodewalk@minmax@list}\forest@cn\forest@nodewalk@minmax@list + \forest@nodewalk@makestep + \ifdefempty{\forest@nodewalk@minmax@list}{\forest@tempfalse}{\forest@temptrue}% + \ifforest@temp + \saferepeat + }% + }% +} +\newtoks\forest@nodewalk@shortsteps@resolution +\newif\ifforest@nodewalk@areshortsteps +\pgfqkeys{/forest/nodewalk}{ + .unknown/.code={% + \forest@nodewalk@areshortstepsfalse + \pgfkeysifdefined{/forest/\pgfkeyscurrentname/@.cmd}{% + }{% + \ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text % no value, so possibly short steps + \forest@nodewalk@shortsteps@resolution{}% + \forest@nodewalk@areshortstepstrue + \expandafter\forest@nodewalk@shortsteps\pgfkeyscurrentname==========,% "=" and "," cannot be short steps, so they are good as delimiters + \fi + }% + \ifforest@nodewalk@areshortsteps + \@escapeif{\expandafter\pgfkeysalso\expandafter{\the\forest@nodewalk@shortsteps@resolution}}% + \else + \@escapeif{\pgfkeysalso{/forest/\pgfkeyscurrentname={#1}}}% + \fi + }, +} +\def\forest@nodewalk@shortsteps{% + \futurelet\forest@nodewalk@nexttoken\forest@nodewalk@shortsteps@ +} +\def\forest@nodewalk@shortsteps@{% + \ifx\forest@nodewalk@nexttoken=% + \let\forest@nodewalk@nextop\forest@nodewalk@shortsteps@end + \else + \ifx\forest@nodewalk@nexttoken\bgroup + \letcs\forest@nodewalk@nextop{forest@shortstep@group}% + \else + \let\forest@nodewalk@nextop\forest@nodewalk@shortsteps@@ + \fi + \fi + \forest@nodewalk@nextop +} +\def\forest@nodewalk@shortsteps@@#1{% + \ifcsdef{forest@shortstep@#1}{% + \csname forest@shortstep@#1\endcsname + }{% + \forest@nodewalk@areshortstepsfalse + \forest@nodewalk@shortsteps@end + }% +} +\csdef{forest@nodewalk@defshortstep@0@args}#1#2{% + \csdef{forest@shortstep@#1}{% + \apptotoks\forest@nodewalk@shortsteps@resolution{,#2}% + \forest@nodewalk@shortsteps}} +\csdef{forest@nodewalk@defshortstep@1@args}#1#2{% + \csdef{forest@shortstep@#1}##1{% + \edef\forest@marshal####1{#2}% + \eapptotoks\forest@nodewalk@shortsteps@resolution{,\forest@marshal{##1}}% + \forest@nodewalk@shortsteps}} +\csdef{forest@nodewalk@defshortstep@2@args}#1#2{% + \csdef{forest@shortstep@#1}##1##2{% + \edef\forest@marshal####1####2{#2}% + \eapptotoks\forest@nodewalk@shortsteps@resolution{,\forest@marshal{##1}{##2}}% + \forest@nodewalk@shortsteps}} +\csdef{forest@nodewalk@defshortstep@3@args}#1#2{% + \csdef{forest@shortstep@#1}##1##2##3{% + \edef\forest@marshal####1####2####3{#2}% + \eapptotoks\forest@nodewalk@shortsteps@resolution{,\forest@marshal{##1}{##2}{##3}}% + \forest@nodewalk@shortsteps}} +\csdef{forest@nodewalk@defshortstep@4@args}#1#2{% + \csdef{forest@shortstep@#1}##1##2##3##4{% + \edef\forest@marshal####1####2####3####4{#2}% + \eapptotoks\forest@nodewalk@shortsteps@resolution{,\forest@marshal{##1}{##2}{##3}{##4}}% + \forest@nodewalk@shortsteps}} +\csdef{forest@nodewalk@defshortstep@5@args}#1#2{% + \csdef{forest@shortstep@#1}##1##2##3##4##5{% + \edef\forest@marshal####1####2####3####4####5{#2}% + \eapptotoks\forest@nodewalk@shortsteps@resolution{,\forest@marshal{##1}{##2}{##3}{##4}{##5}}% + \forest@nodewalk@shortsteps}} +\csdef{forest@nodewalk@defshortstep@6@args}#1#2{% + \csdef{forest@shortstep@#1}##1##2##3##4##5##6{% + \edef\forest@marshal####1####2####3####4####5####6{#2}% + \eapptotoks\forest@nodewalk@shortsteps@resolution{,\forest@marshal{##1}{##2}{##3}{##4}{##5}{##6}}% + \forest@nodewalk@shortsteps}} +\csdef{forest@nodewalk@defshortstep@7@args}#1#2{% + \csdef{forest@shortstep@#1}##1##2##3##4##5##6##7{% + \edef\forest@marshal####1####2####3####4####5####6####7{#2}% + \eapptotoks\forest@nodewalk@shortsteps@resolution{,\forest@marshal{##1}{##2}{##3}{##4}{##5}{##6}{##7}}% + \forest@nodewalk@shortsteps}} +\csdef{forest@nodewalk@defshortstep@8@args}#1#2{% + \csdef{forest@shortstep@#1}##1##2##3##4##5##6##7##8{% + \edef\forest@marshal####1####2####3####4####5####6####7####8{#2}% + \eapptotoks\forest@nodewalk@shortsteps@resolution{,\forest@marshal{##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}}% + \forest@nodewalk@shortsteps}} +\csdef{forest@nodewalk@defshortstep@9@args}#1#2{% + \csdef{forest@shortstep@#1}##1##2##3##4##5##6##7##8##9{% + \edef\forest@marshal####1####2####3####4####5####6####7####8####9{#2}% + \eapptotoks\forest@nodewalk@shortsteps@resolution{,\forest@marshal{##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}{##9}}% + \forest@nodewalk@shortsteps}} +\forestset{ + define short step/.code n args=3{% #1 = short step, #2 = n args, #3 = long step + \csname forest@nodewalk@defshortstep@#2@args\endcsname{#1}{#3}% + }, +} +\def\forest@nodewalk@shortsteps@end#1,{} +\forestset{ + define short step={group}{1}{group={#1}}, % {braces} are special + define short step={p}{0}{previous}, + define short step={n}{0}{next}, + define short step={u}{0}{parent}, + define short step={s}{0}{sibling}, + define short step={c}{0}{current}, + define short step={o}{0}{origin}, + define short step={r}{0}{root}, + define short step={R}{0}{root'}, + define short step={P}{0}{previous leaf}, + define short step={N}{0}{next leaf}, + define short step={F}{0}{first leaf}, + define short step={L}{0}{last leaf}, + define short step={>}{0}{next on tier}, + define short step={<}{0}{previous on tier}, + define short step={1}{0}{n=1}, + define short step={2}{0}{n=2}, + define short step={3}{0}{n=3}, + define short step={4}{0}{n=4}, + define short step={5}{0}{n=5}, + define short step={6}{0}{n=6}, + define short step={7}{0}{n=7}, + define short step={8}{0}{n=8}, + define short step={9}{0}{n=9}, + define short step={l}{0}{last}, + define short step={b}{0}{back}, + define short step={f}{0}{forward}, + define short step={v}{0}{last valid}, + define short step={*}{2}{repeat={#1}{#2}}, + for 1/.style={for nodewalk={n=1}{#1}}, + for 2/.style={for nodewalk={n=2}{#1}}, + for 3/.style={for nodewalk={n=3}{#1}}, + for 4/.style={for nodewalk={n=4}{#1}}, + for 5/.style={for nodewalk={n=5}{#1}}, + for 6/.style={for nodewalk={n=6}{#1}}, + for 7/.style={for nodewalk={n=7}{#1}}, + for 8/.style={for nodewalk={n=8}{#1}}, + for 9/.style={for nodewalk={n=9}{#1}}, + for -1/.style={for nodewalk={n'=1}{#1}}, + for -2/.style={for nodewalk={n'=2}{#1}}, + for -3/.style={for nodewalk={n'=3}{#1}}, + for -4/.style={for nodewalk={n'=4}{#1}}, + for -5/.style={for nodewalk={n'=5}{#1}}, + for -6/.style={for nodewalk={n'=6}{#1}}, + for -7/.style={for nodewalk={n'=7}{#1}}, + for -8/.style={for nodewalk={n'=8}{#1}}, + for -9/.style={for nodewalk={n'=9}{#1}}, +} +\forestset{ + define long step={tree}{}{\forest@node@foreach{\forest@nodewalk@makestep}}, + define long step={tree reversed}{}{\forest@node@foreach@reversed{\forest@nodewalk@makestep}}, + define long step={tree children-first}{}{\forest@node@foreach@childrenfirst{\forest@nodewalk@makestep}}, + define long step={tree children-first reversed}{}{\forest@node@foreach@childrenfirst@reversed{\forest@nodewalk@makestep}}, + define long step={tree breadth-first}{}{\forest@node@foreach@breadthfirst{-1}{\forest@nodewalk@makestep}}, + define long step={tree breadth-first reversed}{}{\forest@node@foreach@breadthfirst@reversed{-1}{\forest@nodewalk@makestep}}, + define long step={descendants}{}{\forest@node@foreachdescendant{\forest@nodewalk@makestep}}, + define long step={descendants reversed}{}{\forest@node@foreachdescendant@reversed{\forest@nodewalk@makestep}}, + define long step={descendants children-first}{}{\forest@node@foreachdescendant@childrenfirst{\forest@nodewalk@makestep}}, + define long step={descendants children-first reversed}{}{\forest@node@foreachdescendant@childrenfirst@reversed{\forest@nodewalk@makestep}}, + define long step={descendants breadth-first}{}{\forest@node@foreach@breadthfirst{0}{\forest@nodewalk@makestep}}, + define long step={descendants breadth-first reversed}{}{\forest@node@foreach@breadthfirst@reversed{0}{\forest@nodewalk@makestep}}, + define long step={level}{n args=1}{% + \pgfmathtruncatemacro\forest@temp{#1}% + \edef\forest@marshal{% + \noexpand\forest@node@foreach@breadthfirst + {\forest@temp}% + {\noexpand\ifnum\noexpand\forestove{level}=\forest@temp\relax\noexpand\forest@nodewalk@makestep\noexpand\fi}% + }\forest@marshal + }, + define long step={level>}{n args=1}{% + \pgfmathtruncatemacro\forest@temp{#1}% + \edef\forest@marshal{% + \noexpand\forest@node@foreach@breadthfirst + {-1}% + {\noexpand\ifnum\noexpand\forestove{level}<\forest@temp\relax\noexpand\else\noexpand\forest@nodewalk@makestep\noexpand\fi}% + }\forest@marshal + }, + define long step={level<}{n args=1}{% + \pgfmathtruncatemacro\forest@temp{(#1)-1}% + % \show\forest@temp + \ifnum\forest@temp=-1 + % special case, as \forest@node@foreach@breadthfirst uses level<0 as a signal for unlimited max level + \ifnum\forestove{level}=0 + \forest@nodewalk@makestep + \fi + \else + \edef\forest@marshal{% + \noexpand\forest@node@foreach@breadthfirst + {\forest@temp}% + {\noexpand\forest@nodewalk@makestep}% + }\forest@marshal + \fi + }, + define long step={level reversed}{n args=1}{% + \pgfmathtruncatemacro\forest@temp{#1}% + \edef\forest@marshal{% + \noexpand\forest@node@foreach@breadthfirst@reversed + {\forest@temp}% + {\noexpand\ifnum\noexpand\forestove{level}=\forest@temp\relax\noexpand\forest@nodewalk@makestep\noexpand\fi}% + }\forest@marshal + }, + define long step={level reversed>}{n args=1}{% + \pgfmathtruncatemacro\forest@temp{#1}% + \edef\forest@marshal{% + \noexpand\forest@node@foreach@breadthfirst@reversed + {-1}% + {\noexpand\ifnum\noexpand\forestove{level}<\forest@temp\relax\noexpand\else\noexpand\forest@nodewalk@makestep\noexpand\fi}% + }\forest@marshal + }, + define long step={level reversed<}{n args=1}{% + \pgfmathtruncatemacro\forest@temp{(#1)-1}% + \edef\forest@marshal{% + \noexpand\forest@node@foreach@breadthfirst@reversed + {\forest@temp}% + {\noexpand\forest@nodewalk@makestep}% + }\forest@marshal + }, + % + define long step={relative level}{n args=1}{% + \pgfmathtruncatemacro\forest@temp{(#1)+\forestove{level}}% + \edef\forest@marshal{% + \noexpand\forest@node@foreach@breadthfirst + {\forest@temp}% + {\noexpand\ifnum\noexpand\forestove{level}=\forest@temp\relax\noexpand\forest@nodewalk@makestep\noexpand\fi}% + }\forest@marshal + }, + define long step={relative level>}{n args=1}{% + \pgfmathtruncatemacro\forest@temp{(#1)+\forestove{level}}% + \edef\forest@marshal{% + \noexpand\forest@node@foreach@breadthfirst + {-1}% + {\noexpand\ifnum\noexpand\forestove{level}<\forest@temp\relax\noexpand\else\noexpand\forest@nodewalk@makestep\noexpand\fi}% + }\forest@marshal + }, + define long step={relative level<}{n args=1}{% + \pgfmathtruncatemacro\forest@temp{(#1)+\forestove{level}-1}% + \edef\forest@marshal{% + \noexpand\forest@node@foreach@breadthfirst + {\forest@temp}% + {\noexpand\forest@nodewalk@makestep}% + }\forest@marshal + }, + define long step={relative level reversed}{n args=1}{% + \pgfmathtruncatemacro\forest@temp{(#1)+\forestove{level}}% + \edef\forest@marshal{% + \noexpand\forest@node@foreach@breadthfirst@reversed + {\forest@temp}% + {\noexpand\ifnum\noexpand\forestove{level}=\forest@temp\relax\noexpand\forest@nodewalk@makestep\noexpand\fi}% + }\forest@marshal + }, + define long step={relative level reversed>}{n args=1}{% + \pgfmathtruncatemacro\forest@temp{(#1)+\forestove{level}}% + \edef\forest@marshal{% + \noexpand\forest@node@foreach@breadthfirst@reversed + {-1}% + {\noexpand\ifnum\noexpand\forestove{level}<\forest@temp\relax\noexpand\else\noexpand\forest@nodewalk@makestep\noexpand\fi}% + }\forest@marshal + }, + define long step={relative level reversed<}{n args=1}{% + \pgfmathtruncatemacro\forest@temp{(#1)+\forestove{level}-1}% + \edef\forest@marshal{% + \noexpand\forest@node@foreach@breadthfirst@reversed + {\forest@temp}% + {\noexpand\forest@nodewalk@makestep}% + }\forest@marshal + }, + define long step={children}{}{\forest@node@foreachchild{\forest@nodewalk@makestep}}, + define long step={children reversed}{}{\forest@node@foreachchild@reversed{\forest@nodewalk@makestep}}, + define long step={current and following siblings}{}{\forest@node@@forselfandfollowingsiblings{\forest@nodewalk@makestep}}, + define long step={following siblings}{style}{if nodewalk valid={next}{fake=next,current and following siblings}{}}, + define long step={current and preceding siblings}{}{\forest@node@@forselfandprecedingsiblings{\forest@nodewalk@makestep}}, + define long step={preceding siblings}{style}{if nodewalk valid={previous}{fake=previous,current and preceding siblings}{}}, + define long step={current and following siblings reversed}{}{\forest@node@@forselfandfollowingsiblings@reversed{\forest@nodewalk@makestep}}, + define long step={following siblings reversed}{style}{fake=next,current and following siblings reversed}, + define long step={current and preceding siblings reversed}{}{\forest@node@@forselfandprecedingsiblings@reversed{\forest@nodewalk@makestep}}, + define long step={preceding siblings reversed}{style}{fake=previous,current and preceding siblings reversed}, + define long step={siblings}{style}{for nodewalk'={preceding siblings},following siblings}, + define long step={siblings reversed}{style}{for nodewalk'={following siblings reversed},preceding siblings reversed}, + define long step={current and siblings}{style}{for nodewalk'={preceding siblings},current and following siblings}, + define long step={current and siblings reversed}{style}{for nodewalk'={current and following siblings reversed},preceding siblings reversed}, + define long step={ancestors}{style}{while={}{parent},last valid}, + define long step={current and ancestors}{style}{current,ancestors}, + define long step={following nodes}{style}{while={}{next node},last valid}, + define long step={preceding nodes}{style}{while={}{previous node},last valid}, + define long step={current and following nodes}{style}{current,following nodes}, + define long step={current and preceding nodes}{style}{current,preceding nodes}, +} +\let\forest@nodewalkstephandler@styletrueorfalse\forest@nodewalkstephandler@styletrue +\def\forest@last@node{0} +\csdef{forest@nodewalk@saved@dynamic nodes}{} +\def\forest@nodehandleby@name@nodewalk@or@bracket#1{% + \ifx\pgfkeysnovalue#1% + \edef\forest@last@node{\forest@node@Nametoid{forest@last@node}}% + \else + \forest@nodehandleby@nnb@checkfirst#1\forest@END + \fi +} +\def\forest@nodehandleby@nnb@checkfirst#1#2\forest@END{% + \ifx[#1%] + \forest@create@node{#1#2}% + \cseappto{forest@nodewalk@saved@dynamic nodes}{\forest@last@node,}% + \else + \forest@forthis{% + \forest@nameandgo{#1#2}% + \ifnum\forest@cn=0 + \PackageError{forest}{Cannot use a dynamic key on the invalid node}{}% + \fi + \let\forest@last@node\forest@cn + }% + \fi +} +\def\forest@create@node#1{% #1=bracket representation + \bracketParse{\forest@create@collectafterthought}% + \forest@last@node=#1\forest@end@create@node +} +\def\forest@create@collectafterthought#1\forest@end@create@node{% + \forest@node@Foreach{\forest@last@node}{% + \forestoleto{delay}{given options}% + \forestoset{given options}{}% + }% + \forestOeappto{\forest@last@node}{delay}{,\unexpanded{#1}}% + \forestOset{\forest@last@node}{given options}{delay={}}% +} +\def\forest@create@node@and@process@given@options#1{% #1=bracket representation + \bracketParse{\forest@createandprocess@collectafterthought}% + \forest@last@node=#1\forest@end@create@node +} +\def\forest@createandprocess@collectafterthought#1\forest@end@create@node{% + \forest@node@Compute@numeric@ts@info{\forest@last@node}% + \forest@saveandrestoremacro\forest@root{% + \let\forest@root\forest@last@node + \forestset{process keylist=given options}% + }% +} +\def\forest@saveandrestoremacro#1#2{% #1 = the (zero-arg) macro to save before and restore after processing code in #2 + \edef\forest@marshal{% + \unexpanded{#2}% + \noexpand\def\noexpand#1{\expandonce{#1}}% + }\forest@marshal +} +\def\forest@saveandrestoreifcs#1#2{% #1 = the if cs to save before and restore after processing code in #2 + \edef\forest@marshal{% + \unexpanded{#2}% + \ifbool{#1}{\noexpand\setbool{#1}{true}}{\noexpand\setbool{#1}{false}} + }\forest@marshal +} +\def\forest@saveandrestoretoks#1#2{% #1 = the toks to save before and restore after processing code in #2 + \edef\forest@marshal{% + \unexpanded{#2}% + \noexpand#1{\the#1}% + }\forest@marshal +} +\def\forest@saveandrestoreregister#1#2{% #1 = the register to save before and restore after processing code in #2 + \edef\forest@marshal{% + \unexpanded{#2}% + \noexpand\forestrset{#1}{\forestregister{#1}}% + }\forest@marshal +} +\forestset{ + save and restore register/.code 2 args={% + \forest@saveandrestoreregister{filter@ed}{% + \pgfkeysalso{#2}% + }% + }, +} +\def\forest@remove@node#1{% + \ifforestdebugdynamics\forestdebug@dynamics{before removing #1}\fi + \forest@node@Remove{#1}% +} +\def\forest@append@node#1#2{% + \ifforestdebugdynamics\forestdebug@dynamics{before appending #2 to #1}\fi + \forest@dynamic@circularitytest{#2}{#1}{append}% + \forest@node@Remove{#2}% + \forest@node@Append{#1}{#2}% +} +\def\forest@prepend@node#1#2{% + \ifforestdebugdynamics\forestdebug@dynamics{before prepending #2 to #1}\fi + \forest@dynamic@circularitytest{#2}{#1}{prepend}% + \forest@node@Remove{#2}% + \forest@node@Prepend{#1}{#2}% +} +\def\forest@insertafter@node#1#2{% + \ifforestdebugdynamics\forestdebug@dynamics{before inserting #2 after #1}\fi + \forest@node@Remove{#2}% + \forest@node@Insertafter{\forestOve{#1}{@parent}}{#2}{#1}% +} +\def\forest@insertbefore@node#1#2{% + \ifforestdebugdynamics\forestdebug@dynamics{before inserting #2 before #1}\fi + \forest@node@Remove{#2}% + \forest@node@Insertbefore{\forestOve{#1}{@parent}}{#2}{#1}% +} +\def\forest@set@root#1#2{% + \ifforestdebugdynamics\forestdebug@dynamics{before setting #1 as root}\fi + \def\forest@root{#2}% +} +\def\forest@dynamic@circularitytest#1#2#3{% + % #1=potenitial ancestor,#2=potential descendant, #3=message prefix + \ifnum#1=#2 + \forest@circularityerror{#1}{#2}{#3}% + \else + \forest@fornode{#1}{% + \forest@ifancestorof{#2}{\forest@circularityerror{#1}{#2}{#3}}{}% + }% + \fi +} +\def\forest@circularityerror#1#2#3{% + \forestdebug@typeouttrees{\forest@temp}% + \PackageError{forest}{#3ing node id=#1 to id=#2 would result in a circular tree\MessageBreak forest of ids: \forest@temp}{}% +}% +\def\forestdebug@dynamics#1{% + \forestdebug@typeouttrees\forest@temp + \typeout{#1: \forest@temp}% +} +\def\forest@appto@do@dynamics#1#2{% + \forest@nodehandleby@name@nodewalk@or@bracket{#2}% + \ifcase\forest@dynamics@copyhow\relax\or + \forest@tree@copy{\forest@last@node}\forest@last@node + \or + \forest@node@copy{\forest@last@node}\forest@last@node + \fi + \forest@node@Ifnamedefined{forest@last@node}{% + \forestOepreto{\forest@last@node}{delay} + {for id={\forest@node@Nametoid{forest@last@node}}{alias=forest@last@node},}% + }{}% + \edef\forest@marshal{% + \noexpand\apptotoks\noexpand\forest@do@dynamics{% + \noexpand#1{\forest@cn}{\forest@last@node}}% + }\forest@marshal +} +\forestset{% + create/.code={% + \forest@create@node{#1}% + \forest@fornode{\forest@last@node}{% + \forest@node@setalias{forest@last@node}% + \cseappto{forest@nodewalk@saved@dynamic nodes}{\forest@last@node,}% + }% + }, + create'/.code={% + \forest@create@node@and@process@given@options{#1}% + \forest@fornode{\forest@last@node}{% + \forest@node@setalias{forest@last@node}% + \cseappto{forest@nodewalk@saved@dynamic nodes}{\forest@last@node,}% + }% + }, + append/.code={\def\forest@dynamics@copyhow{0}\forest@appto@do@dynamics\forest@append@node{#1}}, + prepend/.code={\def\forest@dynamics@copyhow{0}\forest@appto@do@dynamics\forest@prepend@node{#1}}, + insert after/.code={\def\forest@dynamics@copyhow{0}\forest@appto@do@dynamics\forest@insertafter@node{#1}}, + insert before/.code={\def\forest@dynamics@copyhow{0}\forest@appto@do@dynamics\forest@insertbefore@node{#1}}, + append'/.code={\def\forest@dynamics@copyhow{1}\forest@appto@do@dynamics\forest@append@node{#1}}, + prepend'/.code={\def\forest@dynamics@copyhow{1}\forest@appto@do@dynamics\forest@prepend@node{#1}}, + insert after'/.code={\def\forest@dynamics@copyhow{1}\forest@appto@do@dynamics\forest@insertafter@node{#1}}, + insert before'/.code={\def\forest@dynamics@copyhow{1}\forest@appto@do@dynamics\forest@insertbefore@node{#1}}, + append''/.code={\def\forest@dynamics@copyhow{2}\forest@appto@do@dynamics\forest@append@node{#1}}, + prepend''/.code={\def\forest@dynamics@copyhow{2}\forest@appto@do@dynamics\forest@prepend@node{#1}}, + insert after''/.code={\def\forest@dynamics@copyhow{2}\forest@appto@do@dynamics\forest@insertafter@node{#1}}, + insert before''/.code={\def\forest@dynamics@copyhow{2}\forest@appto@do@dynamics\forest@insertbefore@node{#1}}, + remove/.code={% + \pgfkeysalso{alias=forest@last@node}% + \cseappto{forest@nodewalk@saved@dynamic nodes}{\forest@cn,}% + \expandafter\apptotoks\expandafter\forest@do@dynamics\expandafter{% + \expandafter\forest@remove@node\expandafter{\forest@cn}}% + }, + set root/.code={% + \def\forest@dynamics@copyhow{0}% + \forest@appto@do@dynamics\forest@set@root{#1}% + }, + replace by/.code={\forest@replaceby@code{#1}{insert after}}, + replace by'/.code={\forest@replaceby@code{#1}{insert after'}}, + replace by''/.code={\forest@replaceby@code{#1}{insert after''}}, + sort/.code={% + \eapptotoks\forest@do@dynamics{% + \noexpand\forest@nodesort + \noexpand\forest@sort@ascending + {\forest@cn}% + {\expandonce{\forest@nodesort@by}}% + }% + }, + sort'/.code={% + \eapptotoks\forest@do@dynamics{% + \noexpand\forest@nodesort + \noexpand\forest@sort@descending + {\forest@cn}% + {\expandonce{\forest@nodesort@by}}% + }% + }, + sort by/.store in=\forest@nodesort@by, +} +\def\forest@replaceby@code#1#2{%#1=node spec,#2=insert after[']['] + \ifnum\forestove{@parent}=0 + \cseappto{forest@nodewalk@saved@dynamic nodes}{\forest@cn,}% + \pgfkeysalso{alias=forest@last@node,set root={#1}}% + \else + \cseappto{forest@nodewalk@saved@dynamic nodes}{\forest@cn,}% + \pgfkeysalso{alias=forest@last@node,#2={#1}}% + \eapptotoks\forest@do@dynamics{% + \noexpand\ifnum\noexpand\forestOve{\forest@cn}{@parent}=\forestove{@parent} + \noexpand\forest@remove@node{\forest@cn}% + \noexpand\fi + }% + \fi +} +\def\forest@nodesort#1#2#3{% #1 = direction, #2 = parent node, #3 = sort key + \ifforestdebugdynamics\forestdebug@dynamics{before sorting children of #2}\fi + \def\forest@nodesort@sortkey{#3}% + \forest@fornode{#2}{\forest@nodesort@#1}% + \ifforestdebugdynamics\forestdebug@dynamics{after sorting children of #2}\fi +} +\def\forest@nodesort@#1{% + % prepare the array of child ids + \c@pgf@counta=0 + \forestoget{@first}\forest@nodesort@id + \forest@loop + \ifnum\forest@nodesort@id>0 + \advance\c@pgf@counta 1 + \csedef{forest@nodesort@\the\c@pgf@counta}{\forest@nodesort@id}% + \forestOget{\forest@nodesort@id}{@next}\forest@nodesort@id + \forest@repeat + % sort + \forestoget{n children}\forest@nodesort@n + \forest@sort\forest@nodesort@cmpnodes\forest@nodesort@let#1{1}{\forest@nodesort@n}% + % remove all children + \forestoget{@first}\forest@nodesort@id + \forest@loop + \ifnum\forest@nodesort@id>0 + \forest@node@Remove{\forest@nodesort@id}% + \forestoget{@first}\forest@nodesort@id + \forest@repeat + % insert the children in new order + \c@pgf@counta=0 + \forest@loop + \ifnum\c@pgf@counta<\forest@nodesort@n\relax + \advance\c@pgf@counta 1 + \edef\temp{\csname forest@nodesort@\the\c@pgf@counta\endcsname}% + \forest@node@append{\csname forest@nodesort@\the\c@pgf@counta\endcsname}% + \forest@repeat +} +\def\forest@nodesort@cmpnodes#1#2{% + \global\let\forest@nodesort@cmpresult\forest@sort@cmp@eq + \foreach \forest@temp@pgfmath in \forest@nodesort@sortkey {% + \forest@fornode{\csname forest@nodesort@#1\endcsname}{% + \pgfmathparse{\forest@temp@pgfmath}\global\let\forest@global@tempa\pgfmathresult}% + \forest@fornode{\csname forest@nodesort@#2\endcsname}{% + \pgfmathparse{\forest@temp@pgfmath}\global\let\forest@global@tempb\pgfmathresult}% + \ifdim\forest@global@tempa pt<\forest@global@tempb pt + \global\let\forest@nodesort@cmpresult\forest@sort@cmp@lt + \breakforeach + \else + \ifdim\forest@global@tempa pt>\forest@global@tempb pt + \global\let\forest@nodesort@cmpresult\forest@sort@cmp@gt + \breakforeach + \fi + \fi + }% + \forest@nodesort@cmpresult +} +\def\forest@nodesort@let#1#2{% + \csletcs{forest@nodesort@#1}{forest@nodesort@#2}% +} +\forestset{ + define long step={last dynamic node}{style,must start at valid node=false}{% + name=forest@last@node + } +} +\def\forest@root{0} + %%% begin listing region: stages +\forestset{ + stages/.style={ + for root'={ + process keylist register=default preamble, + process keylist register=preamble + }, + process keylist=given options, + process keylist=before typesetting nodes, + typeset nodes stage, + process keylist=before packing, + pack stage, + process keylist=before computing xy, + compute xy stage, + process keylist=before drawing tree, + draw tree stage + }, + typeset nodes stage/.style={for root'=typeset nodes}, + pack stage/.style={for root'=pack}, + compute xy stage/.style={for root'=compute xy}, + draw tree stage/.style={for root'=draw tree}, +} + %%% end listing region: stages +\forestset{ + process keylist/.code={% + \forest@process@hook@keylist{#1}{#1 processing order/.try,processing order/.lastretry}}, + process keylist'/.code 2 args={\forest@process@hook@keylist@nodynamics{#1}{#2}}, + process keylist''/.code 2 args={\forest@process@hook@keylist@{#1}{#2}}, + process keylist register/.code={\forest@process@keylist@register{#1}}, + process delayed/.code={% + \forest@havedelayedoptions{@delay}{#1}% + \ifforest@havedelayedoptions + \forest@process@hook@keylist@nodynamics{@delay}{#1}% + \fi + }, + do dynamics/.code={% + \the\forest@do@dynamics + \forest@do@dynamics{}% + \forest@node@Compute@numeric@ts@info{\forest@root}% + }, + declare keylist={given options}{}, + declare keylist={before typesetting nodes}{}, + declare keylist={before packing}{}, + declare keylist={before packing node}{}, + declare keylist={after packing node}{}, + declare keylist={before computing xy}{}, + declare keylist={before drawing tree}{}, + declare keylist={delay}{}, + delay n/.style 2 args={if={#1==0}{#2}{delay@n={#1}{#2}}}, + delay@n/.style 2 args={ + if={#1==1}{delay={#2}}{delay={delay@n/.process args={P}{#1-1}{#2}}} + }, + if have delayed/.style 2 args={if have delayed'={processing order}{#1}{#2}}, + if have delayed'/.code n args=3{% + \forest@havedelayedoptionsfalse + \forest@forthis{% + \forest@nodewalk{#1}{% + TeX={% + \forestoget{delay}\forest@temp@delayed + \ifdefempty\forest@temp@delayed{}{\forest@havedelayedoptionstrue}% + }% + }% + }% + \ifforest@havedelayedoptions\pgfkeysalso{#2}\else\pgfkeysalso{#3}\fi + }, + typeset nodes/.code={% + \forest@drawtree@preservenodeboxes@false + \forest@nodewalk + {typeset nodes processing order/.try,processing order/.lastretry}% + {TeX={\forest@node@typeset}}% + }, + typeset nodes'/.code={% + \forest@drawtree@preservenodeboxes@true + \forest@nodewalk + {typeset nodes processing order/.try,processing order/.lastretry}% + {TeX={\forest@node@typeset}}% + }, + typeset node/.code={% + \forest@drawtree@preservenodeboxes@false + \forest@node@typeset + }, + pack/.code={\forest@pack}, + pack'/.code={\forest@pack@onlythisnode}, + compute xy/.code={\forest@node@computeabsolutepositions}, + draw tree box/.store in=\forest@drawtreebox, + draw tree box, + draw tree/.code={% + \forest@drawtree@preservenodeboxes@false + \forest@node@drawtree + }, + draw tree'/.code={% + \forest@drawtree@preservenodeboxes@true + \forest@node@drawtree + }, + %%% begin listing region: draw_tree_method + draw tree method/.style={ + for nodewalk={ + draw tree nodes processing order/.try, + draw tree processing order/.retry, + processing order/.lastretry + }{draw tree node}, + for nodewalk={ + draw tree edges processing order/.try, + draw tree processing order/.retry, + processing order/.lastretry + }{draw tree edge}, + for nodewalk={ + draw tree tikz processing order/.try, + draw tree processing order/.retry, + processing order/.lastretry + }{draw tree tikz} + }, + %%% end listing region: draw_tree_method + draw tree node/.code={\forest@draw@node}, + draw tree node'/.code={\forest@draw@node@}, + if node drawn/.code n args={3}{% + \forest@forthis{% + \forest@configured@nodewalk{independent}{inherited}{fake}{#1}{}% + \ifnum\forest@cn=0 + \forest@tempfalse + \else + \ifcsdef{forest@drawn@\forest@cn}{\forest@temptrue}{\forest@tempfalse}% + \fi + }% + \ifforest@temp\pgfkeysalso{#2}\else\pgfkeysalso{#3}\fi + }, + draw tree edge/.code={\forest@draw@edge}, + draw tree edge'/.code={\forest@draw@edge@}, + draw tree tikz/.code={\forest@draw@tikz@}, % always! + draw tree tikz'/.code={\forest@draw@tikz@}, + processing order/.nodewalk style={tree}, + %given options processing order/.style={processing order}, + %before typesetting nodes processing order/.style={processing order}, + %before packing processing order/.style={processing order}, + %before computing xy processing order/.style={processing order}, + %before drawing tree processing order/.style={processing order}, +} +\newtoks\forest@do@dynamics +\newif\ifforest@havedelayedoptions +\def\forest@process@hook@keylist#1#2{%,#1=keylist,#2=processing order nodewalk + \safeloop + \forest@fornode{\forest@root}{\forest@process@hook@keylist@{#1}{#2}}% + \expandafter\ifstrempty\expandafter{\the\forest@do@dynamics}{}{% + \the\forest@do@dynamics + \forest@do@dynamics={}% + \forest@node@Compute@numeric@ts@info{\forest@root}% + }% + \forest@fornode{\forest@root}{\forest@havedelayedoptions{#1}{#2}}% + \ifforest@havedelayedoptions + \saferepeat +} +\def\forest@process@hook@keylist@nodynamics#1#2{%#1=keylist,#2=processing order nodewalk + % note: this macro works on (nodewalk starting at) the current node + \safeloop + \forest@forthis{\forest@process@hook@keylist@{#1}{#2}}% + \forest@havedelayedoptions{#1}{#2}% + \ifforest@havedelayedoptions + \saferepeat +} +\def\forest@process@hook@keylist@#1#2{%#1=keylist,#2=processing order nodewalk + \forest@nodewalk{#2}{% + TeX={% + \forestoget{#1}\forest@temp@keys + \ifdefvoid\forest@temp@keys{}{% + \forestoset{#1}{}% + \expandafter\forestset\expandafter{\forest@temp@keys}% + }% + }% + }% +} +\def\forest@process@keylist@register#1{% + \edef\forest@marshal{% + \noexpand\forestset{\forestregister{#1}}% + }\forest@marshal +} +\def\forest@havedelayedoptions#1#2{%#1 = keylist, #2=nodewalk + \forest@havedelayedoptionsfalse + \forest@forthis{% + \forest@nodewalk{#2}{% + TeX={% + \forestoget{delay}\forest@temp@delayed + \ifdefempty\forest@temp@delayed{}{\forest@havedelayedoptionstrue}% + \forestolet{#1}\forest@temp@delayed + \forestoset{delay}{}% + }% + }% + }% +} +\def\forest@node@typeset{% + \let\forest@next\forest@node@typeset@ + \forestoifdefined{@box}{% + \forestoget{@box}\forest@temp + \ifdefempty\forest@temp{% + \locbox\forest@temp@box + \forestolet{@box}\forest@temp@box + }{% + \ifforest@drawtree@preservenodeboxes@ + \let\forest@next\relax + \fi + }% + }{% + \locbox\forest@temp@box + \forestolet{@box}\forest@temp@box + }% + \def\forest@node@typeset@restore{}% + \ifdefined\ifsa@tikz\forest@standalone@hack\fi + \forest@next + \forest@node@typeset@restore +} +\def\forest@standalone@hack{% + \ifsa@tikz + \let\forest@standalone@tikzpicture\tikzpicture + \let\forest@standalone@endtikzpicture\endtikzpicture + \let\tikzpicture\sa@orig@tikzpicture + \let\endtikzpicture\sa@orig@endtikzpicture + \def\forest@node@typeset@restore{% + \let\tikzpicture\forest@standalone@tikzpicture + \let\endtikzpicture\forest@standalone@endtikzpicture + }% + \fi +} +\newbox\forest@box +\def\forest@pgf@notyetpositioned{not yet positionedPGFINTERNAL} +\def\forest@node@typeset@{% + \forestanchortotikzanchor{anchor}\forest@temp + \edef\forest@marshal{% + \noexpand\forestolet{anchor}\noexpand\forest@temp + \noexpand\forest@node@typeset@@ + \noexpand\forestoset{anchor}{\forestov{anchor}}% + }\forest@marshal +} +\def\forest@node@typeset@@{% + \forestoget{name}\forest@nodename + \edef\forest@temp@nodeformat{\forestove{node format}}% + \gdef\forest@smuggle{}% + \setbox0=\hbox{% + \begin{tikzpicture}[% + /forest/copy command key={/tikz/anchor}{/tikz/forest@orig@anchor}, + anchor/.style={% + /forest/TeX={\forestanchortotikzanchor{##1}\forest@temp@anchor}, + forest@orig@anchor/.expand once=\forest@temp@anchor + }] + \pgfpositionnodelater{\forest@positionnodelater@save}% + \forest@temp@nodeformat + \pgfinterruptpath + \pgfpointanchor{\forest@pgf@notyetpositioned\forest@nodename}{forestcomputenodeboundary}% + \endpgfinterruptpath + \end{tikzpicture}% + }% + \setbox\forestove{@box}=\box\forest@box % smuggle the box + \forestolet{@boundary}\forest@global@boundary + \forest@smuggle % ... and the rest +} + +\forestset{ + declare readonly dimen={min x}{0pt}, + declare readonly dimen={min y}{0pt}, + declare readonly dimen={max x}{0pt}, + declare readonly dimen={max y}{0pt}, +} +\def\forest@patch@enormouscoordinateboxbounds@plus#1{% + \expandafter\ifstrequal\expandafter{#1}{16000.0pt}{\edef#1{0.0\pgfmath@pt}}{}% +} +\def\forest@patch@enormouscoordinateboxbounds@minus#1{% + \expandafter\ifstrequal\expandafter{#1}{-16000.0pt}{\edef#1{0.0\pgfmath@pt}}{}% +} +\def\forest@positionnodelater@save{% + \global\setbox\forest@box=\box\pgfpositionnodelaterbox + \xappto\forest@smuggle{\noexpand\forestoset{later@name}{\pgfpositionnodelatername}}% + % a bug in pgf? ---well, here's a patch + \forest@patch@enormouscoordinateboxbounds@plus\pgfpositionnodelaterminx + \forest@patch@enormouscoordinateboxbounds@plus\pgfpositionnodelaterminy + \forest@patch@enormouscoordinateboxbounds@minus\pgfpositionnodelatermaxx + \forest@patch@enormouscoordinateboxbounds@minus\pgfpositionnodelatermaxy + % end of patch + \xappto\forest@smuggle{\noexpand\forestoset{min x}{\pgfpositionnodelaterminx}}% + \xappto\forest@smuggle{\noexpand\forestoset{min y}{\pgfpositionnodelaterminy}}% + \xappto\forest@smuggle{\noexpand\forestoset{max x}{\pgfpositionnodelatermaxx}}% + \xappto\forest@smuggle{\noexpand\forestoset{max y}{\pgfpositionnodelatermaxy}}% +} +\def\forest@node@forest@positionnodelater@restore{% + \ifforest@drawtree@preservenodeboxes@ + \let\forest@boxorcopy\copy + \else + \let\forest@boxorcopy\box + \fi + \forestoget{@box}\forest@temp + \setbox\pgfpositionnodelaterbox=\forest@boxorcopy\forest@temp + \edef\pgfpositionnodelatername{\forestove{later@name}}% + \edef\pgfpositionnodelaterminx{\forestove{min x}}% + \edef\pgfpositionnodelaterminy{\forestove{min y}}% + \edef\pgfpositionnodelatermaxx{\forestove{max x}}% + \edef\pgfpositionnodelatermaxy{\forestove{max y}}% + \ifforest@drawtree@preservenodeboxes@ + \else + \forestoset{@box}{}% + \fi +} +\def\forest@pack{% + \pgfsyssoftpath@getcurrentpath\forest@pack@original@path + \forest@pack@computetiers + \forest@pack@computegrowthuniformity + \forest@@pack + \pgfsyssoftpath@setcurrentpath\forest@pack@original@path +} +\def\forest@@pack{% + \ifnum\forestove{uniform growth}>0 + \ifnum\forestove{n children}>0 + \forest@pack@level@uniform + \forest@pack@aligntiers@ofsubtree + \forest@pack@sibling@uniform@recursive + \fi + \else + \forest@node@foreachchild{\forest@@pack}% + \forest@process@hook@keylist@nodynamics{before packing node}{current}% + \ifnum\forestove{n children}>0 + \forest@pack@level@nonuniform + \forest@pack@aligntiers + \forest@pack@sibling@uniform@applyreversed + \fi + \forestoget{after packing node}\forest@temp@keys + \forest@process@hook@keylist@nodynamics{after packing node}{current}% + \fi +} +\def\forest@pack@onlythisnode{% + \ifnum\forestove{n children}>0 + \forest@pack@computetiers + \forest@pack@level@nonuniform + \forest@pack@aligntiers + \forest@node@foreachchild{\forestoset{s}{0\pgfmath@pt}}% + \forest@pack@sibling@uniform@applyreversed + \fi +} +\def\forest@pack@computegrowthuniformity{% + \forest@node@foreachchild{\forest@pack@computegrowthuniformity}% + \edef\forest@pack@cgu@uniformity{% + \ifnum\forestove{n children}=0 + 2\else 1\fi + }% + \forestoget{grow}\forest@pack@cgu@parentgrow + \forest@node@foreachchild{% + \ifnum\forestove{uniform growth}=0 + \def\forest@pack@cgu@uniformity{0}% + \else + \ifnum\forestove{uniform growth}=1 + \ifnum\forestove{grow}=\forest@pack@cgu@parentgrow\relax\else + \def\forest@pack@cgu@uniformity{0}% + \fi + \fi + \fi + }% + \forestoget{before packing node}\forest@temp@a + \forestoget{after packing node}\forest@temp@b + \expandafter\expandafter\expandafter\ifstrempty\expandafter\expandafter\expandafter{\expandafter\forest@temp@a\forest@temp@b}{% + \forestolet{uniform growth}\forest@pack@cgu@uniformity + }{% + \forestoset{uniform growth}{0}% + }% +} +\def\forest@pack@level@uniform{% + \let\forest@plu@minchildl\relax + \forestoget{grow}\forest@plu@grow + \forest@node@foreachchild{% + \forest@node@getboundingrectangle@ls{\forest@plu@grow}% + \advance\pgf@xa\forestove{l}\relax + \ifx\forest@plu@minchildl\relax + \edef\forest@plu@minchildl{\the\pgf@xa}% + \else + \ifdim\pgf@xa<\forest@plu@minchildl\relax + \edef\forest@plu@minchildl{\the\pgf@xa}% + \fi + \fi + }% + \forest@node@getboundingrectangle@ls{\forest@plu@grow}% + \pgfutil@tempdima=\pgf@xb\relax + \advance\pgfutil@tempdima -\forest@plu@minchildl\relax + \advance\pgfutil@tempdima \forestove{l sep}\relax + \ifdim\pgfutil@tempdima>0pt + \forest@node@foreachchild{% + \forestoeset{l}{\the\dimexpr\forestove{l}+\the\pgfutil@tempdima}% + }% + \fi + \forest@node@foreachchild{% + \ifnum\forestove{n children}>0 + \forest@pack@level@uniform + \fi + }% +} +\def\forest@pack@level@nonuniform{% + \let\forest@plu@minchildl\relax + \forestoget{grow}\forest@plu@grow + \forest@node@foreachchild{% + \forest@node@getedge{negative}{\forest@plu@grow}{\forest@plnu@negativechildedge}% + \forest@node@getedge{positive}{\forest@plu@grow}{\forest@plnu@positivechildedge}% + \def\forest@plnu@childedge{\forest@plnu@negativechildedge\forest@plnu@positivechildedge}% + \forest@path@getboundingrectangle@ls\forest@plnu@childedge{\forest@plu@grow}% + \advance\pgf@xa\forestove{l}\relax + \ifx\forest@plu@minchildl\relax + \edef\forest@plu@minchildl{\the\pgf@xa}% + \else + \ifdim\pgf@xa<\forest@plu@minchildl\relax + \edef\forest@plu@minchildl{\the\pgf@xa}% + \fi + \fi + }% + \forest@node@getboundingrectangle@ls{\forest@plu@grow}% + \pgfutil@tempdima=\pgf@xb\relax + \advance\pgfutil@tempdima -\forest@plu@minchildl\relax + \advance\pgfutil@tempdima \forestove{l sep}\relax + \ifdim\pgfutil@tempdima>0pt + \forest@node@foreachchild{% + \forestoeset{l}{\the\dimexpr\the\pgfutil@tempdima+\forestove{l}}% + }% + \fi +} +\def\forest@pack@aligntiers{% + \forestoget{grow}\forest@temp@parentgrow + \forestoget{@tiers}\forest@temp@tiers + \forlistloop\forest@pack@aligntier@\forest@temp@tiers +} +\def\forest@pack@aligntiers@ofsubtree{% + \forest@node@foreach{\forest@pack@aligntiers}% +} +\def\forest@pack@aligntiers@computeabsl{% + \forestoleto{abs@l}{l}% + \forest@node@foreachdescendant{\forest@pack@aligntiers@computeabsl@}% +} +\def\forest@pack@aligntiers@computeabsl@{% + \forestoeset{abs@l}{\the\dimexpr\forestove{l}+\forestOve{\forestove{@parent}}{abs@l}}% +} +\def\forest@pack@aligntier@#1{% + \forest@pack@aligntiers@computeabsl + \pgfutil@tempdima=-\maxdimen\relax + \def\forest@temp@currenttier{#1}% + \forest@node@foreach{% + \forestoget{tier}\forest@temp@tier + \ifx\forest@temp@currenttier\forest@temp@tier + \ifdim\pgfutil@tempdima<\forestove{abs@l}\relax + \pgfutil@tempdima=\forestove{abs@l}\relax + \fi + \fi + }% + \ifdim\pgfutil@tempdima=-\maxdimen\relax\else + \forest@node@foreach{% + \forestoget{tier}\forest@temp@tier + \ifx\forest@temp@currenttier\forest@temp@tier + \forestoeset{l}{\the\dimexpr\pgfutil@tempdima-\forestove{abs@l}+\forestove{l}}% + \fi + }% + \fi +} +\def\forest@pack@sibling@uniform@recursive{% + \forest@node@foreachchild{\forest@pack@sibling@uniform@recursive}% + \forest@pack@sibling@uniform@applyreversed +} +\def\forest@pack@sibling@uniform@applyreversed{% + \ifnum\forestove{n children}>1 + \ifnum\forestove{reversed}=0 + \forest@pack@sibling@uniform@main{first}{last}{next}{previous}% + \else + \forest@pack@sibling@uniform@main{last}{first}{previous}{next}% + \fi + \else + \ifnum\forestove{n children}=1 + \csname forest@calign@\forestove{calign}\endcsname + \fi + \fi +} +\def\forest@pack@sibling@uniform@main#1#2#3#4{% + \forestoget{@#1}\forest@child + \edef\forest@marshal{% + \noexpand\forest@fornode{\forestove{@#1}}{% + \noexpand\forest@node@getedge + {positive}% + {\forestove{grow}}% + \noexpand\forest@temp@edge + }% + }\forest@marshal + \forest@pack@pgfpoint@childsposition\forest@child + \let\forest@previous@positive@edge\pgfutil@empty + \forest@extendpath\forest@previous@positive@edge\forest@temp@edge{}% + \forestOget{\forest@child}{@#3}\forest@child + \edef\forest@previous@child@s{0\pgfmath@pt}% + \safeloop + \unless\ifnum\forest@child=0 + \edef\forest@temp{% + \noexpand\forest@fornode{\forest@child}{% + \noexpand\forest@node@getedge + {negative}% + {\forestove{grow}}% + \noexpand\forest@temp@edge + }% + }\forest@temp + \forest@pack@pgfpoint@childsposition\forest@child + \let\forest@child@negative@edge\pgfutil@empty + \forest@extendpath\forest@child@negative@edge\forest@temp@edge{}% + \forest@setupgrowline{\forestove{grow}}% + \forest@distance@between@edge@paths\forest@previous@positive@edge\forest@child@negative@edge\forest@csdistance + \ifx\forest@csdistance\relax + %\forestOeset{\forest@child}{s}{\forest@previous@child@s}% + \else + \advance\pgfutil@tempdimb-\forest@csdistance\relax + \advance\pgfutil@tempdimb\forestove{s sep}\relax + \forestOeset{\forest@child}{s}{\the\dimexpr\forestOve{\forest@child}{s}-\forest@csdistance+\forestove{s sep}}% + \fi + \ifdim\forestOve{\forest@child}{s}<\forest@previous@child@s\relax + \forestOeset{\forest@child}{s}{\forest@previous@child@s}% + \fi + \forestOget{\forest@child}{s}\forest@child@s + \edef\forest@previous@child@s{\forest@child@s}% + \edef\forest@temp{% + \noexpand\forest@fornode{\forest@child}{% + \noexpand\forest@node@getedge + {positive}% + {\forestove{grow}}% + \noexpand\forest@temp@edge + }% + }\forest@temp + \forest@pack@pgfpoint@childsposition\forest@child + \forest@extendpath\forest@previous@positive@edge\forest@temp@edge{}% + \forest@getpositivetightedgeofpath\forest@previous@positive@edge\forest@previous@positive@edge + \forestOget{\forest@child}{@#3}\forest@child + \saferepeat + \csname forest@calign@\forestove{calign}\endcsname +} +\def\forest@pack@pgfpoint@childsposition#1{% + {% + \pgftransformreset + \pgftransformrotate{\forestove{grow}}% + \forest@fornode{#1}{% + \pgfpointtransformed{\pgfqpoint{\forestove{l}}{\forestove{s}}}% + }% + }% +} +\def\forest@pack@pgfpoint@positioningrow#1{% + {% + \pgftransformreset + \pgftransformrotate{#1}% + \pgfpointtransformed{\pgfqpoint{\forestove{l}}{\forestove{s}}}% + }% +} +\def\forest@calign@s@shift#1{% + \pgfutil@tempdima=\the\dimexpr\forestove{calign xshift}+#1\relax + \forest@node@foreachchild{% + \forestoeset{s}{\the\dimexpr\forestove{s}+\pgfutil@tempdima}% + }% +} +\def\forest@calign@child{% + \forest@calign@s@shift{-\forestOve{\forest@node@nornbarthchildid{\forestove{calign primary child}}}{s}}% +} +\csdef{forest@calign@child edge}{% + {% + \edef\forest@temp@child{\forest@node@nornbarthchildid{\forestove{calign primary child}}}% + \pgftransformreset + \pgftransformrotate{\forestove{grow}}% + \pgfpointtransformed{\pgfqpoint{\forestOve{\forest@temp@child}{l}}{\forestOve{\forest@temp@child}{s}}}% + \pgf@xa=\pgf@x\relax\pgf@ya=\pgf@y\relax + \forest@Pointanchor{\forest@temp@child}{child anchor}% + \advance\pgf@xa\pgf@x\relax\advance\pgf@ya\pgf@y\relax + \forest@pointanchor{parent anchor}% + \advance\pgf@xa-\pgf@x\relax\advance\pgf@ya-\pgf@y\relax + \edef\forest@marshal{% + \noexpand\pgftransformreset + \noexpand\pgftransformrotate{-\forestove{grow}}% + \noexpand\pgfpointtransformed{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}% + }\forest@marshal + }% + \forest@calign@s@shift{\the\dimexpr-\the\pgf@y}% +} +\csdef{forest@calign@midpoint}{% + \forest@calign@s@shift{\the\dimexpr 0pt -% + (\forestOve{\forest@node@nornbarthchildid{\forestove{calign primary child}}}{s}% + +\forestOve{\forest@node@nornbarthchildid{\forestove{calign secondary child}}}{s}% + )/2\relax + }% +} +\csdef{forest@calign@edge midpoint}{% + {% + \edef\forest@temp@firstchild{\forest@node@nornbarthchildid{\forestove{calign primary child}}}% + \edef\forest@temp@secondchild{\forest@node@nornbarthchildid{\forestove{calign secondary child}}}% + \pgftransformreset + \pgftransformrotate{\forestove{grow}}% + \pgfpointtransformed{\pgfqpoint{\forestOve{\forest@temp@firstchild}{l}}{\forestOve{\forest@temp@firstchild}{s}}}% + \pgf@xa=\pgf@x\relax\pgf@ya=\pgf@y\relax + \forest@Pointanchor{\forest@temp@firstchild}{child anchor}% + \advance\pgf@xa\pgf@x\relax\advance\pgf@ya\pgf@y\relax + \edef\forest@marshal{% + \noexpand\pgfpointtransformed{\noexpand\pgfqpoint{\forestOve{\forest@temp@secondchild}{l}}{\forestOve{\forest@temp@secondchild}{s}}}% + }\forest@marshal + \advance\pgf@xa\pgf@x\relax\advance\pgf@ya\pgf@y\relax + \forest@Pointanchor{\forest@temp@secondchild}{child anchor}% + \advance\pgf@xa\pgf@x\relax\advance\pgf@ya\pgf@y\relax + \divide\pgf@xa2 \divide\pgf@ya2 + \forest@pointanchor{parent anchor}% + \advance\pgf@xa-\pgf@x\relax\advance\pgf@ya-\pgf@y\relax + \edef\forest@marshal{% + \noexpand\pgftransformreset + \noexpand\pgftransformrotate{-\forestove{grow}}% + \noexpand\pgfpointtransformed{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}% + }\forest@marshal + }% + \forest@calign@s@shift{\the\dimexpr-\the\pgf@y}% +} +\csdef{forest@calign@fixed angles}{% + \ifnum\forestove{n children}>1 + \edef\forest@ca@first@child{\forest@node@nornbarthchildid{\forestove{calign primary child}}}% + \edef\forest@ca@second@child{\forest@node@nornbarthchildid{\forestove{calign secondary child}}}% + \ifnum\forestove{reversed}=1 + \let\forest@temp\forest@ca@first@child + \let\forest@ca@first@child\forest@ca@second@child + \let\forest@ca@second@child\forest@temp + \fi + \forestOget{\forest@ca@first@child}{l}\forest@ca@first@l + \forestOget{\forest@ca@second@child}{l}\forest@ca@second@l + \pgfmathsetlengthmacro\forest@ca@desired@s@distance{% + tan(\forestove{calign secondary angle})*\forest@ca@second@l + -tan(\forestove{calign primary angle})*\forest@ca@first@l + }% + \forestOget{\forest@ca@first@child}{s}\forest@ca@first@s + \forestOget{\forest@ca@second@child}{s}\forest@ca@second@s + \pgfmathsetlengthmacro\forest@ca@actual@s@distance{% + \forest@ca@second@s-\forest@ca@first@s}% + \ifdim\forest@ca@desired@s@distance>\forest@ca@actual@s@distance\relax + \ifdim\forest@ca@actual@s@distance=0pt + \pgfmathsetlength\pgfutil@tempdima{tan(\forestove{calign primary angle})*\forest@ca@second@l}% + \pgfmathsetlength\pgfutil@tempdimb{\forest@ca@desired@s@distance/(\forestove{n children}-1)}% + \forest@node@foreachchild{% + \forestoeset{s}{\the\pgfutil@tempdima}% + \advance\pgfutil@tempdima\pgfutil@tempdimb + }% + \def\forest@calign@anchor{0pt}% + \else + \pgfmathsetmacro\forest@ca@ratio{% + \forest@ca@desired@s@distance/\forest@ca@actual@s@distance}% + \forest@node@foreachchild{% + \pgfmathsetlengthmacro\forest@temp{\forest@ca@ratio*\forestove{s}}% + \forestolet{s}\forest@temp + }% + \pgfmathsetlengthmacro\forest@calign@anchor{% + -tan(\forestove{calign primary angle})*\forest@ca@first@l}% + \fi + \else + \ifdim\forest@ca@desired@s@distance<\forest@ca@actual@s@distance\relax + \pgfmathsetlengthmacro\forest@ca@ratio{% + \forest@ca@actual@s@distance/\forest@ca@desired@s@distance}% + \forest@node@foreachchild{% + \pgfmathsetlengthmacro\forest@temp{\forest@ca@ratio*\forestove{l}}% + \forestolet{l}\forest@temp + }% + \forestOget{\forest@ca@first@child}{l}\forest@ca@first@l + \pgfmathsetlengthmacro\forest@calign@anchor{% + -tan(\forestove{calign primary angle})*\forest@ca@first@l}% + \fi + \fi + \forest@calign@s@shift{-\forest@calign@anchor}% + \fi +} +\csdef{forest@calign@fixed edge angles}{% + \ifnum\forestove{n children}>1 + \edef\forest@ca@first@child{\forest@node@nornbarthchildid{\forestove{calign primary child}}}% + \edef\forest@ca@second@child{\forest@node@nornbarthchildid{\forestove{calign secondary child}}}% + \ifnum\forestove{reversed}=1 + \let\forest@temp\forest@ca@first@child + \let\forest@ca@first@child\forest@ca@second@child + \let\forest@ca@second@child\forest@temp + \fi + \forestOget{\forest@ca@first@child}{l}\forest@ca@first@l + \forestOget{\forest@ca@second@child}{l}\forest@ca@second@l + \forest@pointanchor{parent anchor}% + \edef\forest@ca@parent@anchor@s{\the\pgf@x}% + \edef\forest@ca@parent@anchor@l{\the\pgf@y}% + \forest@Pointanchor{\forest@ca@first@child}{child anchor}% + \edef\forest@ca@first@child@anchor@s{\the\pgf@x}% + \edef\forest@ca@first@child@anchor@l{\the\pgf@y}% + \forest@Pointanchor{\forest@ca@second@child}{child anchor}% + \edef\forest@ca@second@child@anchor@s{\the\pgf@x}% + \edef\forest@ca@second@child@anchor@l{\the\pgf@y}% + \pgfmathsetlengthmacro\forest@ca@desired@second@edge@s{tan(\forestove{calign secondary angle})*% + (\forest@ca@second@l-\forest@ca@second@child@anchor@l+\forest@ca@parent@anchor@l)}% + \pgfmathsetlengthmacro\forest@ca@desired@first@edge@s{tan(\forestove{calign primary angle})*% + (\forest@ca@first@l-\forest@ca@first@child@anchor@l+\forest@ca@parent@anchor@l)} + \pgfmathsetlengthmacro\forest@ca@desired@s@distance{\forest@ca@desired@second@edge@s-\forest@ca@desired@first@edge@s}% + \forestOget{\forest@ca@first@child}{s}\forest@ca@first@s + \forestOget{\forest@ca@second@child}{s}\forest@ca@second@s + \pgfmathsetlengthmacro\forest@ca@actual@s@distance{% + \forest@ca@second@s+\forest@ca@second@child@anchor@s + -\forest@ca@first@s-\forest@ca@first@child@anchor@s}% + \ifdim\forest@ca@desired@s@distance>\forest@ca@actual@s@distance\relax + \ifdim\forest@ca@actual@s@distance=0pt + \forestoget{n children}\forest@temp@n@children + \forest@node@foreachchild{% + \forest@pointanchor{child anchor}% + \edef\forest@temp@child@anchor@s{\the\pgf@x}% + \pgfmathsetlengthmacro\forest@temp{% + \forest@ca@desired@first@edge@s+(\forestove{n}-1)*\forest@ca@desired@s@distance/(\forest@temp@n@children-1)+\forest@ca@first@child@anchor@s-\forest@temp@child@anchor@s}% + \forestolet{s}\forest@temp + }% + \def\forest@calign@anchor{0pt}% + \else + \pgfmathsetmacro\forest@ca@ratio{% + \forest@ca@desired@s@distance/\forest@ca@actual@s@distance}% + \forest@node@foreachchild{% + \forest@pointanchor{child anchor}% + \edef\forest@temp@child@anchor@s{\the\pgf@x}% + \pgfmathsetlengthmacro\forest@temp{% + \forest@ca@ratio*(% + \forestove{s}-\forest@ca@first@s + +\forest@temp@child@anchor@s-\forest@ca@first@child@anchor@s)% + +\forest@ca@first@s + +\forest@ca@first@child@anchor@s-\forest@temp@child@anchor@s}% + \forestolet{s}\forest@temp + }% + \pgfmathsetlengthmacro\forest@calign@anchor{% + -tan(\forestove{calign primary angle})*(\forest@ca@first@l-\forest@ca@first@child@anchor@l+\forest@ca@parent@anchor@l)% + +\forest@ca@first@child@anchor@s-\forest@ca@parent@anchor@s + }% + \fi + \else + \ifdim\forest@ca@desired@s@distance<\forest@ca@actual@s@distance\relax + \pgfmathsetlengthmacro\forest@ca@ratio{% + \forest@ca@actual@s@distance/\forest@ca@desired@s@distance}% + \forest@node@foreachchild{% + \forest@pointanchor{child anchor}% + \edef\forest@temp@child@anchor@l{\the\pgf@y}% + \pgfmathsetlengthmacro\forest@temp{% + \forest@ca@ratio*(% + \forestove{l}+\forest@ca@parent@anchor@l-\forest@temp@child@anchor@l) + -\forest@ca@parent@anchor@l+\forest@temp@child@anchor@l}% + \forestolet{l}\forest@temp + }% + \forestOget{\forest@ca@first@child}{l}\forest@ca@first@l + \pgfmathsetlengthmacro\forest@calign@anchor{% + -tan(\forestove{calign primary angle})*(\forest@ca@first@l+\forest@ca@parent@anchor@l-\forest@temp@child@anchor@l)% + +\forest@ca@first@child@anchor@s-\forest@ca@parent@anchor@s + }% + \fi + \fi + \forest@calign@s@shift{-\forest@calign@anchor}% + \fi +} +\def\forest@node@getedge#1#2#3{% + \forestoget{#1@edge@#2}#3% + \ifx#3\relax + \forest@node@foreachchild{% + \forest@node@getedge{#1}{#2}{\forest@temp@edge}% + }% + \forest@forthis{\forest@node@getedges{#2}}% + \forestoget{#1@edge@#2}#3% + \fi +} +\def\forest@node@getedges#1{% + %{% + \forest@setupgrowline{#1}% + \ifnum\forestove{ignore}=0 + \forestoget{@boundary}\forest@node@boundary + \else + \def\forest@node@boundary{}% + \fi + \csname forest@getboth\forestove{fit}edgesofpath\endcsname + \forest@node@boundary\forest@negative@node@edge\forest@positive@node@edge + \forestolet{negative@edge@#1}\forest@negative@node@edge + \forestolet{positive@edge@#1}\forest@positive@node@edge + \get@edges@merge{negative}{#1}% + \get@edges@merge{positive}{#1}% + %}% +} +\def\get@edges@merge#1#2{% + \ifnum\forestove{n children}>0 + \forestoget{#1@edge@#2}\forest@node@edge + \forest@pointanchor{parent anchor}% + \edef\forest@getedge@pa@l{\the\pgf@x}% + \edef\forest@getedge@pa@s{\the\pgf@y}% + \eappto\forest@node@edge{\noexpand\pgfsyssoftpath@movetotoken{\forest@getedge@pa@l}{\forest@getedge@pa@s}}% + \pgfgettransform\forest@temp@transform + \pgftransformreset + \pgftransformrotate{\forestove{grow}}% + \def\forest@all@edges{}% + \forest@node@foreachchild{% + \forestoget{#1@edge@#2}\forest@temp@edge + \pgfpointtransformed{\pgfqpoint{\forestove{l}}{\forestove{s}}}% + \forest@extendpath\forest@node@edge\forest@temp@edge{}% + \ifnum\forestove{ignore edge}=0 + \pgfpointadd + {\pgfpointtransformed{\pgfqpoint{\forestove{l}}{\forestove{s}}}}% + {\forest@pointanchor{child anchor}}% + \pgfgetlastxy{\forest@getedge@ca@l}{\forest@getedge@ca@s}% + \eappto\forest@all@edges{% + \noexpand\pgfsyssoftpath@movetotoken{\forest@getedge@pa@l}{\forest@getedge@pa@s}% + \noexpand\pgfsyssoftpath@linetotoken{\forest@getedge@ca@l}{\forest@getedge@ca@s}% + }% + % this deals with potential overlap of the edges: + \eappto\forest@node@edge{\noexpand\pgfsyssoftpath@movetotoken{\forest@getedge@ca@l}{\forest@getedge@ca@s}}% + \fi + }% + \ifdefempty{\forest@all@edges}{}{% + \pgfintersectionofpaths{\pgfsetpath\forest@all@edges}{\pgfsetpath\forest@node@edge}% + \def\forest@edgenode@intersections{}% + \forest@merge@intersectionloop + \eappto\forest@node@edge{\expandonce{\forest@all@edges}\expandonce{\forest@edgenode@intersections}}% + }% + \pgfsettransform\forest@temp@transform + \csname forest@get#1\forestove{fit}edgeofpath\endcsname\forest@node@edge\forest@node@edge + \forestolet{#1@edge@#2}\forest@node@edge + \fi +} +\def\forest@merge@intersectionloop{% + \c@pgf@counta=0 + \forest@loop + \ifnum\c@pgf@counta<\pgfintersectionsolutions\relax + \advance\c@pgf@counta1 + \pgfpointintersectionsolution{\the\c@pgf@counta}% + \eappto\forest@edgenode@intersections{\noexpand\pgfsyssoftpath@movetotoken + {\the\pgf@x}{\the\pgf@y}}% + \forest@repeat +} +\def\forest@node@getboundingrectangle@ls#1{% + \forestoget{@boundary}\forest@node@boundary + \forest@path@getboundingrectangle@ls\forest@node@boundary{#1}% +} +\def\forest@pgfpathtransformed#1{% + \forest@save@pgfsyssoftpath@tokendefs + \let\pgfsyssoftpath@movetotoken\forest@pgfpathtransformed@moveto + \let\pgfsyssoftpath@linetotoken\forest@pgfpathtransformed@lineto + \pgfsyssoftpath@setcurrentpath\pgfutil@empty + #1% + \forest@restore@pgfsyssoftpath@tokendefs +} +\def\forest@pgfpathtransformed@moveto#1#2{% + \forest@pgfpathtransformed@op\pgfsyssoftpath@moveto{#1}{#2}% +} +\def\forest@pgfpathtransformed@lineto#1#2{% + \forest@pgfpathtransformed@op\pgfsyssoftpath@lineto{#1}{#2}% +} +\def\forest@pgfpathtransformed@op#1#2#3{% + \pgfpointtransformed{\pgfqpoint{#2}{#3}}% + \edef\forest@temp{% + \noexpand#1{\the\pgf@x}{\the\pgf@y}% + }% + \forest@temp +} +\def\forest@pack@computetiers{% + {% + \forest@pack@tiers@getalltiersinsubtree + \forest@pack@tiers@computetierhierarchy + \forest@pack@tiers@findcontainers + \forest@pack@tiers@raisecontainers + \forest@pack@tiers@computeprocessingorder + \gdef\forest@smuggle{}% + \forest@pack@tiers@write + }% + \forest@node@foreach{\forestoset{@tiers}{}}% + \forest@smuggle +} +\def\forest@pack@tiers@getalltiersinsubtree{% + \ifnum\forestove{n children}>0 + \forest@node@foreachchild{\forest@pack@tiers@getalltiersinsubtree}% + \fi + \forestoget{tier}\forest@temp@mytier + \def\forest@temp@mytiers{}% + \ifdefempty\forest@temp@mytier{}{% + \listeadd\forest@temp@mytiers\forest@temp@mytier + }% + \ifnum\forestove{n children}>0 + \forest@node@foreachchild{% + \forestoget{tiers}\forest@temp@tiers + \forlistloop\forest@pack@tiers@forhandlerA\forest@temp@tiers + }% + \fi + \forestolet{tiers}\forest@temp@mytiers +} +\def\forest@pack@tiers@forhandlerA#1{% + \ifinlist{#1}\forest@temp@mytiers{}{% + \listeadd\forest@temp@mytiers{#1}% + }% +} +\def\forest@pack@tiers@computetierhierarchy{% + \def\forest@tiers@ancestors{}% + \forestoget{tiers}\forest@temp@mytiers + \forlistloop\forest@pack@tiers@cth@init\forest@temp@mytiers + \forest@pack@tiers@computetierhierarchy@ +} +\def\forest@pack@tiers@cth@init#1{% + \csdef{forest@tiers@higher@#1}{}% + \csdef{forest@tiers@lower@#1}{}% +} +\def\forest@pack@tiers@computetierhierarchy@{% + \forestoget{tier}\forest@temp@mytier + \ifdefempty\forest@temp@mytier{}{% + \forlistloop\forest@pack@tiers@forhandlerB\forest@tiers@ancestors + \listeadd\forest@tiers@ancestors\forest@temp@mytier + }% + \forest@node@foreachchild{% + \forest@pack@tiers@computetierhierarchy@ + }% + \forestoget{tier}\forest@temp@mytier + \ifdefempty\forest@temp@mytier{}{% + \forest@listedel\forest@tiers@ancestors\forest@temp@mytier + }% +} +\def\forest@pack@tiers@forhandlerB#1{% + \def\forest@temp@tier{#1}% + \ifx\forest@temp@tier\forest@temp@mytier + \PackageError{forest}{Circular tier hierarchy (tier \forest@temp@mytier)}{}% + \fi + \ifinlistcs{#1}{forest@tiers@higher@\forest@temp@mytier}{}{% + \listcsadd{forest@tiers@higher@\forest@temp@mytier}{#1}}% + \xifinlistcs\forest@temp@mytier{forest@tiers@lower@#1}{}{% + \listcseadd{forest@tiers@lower@#1}{\forest@temp@mytier}}% +} +\def\forest@pack@tiers@findcontainers{% + \forestoget{tiers}\forest@temp@tiers + \forlistloop\forest@pack@tiers@findcontainer\forest@temp@tiers +} +\def\forest@pack@tiers@findcontainer#1{% + \def\forest@temp@tier{#1}% + \forestoget{tier}\forest@temp@mytier + \ifx\forest@temp@tier\forest@temp@mytier + \csedef{forest@tiers@container@#1}{\forest@cn}% + \else\@escapeif{% + \forest@pack@tiers@findcontainerA{#1}% + }\fi% +} +\def\forest@pack@tiers@findcontainerA#1{% + \c@pgf@counta=0 + \forest@node@foreachchild{% + \forestoget{tiers}\forest@temp@tiers + \ifinlist{#1}\forest@temp@tiers{% + \advance\c@pgf@counta 1 + \let\forest@temp@child\forest@cn + }{}% + }% + \ifnum\c@pgf@counta>1 + \csedef{forest@tiers@container@#1}{\forest@cn}% + \else\@escapeif{% surely =1 + \forest@fornode{\forest@temp@child}{% + \forest@pack@tiers@findcontainer{#1}% + }% + }\fi +} +\def\forest@pack@tiers@raisecontainers{% + \forestoget{tiers}\forest@temp@mytiers + \forlistloop\forest@pack@tiers@rc@forhandlerA\forest@temp@mytiers +} +\def\forest@pack@tiers@rc@forhandlerA#1{% + \edef\forest@tiers@temptier{#1}% + \letcs\forest@tiers@containernodeoftier{forest@tiers@container@#1}% + \letcs\forest@temp@lowertiers{forest@tiers@lower@#1}% + \forlistloop\forest@pack@tiers@rc@forhandlerB\forest@temp@lowertiers +} +\def\forest@pack@tiers@rc@forhandlerB#1{% + \letcs\forest@tiers@containernodeoflowertier{forest@tiers@container@#1}% + \forestOget{\forest@tiers@containernodeoflowertier}{content}\lowercontent + \forestOget{\forest@tiers@containernodeoftier}{content}\uppercontent + \forest@fornode{\forest@tiers@containernodeoflowertier}{% + \forest@ifancestorof + {\forest@tiers@containernodeoftier} + {\csletcs{forest@tiers@container@\forest@tiers@temptier}{forest@tiers@container@#1}}% + {}% + }% +} +\def\forest@pack@tiers@computeprocessingorder{% + \def\forest@tiers@processingorder{}% + \forestoget{tiers}\forest@tiers@cpo@tierstodo + \safeloop + \ifdefempty\forest@tiers@cpo@tierstodo{\forest@tempfalse}{\forest@temptrue}% + \ifforest@temp + \def\forest@tiers@cpo@tiersremaining{}% + \def\forest@tiers@cpo@tiersindependent{}% + \forlistloop\forest@pack@tiers@cpo@forhandlerA\forest@tiers@cpo@tierstodo + \ifdefempty\forest@tiers@cpo@tiersindependent{% + \PackageError{forest}{Circular tiers!}{}}{}% + \forlistloop\forest@pack@tiers@cpo@forhandlerB\forest@tiers@cpo@tiersremaining + \let\forest@tiers@cpo@tierstodo\forest@tiers@cpo@tiersremaining + \saferepeat +} +\def\forest@pack@tiers@cpo@forhandlerA#1{% + \ifcsempty{forest@tiers@higher@#1}{% + \listadd\forest@tiers@cpo@tiersindependent{#1}% + \listadd\forest@tiers@processingorder{#1}% + }{% + \listadd\forest@tiers@cpo@tiersremaining{#1}% + }% +} +\def\forest@pack@tiers@cpo@forhandlerB#1{% + \def\forest@pack@tiers@cpo@aremainingtier{#1}% + \forlistloop\forest@pack@tiers@cpo@forhandlerC\forest@tiers@cpo@tiersindependent +} +\def\forest@pack@tiers@cpo@forhandlerC#1{% + \ifinlistcs{#1}{forest@tiers@higher@\forest@pack@tiers@cpo@aremainingtier}{% + \forest@listcsdel{forest@tiers@higher@\forest@pack@tiers@cpo@aremainingtier}{#1}% + }{}% +} +\def\forest@pack@tiers@write{% + \forlistloop\forest@pack@tiers@write@forhandler\forest@tiers@processingorder +} +\def\forest@pack@tiers@write@forhandler#1{% + \forest@fornode{\csname forest@tiers@container@#1\endcsname}{% + \forest@pack@tiers@check{#1}% + }% + \xappto\forest@smuggle{% + \noexpand\listadd + \forestOm{\csname forest@tiers@container@#1\endcsname}{@tiers}% + {#1}% + }% +} + % checks if the tier is compatible with growth changes and calign=node/edge angle +\def\forest@pack@tiers@check#1{% + \def\forest@temp@currenttier{#1}% + \forest@node@foreachdescendant{% + \ifnum\forestove{grow}=\forestOve{\forestove{@parent}}{grow} + \else + \forest@pack@tiers@check@grow + \fi + \ifnum\forestove{n children}>1 + \forestoget{calign}\forest@temp + \ifx\forest@temp\forest@pack@tiers@check@nodeangle + \forest@pack@tiers@check@calign + \fi + \ifx\forest@temp\forest@pack@tiers@check@edgeangle + \forest@pack@tiers@check@calign + \fi + \fi + }% +} +\def\forest@pack@tiers@check@nodeangle{node angle}% +\def\forest@pack@tiers@check@edgeangle{edge angle}% +\def\forest@pack@tiers@check@grow{% + \forestoget{content}\forest@temp@content + \let\forest@temp@currentnode\forest@cn + \forest@node@foreachdescendant{% + \forestoget{tier}\forest@temp + \ifx\forest@temp@currenttier\forest@temp + \forest@pack@tiers@check@grow@error + \fi + }% +} +\def\forest@pack@tiers@check@grow@error{% + \PackageError{forest}{Tree growth direction changes in node \forest@temp@currentnode\space + (content: \forest@temp@content), while tier '\forest@temp' is specified for nodes both + out- and inside the subtree rooted in node \forest@temp@currentnode. This will not work.}{}% +} +\def\forest@pack@tiers@check@calign{% + \forest@node@foreachchild{% + \forestoget{tier}\forest@temp + \ifx\forest@temp@currenttier\forest@temp + \forest@pack@tiers@check@calign@warning + \fi + }% +} +\def\forest@pack@tiers@check@calign@warning{% + \PackageWarning{forest}{Potential option conflict: node \forestove{@parent} (content: + '\forestOve{\forestove{@parent}}{content}') was given 'calign=\forestove{calign}', while its + child \forest@cn\space (content: '\forestove{content}') was given 'tier=\forestove{tier}'. + The parent's 'calign' will only work if the child was the lowest node on its tier before the + alignment.}% +} +\pgfdeclaregenericanchor{forestcomputenodeboundary}{% + \letcs\forest@temp@boundary@macro{forest@compute@node@boundary@#1}% + \ifcsname forest@compute@node@boundary@#1\endcsname + \csname forest@compute@node@boundary@#1\endcsname + \else + \forest@compute@node@boundary@rectangle + \fi + \pgfsyssoftpath@getcurrentpath\forest@temp + \global\let\forest@global@boundary\forest@temp +} +\def\forest@mt#1{% + \expandafter\pgfpointanchor\expandafter{\pgfreferencednodename}{#1}% + \pgfsyssoftpath@moveto{\the\pgf@x}{\the\pgf@y}% +}% +\def\forest@lt#1{% + \expandafter\pgfpointanchor\expandafter{\pgfreferencednodename}{#1}% + \pgfsyssoftpath@lineto{\the\pgf@x}{\the\pgf@y}% +}% +\def\forest@compute@node@boundary@coordinate{% + \forest@mt{center}% +} +\def\forest@compute@node@boundary@circle{% + \forest@mt{east}% + \forest@lt{north east}% + \forest@lt{north}% + \forest@lt{north west}% + \forest@lt{west}% + \forest@lt{south west}% + \forest@lt{south}% + \forest@lt{south east}% + \forest@lt{east}% +} +\def\forest@compute@node@boundary@rectangle{% + \forest@mt{south west}% + \forest@lt{south east}% + \forest@lt{north east}% + \forest@lt{north west}% + \forest@lt{south west}% +} +\def\forest@compute@node@boundary@diamond{% + \forest@mt{east}% + \forest@lt{north}% + \forest@lt{west}% + \forest@lt{south}% + \forest@lt{east}% +} +\let\forest@compute@node@boundary@ellipse\forest@compute@node@boundary@circle +\def\forest@compute@node@boundary@trapezium{% + \forest@mt{top right corner}% + \forest@lt{top left corner}% + \forest@lt{bottom left corner}% + \forest@lt{bottom right corner}% + \forest@lt{top right corner}% +} +\def\forest@compute@node@boundary@semicircle{% + \forest@mt{arc start}% + \forest@lt{north}% + \forest@lt{east}% + \forest@lt{north east}% + \forest@lt{apex}% + \forest@lt{north west}% + \forest@lt{west}% + \forest@lt{arc end}% + \forest@lt{arc start}% +} +\csdef{forest@compute@node@boundary@regular polygon}{% + \forest@mt{corner 1}% + \c@pgf@counta=\sides\relax + \forest@loop + \ifnum\c@pgf@counta>0 + \forest@lt{corner \the\c@pgf@counta}% + \advance\c@pgf@counta-1 + \forest@repeat +}% +\def\forest@compute@node@boundary@star{% + \forest@mt{outer point 1}% + \c@pgf@counta=\totalstarpoints\relax + \divide\c@pgf@counta2 + \forest@loop + \ifnum\c@pgf@counta>0 + \forest@lt{inner point \the\c@pgf@counta}% + \forest@lt{outer point \the\c@pgf@counta}% + \advance\c@pgf@counta-1 + \forest@repeat +}% +\csdef{forest@compute@node@boundary@isosceles triangle}{% + \forest@mt{apex}% + \forest@lt{left corner}% + \forest@lt{right corner}% + \forest@lt{apex}% +} +\def\forest@compute@node@boundary@kite{% + \forest@mt{upper vertex}% + \forest@lt{left vertex}% + \forest@lt{lower vertex}% + \forest@lt{right vertex}% + \forest@lt{upper vertex}% +} +\def\forest@compute@node@boundary@dart{% + \forest@mt{tip}% + \forest@lt{left tail}% + \forest@lt{tail center}% + \forest@lt{right tail}% + \forest@lt{tip}% +} +\csdef{forest@compute@node@boundary@circular sector}{% + \forest@mt{sector center}% + \forest@lt{arc start}% + \forest@lt{arc center}% + \forest@lt{arc end}% + \forest@lt{sector center}% +} +\def\forest@compute@node@boundary@cylinder{% + \forest@mt{top}% + \forest@lt{after top}% + \forest@lt{before bottom}% + \forest@lt{bottom}% + \forest@lt{after bottom}% + \forest@lt{before top}% + \forest@lt{top}% +} +\cslet{forest@compute@node@boundary@forbidden sign}\forest@compute@node@boundary@circle +\cslet{forest@compute@node@boundary@magnifying glass}\forest@compute@node@boundary@circle +\def\forest@compute@node@boundary@cloud{% + \getradii + \forest@mt{puff 1}% + \c@pgf@counta=\puffs\relax + \forest@loop + \ifnum\c@pgf@counta>0 + \forest@lt{puff \the\c@pgf@counta}% + \advance\c@pgf@counta-1 + \forest@repeat +} +\def\forest@compute@node@boundary@starburst{ + \calculatestarburstpoints + \forest@mt{outer point 1}% + \c@pgf@counta=\totalpoints\relax + \divide\c@pgf@counta2 + \forest@loop + \ifnum\c@pgf@counta>0 + \forest@lt{inner point \the\c@pgf@counta}% + \forest@lt{outer point \the\c@pgf@counta}% + \advance\c@pgf@counta-1 + \forest@repeat +}% +\def\forest@compute@node@boundary@signal{% + \forest@mt{east}% + \forest@lt{south east}% + \forest@lt{south west}% + \forest@lt{west}% + \forest@lt{north west}% + \forest@lt{north east}% + \forest@lt{east}% +} +\def\forest@compute@node@boundary@tape{% + \forest@mt{north east}% + \forest@lt{60}% + \forest@lt{north}% + \forest@lt{120}% + \forest@lt{north west}% + \forest@lt{south west}% + \forest@lt{240}% + \forest@lt{south}% + \forest@lt{310}% + \forest@lt{south east}% + \forest@lt{north east}% +} +\csdef{forest@compute@node@boundary@single arrow}{% + \forest@mt{tip}% + \forest@lt{after tip}% + \forest@lt{after head}% + \forest@lt{before tail}% + \forest@lt{after tail}% + \forest@lt{before head}% + \forest@lt{before tip}% + \forest@lt{tip}% +} +\csdef{forest@compute@node@boundary@double arrow}{% + \forest@mt{tip 1}% + \forest@lt{after tip 1}% + \forest@lt{after head 1}% + \forest@lt{before head 2}% + \forest@lt{before tip 2}% + \forest@mt{tip 2}% + \forest@lt{after tip 2}% + \forest@lt{after head 2}% + \forest@lt{before head 1}% + \forest@lt{before tip 1}% + \forest@lt{tip 1}% +} +\csdef{forest@compute@node@boundary@arrow box}{% + \forest@mt{before north arrow}% + \forest@lt{before north arrow head}% + \forest@lt{before north arrow tip}% + \forest@lt{north arrow tip}% + \forest@lt{after north arrow tip}% + \forest@lt{after north arrow head}% + \forest@lt{after north arrow}% + \forest@lt{north east}% + \forest@lt{before east arrow}% + \forest@lt{before east arrow head}% + \forest@lt{before east arrow tip}% + \forest@lt{east arrow tip}% + \forest@lt{after east arrow tip}% + \forest@lt{after east arrow head}% + \forest@lt{after east arrow}% + \forest@lt{south east}% + \forest@lt{before south arrow}% + \forest@lt{before south arrow head}% + \forest@lt{before south arrow tip}% + \forest@lt{south arrow tip}% + \forest@lt{after south arrow tip}% + \forest@lt{after south arrow head}% + \forest@lt{after south arrow}% + \forest@lt{south west}% + \forest@lt{before west arrow}% + \forest@lt{before west arrow head}% + \forest@lt{before west arrow tip}% + \forest@lt{west arrow tip}% + \forest@lt{after west arrow tip}% + \forest@lt{after west arrow head}% + \forest@lt{after west arrow}% + \forest@lt{north west}% + \forest@lt{before north arrow}% +} +\cslet{forest@compute@node@boundary@circle split}\forest@compute@node@boundary@circle +\cslet{forest@compute@node@boundary@circle solidus}\forest@compute@node@boundary@circle +\cslet{forest@compute@node@boundary@ellipse split}\forest@compute@node@boundary@ellipse +\cslet{forest@compute@node@boundary@rectangle split}\forest@compute@node@boundary@rectangle +\def\forest@compute@node@boundary@@callout{% + \beforecalloutpointer + \pgfsyssoftpath@moveto{\the\pgf@x}{\the\pgf@y}% + \calloutpointeranchor + \pgfsyssoftpath@lineto{\the\pgf@x}{\the\pgf@y}% + \aftercalloutpointer + \pgfsyssoftpath@lineto{\the\pgf@x}{\the\pgf@y}% +} +\csdef{forest@compute@node@boundary@rectangle callout}{% + \forest@compute@node@boundary@rectangle + \rectanglecalloutpoints + \forest@compute@node@boundary@@callout +} +\csdef{forest@compute@node@boundary@ellipse callout}{% + \forest@compute@node@boundary@ellipse + \ellipsecalloutpoints + \forest@compute@node@boundary@@callout +} +\csdef{forest@compute@node@boundary@cloud callout}{% + \forest@compute@node@boundary@cloud + % at least a first approx... + \forest@mt{center}% + \forest@lt{pointer}% +}% +\csdef{forest@compute@node@boundary@cross out}{% + \forest@mt{south east}% + \forest@lt{north west}% + \forest@mt{south west}% + \forest@lt{north east}% +}% +\csdef{forest@compute@node@boundary@strike out}{% + \forest@mt{north east}% + \forest@lt{south west}% +}% +\csdef{forest@compute@node@boundary@rounded rectangle}{% + \forest@mt{east}% + \forest@lt{north east}% + \forest@lt{north}% + \forest@lt{north west}% + \forest@lt{west}% + \forest@lt{south west}% + \forest@lt{south}% + \forest@lt{south east}% + \forest@lt{east}% +}% +\csdef{forest@compute@node@boundary@chamfered rectangle}{% + \forest@mt{before south west}% + \forest@mt{after south west}% + \forest@lt{before south east}% + \forest@lt{after south east}% + \forest@lt{before north east}% + \forest@lt{after north east}% + \forest@lt{before north west}% + \forest@lt{after north west}% + \forest@lt{before south west}% +}% +\def\forest@node@computeabsolutepositions{% + \edef\forest@marshal{% + \noexpand\forest@node@foreachchild{% + \noexpand\forest@node@computeabsolutepositions@{\forestove{x}}{\forestove{y}}{\forestove{grow}}% + }% + }\forest@marshal +} +\def\forest@node@computeabsolutepositions@#1#2#3{% + \pgfpointadd{\pgfpoint{#1}{#2}}{% + \pgfpointadd{\pgfpolar{#3}{\forestove{l}}}{\pgfpolar{90 + #3}{\forestove{s}}}}% + \pgfgetlastxy\forest@temp@x\forest@temp@y + \forestolet{x}\forest@temp@x + \forestolet{y}\forest@temp@y + \edef\forest@marshal{% + \noexpand\forest@node@foreachchild{% + \noexpand\forest@node@computeabsolutepositions@{\forest@temp@x}{\forest@temp@y}{\forestove{grow}}% + }% + }\forest@marshal +} +\newif\ifforest@drawtree@preservenodeboxes@ +\def\forest@node@drawtree{% + \expandafter\ifstrequal\expandafter{\forest@drawtreebox}{\pgfkeysnovalue}{% + \let\forest@drawtree@beginbox\relax + \let\forest@drawtree@endbox\relax + }{% + \edef\forest@drawtree@beginbox{\global\setbox\forest@drawtreebox=\hbox\bgroup}% + \let\forest@drawtree@endbox\egroup + }% + \ifforest@external@ + \ifforest@externalize@tree@ + \forest@temptrue + \else + \tikzifexternalizing{% + \ifforest@was@tikzexternalwasenable + \forest@temptrue + \pgfkeys{/tikz/external/optimize=false}% + \let\forest@drawtree@beginbox\relax + \let\forest@drawtree@endbox\relax + \else + \forest@tempfalse + \fi + }{% + \forest@tempfalse + }% + \fi + \ifforest@temp + \advance\forest@externalize@inner@n 1 + \edef\forest@externalize@filename{% + \tikzexternalrealjob-forest-\forest@externalize@outer@n + \ifnum\forest@externalize@inner@n=0 \else.\the\forest@externalize@inner@n\fi}% + \expandafter\tikzsetnextfilename\expandafter{\forest@externalize@filename}% + \tikzexternalenable + \pgfkeysalso{/tikz/external/remake next,/tikz/external/export next}% + \fi + \ifforest@externalize@tree@ + \typeout{forest: Invoking a recursive call to generate the external picture + '\forest@externalize@filename' for the following context+code: + '\expandafter\detokenize\expandafter{\forest@externalize@id}'}% + \fi + \fi + % + \ifforesttikzcshack + \let\forest@original@tikz@parse@node\tikz@parse@node + \let\tikz@parse@node\forest@tikz@parse@node + \fi + \pgfkeysgetvalue{/forest/begin draw/.@cmd}\forest@temp@begindraw + \pgfkeysgetvalue{/forest/end draw/.@cmd}\forest@temp@enddraw + \edef\forest@marshal{% + \noexpand\forest@drawtree@beginbox + \expandonce{\forest@temp@begindraw\pgfkeysnovalue\pgfeov}% + \noexpand\forest@node@drawtree@ + \expandonce{\forest@temp@enddraw\pgfkeysnovalue\pgfeov}% + \noexpand\forest@drawtree@endbox + }\forest@marshal + \ifforesttikzcshack + \let\tikz@parse@node\forest@original@tikz@parse@node + \fi + % + \ifforest@external@ + \ifforest@externalize@tree@ + \tikzexternaldisable + \eappto\forest@externalize@checkimages{% + \noexpand\forest@includeexternal@check{\forest@externalize@filename}% + }% + \expandafter\ifstrequal\expandafter{\forest@drawtreebox}{\pgfkeysnovalue}{% + \eappto\forest@externalize@loadimages{% + \noexpand\forest@includeexternal{\forest@externalize@filename}% + }% + }{% + \eappto\forest@externalize@loadimages{% + \noexpand\forest@includeexternal@box\forest@drawtreebox{\forest@externalize@filename}% + }% + }% + \fi + \fi +} +\def\forest@drawtree@root{0} +\def\forest@node@drawtree@{% + \def\forest@clear@drawn{}% + \forest@forthis{% + \forest@saveandrestoremacro\forest@drawtree@root{% + \edef\forest@drawtree@root{\forest@cn}% + \forestset{draw tree method}% + }% + }% + \forest@node@Ifnamedefined{forest@baseline@node}{% + \edef\forest@baseline@id{\forest@node@Nametoid{forest@baseline@node}}% + \ifcsdef{forest@drawn@\forest@baseline@id}{% + \edef\forest@marshal{% + \noexpand\pgfsetbaselinepointlater{% + \noexpand\pgfpointanchor + {\forestOve{\forest@baseline@id}{name}}% + {\forestOve{\forest@baseline@id}{anchor}}% + }% + }\forest@marshal + }{}% + }{}% + \forest@clear@drawn +} +\def\forest@draw@node{% + \ifnum\forestove{phantom}=0 + \forest@draw@node@ + \fi +} +\def\forest@draw@node@{% + \forest@node@forest@positionnodelater@restore + \ifforest@drawtree@preservenodeboxes@ + \pgfnodealias{forest@temp}{\forestove{later@name}}% + \fi + \pgfpositionnodenow{\pgfqpoint{\forestove{x}}{\forestove{y}}}% + \ifforest@drawtree@preservenodeboxes@ + \pgfnodealias{\forestove{later@name}}{forest@temp}% + \fi + \csdef{forest@drawn@\forest@cn}{}% + \eappto\forest@clear@drawn{\noexpand\csundef{forest@drawn@\forest@cn}}% +} +\def\forest@draw@edge{% + \ifcsdef{forest@drawn@\forest@cn}{% was the current node drawn? + \ifnum\forestove{@parent}=0 % do we have a parent? + \else + \ifcsdef{forest@drawn@\forestove{@parent}}{% was the parent drawn? + \forest@draw@edge@ + }{}% + \fi + }{}% +} +\def\forest@draw@edge@{% + \edef\forest@temp{\forestove{edge path}}\forest@temp +} +\def\forest@draw@tikz{% + \ifnum\forestove{phantom}=0 + \forest@draw@tikz@ + \fi +} +\def\forest@draw@tikz@{% + \forestove{tikz}% +} +\newdimen\forest@xg +\newdimen\forest@yg +\newdimen\forest@xs +\newdimen\forest@ys +\def\forest@setupgrowline#1{% + \edef\forest@grow{#1}% + \pgfpointpolar\forest@grow{1pt}% + \forest@xg=\pgf@x + \forest@yg=\pgf@y + \forest@xs=-\pgf@y + \forest@ys=\pgf@x +} +\def\forest@pgfpointprojectiontogrowline#1{{% + \pgf@process{#1}% + \pgfutil@tempdima=\pgf@sys@tonumber{\pgf@x}\forest@xg% + \advance\pgfutil@tempdima by\pgf@sys@tonumber{\pgf@y}\forest@yg% + \global\pgf@x=\pgf@sys@tonumber{\pgfutil@tempdima}\forest@xg% + \global\pgf@y=\pgf@sys@tonumber{\pgfutil@tempdima}\forest@yg% +}} +\def\forest@distancetogrowline#1#2{% + \pgf@process{#2}% + #1=\pgf@sys@tonumber{\pgf@x}\forest@xs\relax + \advance#1 by\pgf@sys@tonumber{\pgf@y}\forest@ys\relax +} +\let\forest@pp@n\relax +\def\forest@projectpathtogrowline#1#2{% + \edef\forest@pp@prefix{#2}% + \forest@save@pgfsyssoftpath@tokendefs + \let\pgfsyssoftpath@movetotoken\forest@projectpath@processpoint + \let\pgfsyssoftpath@linetotoken\forest@projectpath@processpoint + \c@pgf@counta=0 + #1% + \csedef{#2n}{\the\c@pgf@counta}% + \forest@restore@pgfsyssoftpath@tokendefs +} +\def\forest@projectpath@processpoint#1#2{% + \pgfqpoint{#1}{#2}% + \expandafter\edef\csname\forest@pp@prefix\the\c@pgf@counta xo\endcsname{\the\pgf@x}% + \expandafter\edef\csname\forest@pp@prefix\the\c@pgf@counta yo\endcsname{\the\pgf@y}% + \forest@pgfpointprojectiontogrowline{}% + \expandafter\edef\csname\forest@pp@prefix\the\c@pgf@counta xp\endcsname{\the\pgf@x}% + \expandafter\edef\csname\forest@pp@prefix\the\c@pgf@counta yp\endcsname{\the\pgf@y}% + \advance\c@pgf@counta 1\relax +} +\def\forest@sortprojections#1{% + % todo: optimize in cases when we know that the array is actually a + % merger of sorted arrays; when does this happen? in + % distance_between_paths, and when merging the edges of the parent + % and its children in a uniform growth tree + \edef\forest@ppi@inputprefix{#1}% + \c@pgf@counta=\csname#1n\endcsname\relax + \advance\c@pgf@counta -1 + \forest@sort\forest@ppiraw@cmp\forest@ppiraw@let\forest@sort@ascending{0}{\the\c@pgf@counta}% +} +\def\forest@processprojectioninfo#1#2{% + \edef\forest@ppi@inputprefix{#1}% + \c@pgf@counta=0 + \c@pgf@countb=-1 + \safeloop + \ifnum\c@pgf@counta<\csname#1n\endcsname\relax + \letcs\forest@xo{#1\the\c@pgf@counta xo}% + \letcs\forest@yo{#1\the\c@pgf@counta yo}% + \letcs\forest@xp{#1\the\c@pgf@counta xp}% + \letcs\forest@yp{#1\the\c@pgf@counta yp}% + \ifnum\c@pgf@countb<0 + \forest@equaltotolerancefalse + \else + \forest@equaltotolerance + {\pgfqpoint\forest@xp\forest@yp}% + {\pgfqpoint + {\csname#2\the\c@pgf@countb x\endcsname}% + {\csname#2\the\c@pgf@countb y\endcsname}% + }% + \fi + \ifforest@equaltotolerance\else + \advance\c@pgf@countb 1 + \cslet{#2\the\c@pgf@countb x}\forest@xp + \cslet{#2\the\c@pgf@countb y}\forest@yp + \csdef{#2\the\c@pgf@countb @n}{0}% + \fi + % todo: this is ugly! + \ifdefined\forest@xo\ifx\forest@xo\relax\else + \ifdefined\forest@yo\ifx\forest@yo\relax\else + \forest@append@point@to@inner@array + \forest@xo\forest@yo + {#2\the\c@pgf@countb @}% + \csedef{#2(\forest@xo,\forest@yo)}{\the\c@pgf@countb}% + \fi\fi + \fi\fi + \cslet{#1\the\c@pgf@counta xo}\relax + \cslet{#1\the\c@pgf@counta yo}\relax + \cslet{#1\the\c@pgf@counta xp}\relax + \cslet{#1\the\c@pgf@counta yp}\relax + \advance\c@pgf@counta 1 + \saferepeat + \cslet{#1n}\relax + \advance\c@pgf@countb 1 + \csedef{#2n}{\the\c@pgf@countb}% +} +\def\forest@ppiraw@let#1#2{% + \csletcs{\forest@ppi@inputprefix#1xo}{\forest@ppi@inputprefix#2xo}% + \csletcs{\forest@ppi@inputprefix#1yo}{\forest@ppi@inputprefix#2yo}% + \csletcs{\forest@ppi@inputprefix#1xp}{\forest@ppi@inputprefix#2xp}% + \csletcs{\forest@ppi@inputprefix#1yp}{\forest@ppi@inputprefix#2yp}% +} +\def\forest@ppiraw@cmp#1#2{% + \forest@sort@cmptwodimcs + {\forest@ppi@inputprefix#1xp}{\forest@ppi@inputprefix#1yp}% + {\forest@ppi@inputprefix#2xp}{\forest@ppi@inputprefix#2yp}% +} +\def\forest@append@point@to@inner@array#1#2#3{% + \c@pgf@countc=\csname#3n\endcsname\relax + \csedef{#3\the\c@pgf@countc x}{#1}% + \csedef{#3\the\c@pgf@countc y}{#2}% + \forest@distancetogrowline\pgfutil@tempdima{\pgfqpoint#1#2}% + \csedef{#3\the\c@pgf@countc d}{\the\pgfutil@tempdima}% + \advance\c@pgf@countc 1 + \csedef{#3n}{\the\c@pgf@countc}% +} +\def\forest@breakpath#1#2#3{% + \edef\forest@bp@prefix{#2}% + \forest@save@pgfsyssoftpath@tokendefs + \let\pgfsyssoftpath@movetotoken\forest@breakpath@processfirstpoint + \let\pgfsyssoftpath@linetotoken\forest@breakpath@processfirstpoint + %\pgfusepath{}% empty the current path. ok? + #1% + \forest@restore@pgfsyssoftpath@tokendefs + \pgfsyssoftpath@getcurrentpath#3% +} +\def\forest@breakpath@processfirstpoint#1#2{% + \forest@breakpath@processmoveto{#1}{#2}% + \let\pgfsyssoftpath@movetotoken\forest@breakpath@processmoveto + \let\pgfsyssoftpath@linetotoken\forest@breakpath@processlineto +} +\def\forest@breakpath@processmoveto#1#2{% + \pgfsyssoftpath@moveto{#1}{#2}% + \def\forest@previous@x{#1}% + \def\forest@previous@y{#2}% + \expandafter\let\expandafter\forest@previous@i + \csname\forest@bp@prefix(#1,#2)\endcsname + \expandafter\let\expandafter\forest@previous@px + \csname\forest@bp@prefix\forest@previous@i x\endcsname + \expandafter\let\expandafter\forest@previous@py + \csname\forest@bp@prefix\forest@previous@i y\endcsname +} +\def\forest@breakpath@processlineto#1#2{% + \let\forest@breakpath@op\pgfsyssoftpath@lineto + \expandafter\let\expandafter\forest@i + \csname\forest@bp@prefix(#1,#2)\endcsname + \expandafter\let\expandafter\forest@px + \csname\forest@bp@prefix\forest@i x\endcsname + \expandafter\let\expandafter\forest@py + \csname\forest@bp@prefix\forest@i y\endcsname + \forest@equaltotolerance + {\pgfqpoint{\forest@previous@px}{\forest@previous@py}}% + {\pgfqpoint{\forest@px}{\forest@py}}% + \ifforest@equaltotolerance + \let\forest@breakpath@op\pgfsyssoftpath@moveto + \else + \forest@temp@count=\forest@previous@i\relax + \ifnum\forest@previous@i<\forest@i\relax + \def\forest@breakpath@step{1}% + \def\forest@breakpath@test{\forest@temp@count<\forest@i\relax}% + \else + \def\forest@breakpath@step{-1}% + \def\forest@breakpath@test{\forest@temp@count>\forest@i\relax}% + \fi + \safeloop + \advance\forest@temp@count\forest@breakpath@step\relax + \expandafter\ifnum\forest@breakpath@test + \pgfpointintersectionoflines + {\pgfqpoint + {\csname\forest@bp@prefix\the\forest@temp@count x\endcsname}% + {\csname\forest@bp@prefix\the\forest@temp@count y\endcsname}% + }% + {\pgfpointadd + {\pgfqpoint + {\csname\forest@bp@prefix\the\forest@temp@count x\endcsname}% + {\csname\forest@bp@prefix\the\forest@temp@count y\endcsname}% + }% + {\pgfqpoint{\forest@xs}{\forest@ys}}% + }% + {\pgfqpoint{\forest@previous@x}{\forest@previous@y}}% + {\pgfqpoint{#1}{#2}}% + \pgfgetlastxy\forest@last@x\forest@last@y + \pgfsyssoftpath@lineto\forest@last@x\forest@last@y + \forest@append@point@to@inner@array + \forest@last@x\forest@last@y + {\forest@bp@prefix\the\forest@temp@count @}% + \csedef{\forest@bp@prefix(\the\pgf@x,\the\pgf@y)}{\the\forest@temp@count}% + \saferepeat + \fi + \forest@breakpath@op{#1}{#2}% + \def\forest@previous@x{#1}% + \def\forest@previous@y{#2}% + \let\forest@previous@i\forest@i + \let\forest@previous@px\forest@px + \let\forest@previous@py\forest@py +} +\def\forest@getnegativetightedgeofpath#1#2{% + \forest@get@onetightedgeofpath#1\forest@sort@ascending#2} +\def\forest@getpositivetightedgeofpath#1#2{% + \forest@get@onetightedgeofpath#1\forest@sort@descending#2} +\def\forest@get@onetightedgeofpath#1#2#3{% + {% + \forest@get@one@tightedgeofpath#1#2\forest@gep@edge + \global\let\forest@gep@global@edge\forest@gep@edge + }% + \let#3\forest@gep@global@edge +} +\def\forest@get@one@tightedgeofpath#1#2#3{% + \forest@projectpathtogrowline#1{forest@pp@}% + \forest@sortprojections{forest@pp@}% + \forest@processprojectioninfo{forest@pp@}{forest@pi@}% + \forest@breakpath#1{forest@pi@}\forest@brokenpath + \forest@sort@inner@arrays{forest@pi@}#2% + \forest@pathtodict\forest@brokenpath{forest@pi@}% + \forest@gettightedgeofpath@getedge\forest@edge + \forest@simplifypath\forest@edge#3% +} +\def\forest@getbothtightedgesofpath#1#2#3{% + {% + \forest@get@one@tightedgeofpath#1\forest@sort@ascending\forest@gep@firstedge + \c@pgf@counta=0 + \forest@loop + \ifnum\c@pgf@counta<\forest@pi@n\relax + \forest@ppi@deflet{forest@pi@\the\c@pgf@counta @}% + \forest@reversearray\forest@ppi@let + {0}% + {\csname forest@pi@\the\c@pgf@counta @n\endcsname}% + \advance\c@pgf@counta 1 + \forest@repeat + \forest@gettightedgeofpath@getedge\forest@edge + \forest@simplifypath\forest@edge\forest@gep@secondedge + \global\let\forest@gep@global@firstedge\forest@gep@firstedge + \global\let\forest@gep@global@secondedge\forest@gep@secondedge + }% + \let#2\forest@gep@global@firstedge + \let#3\forest@gep@global@secondedge +} +\def\forest@sort@inner@arrays#1#2{% + \c@pgf@counta=0 + \safeloop + \ifnum\c@pgf@counta<\csname#1n\endcsname + \c@pgf@countb=\csname#1\the\c@pgf@counta @n\endcsname\relax + \ifnum\c@pgf@countb>1 + \advance\c@pgf@countb -1 + \forest@ppi@deflet{#1\the\c@pgf@counta @}% + \forest@ppi@defcmp{#1\the\c@pgf@counta @}% + \forest@sort\forest@ppi@cmp\forest@ppi@let#2{0}{\the\c@pgf@countb}% + \fi + \advance\c@pgf@counta 1 + \saferepeat +} +\def\forest@ppi@deflet#1{% + \edef\forest@ppi@let##1##2{% + \noexpand\csletcs{#1##1x}{#1##2x}% + \noexpand\csletcs{#1##1y}{#1##2y}% + \noexpand\csletcs{#1##1d}{#1##2d}% + }% +} +\def\forest@ppi@defcmp#1{% + \edef\forest@ppi@cmp##1##2{% + \noexpand\forest@sort@cmpdimcs{#1##1d}{#1##2d}% + }% +} +\let\forest@inpath\advance +\def\forest@pathtodict#1#2{% + \edef\forest@pathtodict@prefix{#2}% + \forest@save@pgfsyssoftpath@tokendefs + \let\pgfsyssoftpath@movetotoken\forest@pathtodict@movetoop + \let\pgfsyssoftpath@linetotoken\forest@pathtodict@linetoop + \def\forest@pathtodict@subpathstart{}% + #1% + \forest@restore@pgfsyssoftpath@tokendefs +} +\def\forest@pathtodict@movetoop#1#2{% + \def\forest@pathtodict@subpathstart{(#1,#2)-}% +} +\def\forest@pathtodict@linetoop#1#2{% +\if\relax\forest@pathtodict@subpathstart\relax\else + \let\forest@pathtodict@from\forest@pathtodict@subpathstart + \fi + \expandafter\let\csname\forest@pathtodict@prefix\forest@pathtodict@from-(#1,#2)\endcsname\forest@inpath + \def\forest@pathtodict@from{(#1,#2)-}% + \def\forest@pathtodict@subpathstart{}% +} +\def\forest@gettightedgeofpath@getedge#1{% cs to store the edge into + \pgfsyssoftpath@setcurrentpath\pgfutil@empty + \let\forest@last@x\relax + \let\forest@last@y\relax + \c@pgf@counta=0 + \forest@temp@count=\forest@pi@n\relax + \advance\forest@temp@count -1 + \edef\forest@nminusone{\the\forest@temp@count}% + \safeloop + \ifnum\c@pgf@counta<\forest@nminusone\relax + \forest@gettightedgeofpath@getedge@loopa + \saferepeat + \ifnum\forest@nminusone<\forest@n\relax\else + \ifnum\csname forest@pi@\forest@nminusone @n\endcsname>0 + \forest@gettightedgeofpath@maybemoveto{\forest@nminusone}{0}% + \fi + \fi + \pgfsyssoftpath@getcurrentpath#1% + \pgfsyssoftpath@setcurrentpath\pgfutil@empty +} +\def\forest@gettightedgeofpath@getedge@loopa{% + \ifnum\csname forest@pi@\the\c@pgf@counta @n\endcsname>0 + \forest@gettightedgeofpath@maybemoveto{\the\c@pgf@counta}{0}% + \c@pgf@countb=0 + \safeloop + \ifnum\c@pgf@countb<\csname forest@pi@\the\c@pgf@counta @n\endcsname\relax + \forest@gettightedgeofpath@getedge@loopb + \saferepeat + \fi + \advance\c@pgf@counta 1 +} +\def\forest@gettightedgeofpath@getedge@loopb{% + \c@pgf@countc=0 + \advance\c@pgf@counta 1 + \edef\forest@aplusone{\the\c@pgf@counta}% + \advance\c@pgf@counta -1 + \safeloop + \ifnum\c@pgf@countc<\csname forest@pi@\forest@aplusone @n\endcsname\relax + \forest@tempfalse + \expandafter\ifx\csname forest@pi@(% + \csname forest@pi@\the\c@pgf@counta @\the\c@pgf@countb x\endcsname,% + \csname forest@pi@\the\c@pgf@counta @\the\c@pgf@countb y\endcsname)--(% + \csname forest@pi@\forest@aplusone @\the\c@pgf@countc x\endcsname,% + \csname forest@pi@\forest@aplusone @\the\c@pgf@countc y\endcsname)% + \endcsname\forest@inpath + \forest@temptrue + \else + \expandafter\ifx\csname forest@pi@(% + \csname forest@pi@\forest@aplusone @\the\c@pgf@countc x\endcsname,% + \csname forest@pi@\forest@aplusone @\the\c@pgf@countc y\endcsname)--(% + \csname forest@pi@\the\c@pgf@counta @\the\c@pgf@countb x\endcsname,% + \csname forest@pi@\the\c@pgf@counta @\the\c@pgf@countb y\endcsname)% + \endcsname\forest@inpath + \forest@temptrue + \fi + \fi + \ifforest@temp + \forest@gettightedgeofpath@maybemoveto{\the\c@pgf@counta}{\the\c@pgf@countb}% + \edef\forest@last@x{% + \csname forest@pi@\forest@aplusone @\the\c@pgf@countc x\endcsname}% + \edef\forest@last@y{% + \csname forest@pi@\forest@aplusone @\the\c@pgf@countc y\endcsname}% + \pgfsyssoftpath@lineto\forest@last@x\forest@last@y + \c@pgf@countc=\csname forest@pi@\forest@aplusone @n\endcsname + \c@pgf@countb=\csname forest@pi@\the\c@pgf@counta @n\endcsname + \fi + \advance\c@pgf@countc 1 + \saferepeat + \advance\c@pgf@countb 1 +} +\def\forest@gettightedgeofpath@maybemoveto#1#2{% + \forest@temptrue + \ifx\forest@last@x\relax\else + \ifdim\forest@last@x=\csname forest@pi@#1@#2x\endcsname\relax + \ifdim\forest@last@y=\csname forest@pi@#1@#2y\endcsname\relax + \forest@tempfalse + \fi + \fi + \fi + \ifforest@temp + \edef\forest@last@x{\csname forest@pi@#1@#2x\endcsname}% + \edef\forest@last@y{\csname forest@pi@#1@#2y\endcsname}% + \pgfsyssoftpath@moveto\forest@last@x\forest@last@y + \fi +} +\def\forest@simplifypath#1#2{% + \pgfsyssoftpath@setcurrentpath\pgfutil@empty + \forest@save@pgfsyssoftpath@tokendefs + \let\pgfsyssoftpath@movetotoken\forest@simplifypath@moveto + \let\pgfsyssoftpath@linetotoken\forest@simplifypath@lineto + \let\forest@last@x\relax + \let\forest@last@y\relax + \let\forest@last@atan\relax + #1% + \ifx\forest@last@x\relax\else + \ifx\forest@last@atan\relax\else + \pgfsyssoftpath@lineto\forest@last@x\forest@last@y + \fi + \fi + \forest@restore@pgfsyssoftpath@tokendefs + \pgfsyssoftpath@getcurrentpath#2% + \pgfsyssoftpath@setcurrentpath\pgfutil@empty +} +\def\forest@simplifypath@moveto#1#2{% + \ifx\forest@last@x\relax\else + \pgfsyssoftpath@lineto\forest@last@x\forest@last@y + \fi + \pgfsyssoftpath@moveto{#1}{#2}% + \def\forest@last@x{#1}% + \def\forest@last@y{#2}% + \let\forest@last@atan\relax +} +\def\forest@getedgeofpath@precision{1pt} +\def\forest@simplifypath@lineto#1#2{% + \ifx\forest@last@x\relax + \def\forest@last@x{#1}% + \def\forest@last@y{#2}% + \let\forest@last@atan\relax + \else + \pgfpointdiff{\pgfqpoint{#1}{#2}}{\pgfqpoint{\forest@last@x}{\forest@last@y}}% + \ifdim\pgf@x<\pgfintersectiontolerance + \ifdim-\pgf@x<\pgfintersectiontolerance + \pgf@x=0pt + \fi + \fi + \csname pgfmathatan2\endcsname{\pgf@x}{\pgf@y}% + \let\forest@current@atan\pgfmathresult + \ifx\forest@last@atan\relax + \def\forest@last@x{#1}% + \def\forest@last@y{#2}% + \let\forest@last@atan\forest@current@atan + \else + \pgfutil@tempdima=\forest@current@atan pt + \advance\pgfutil@tempdima -\forest@last@atan pt + \ifdim\pgfutil@tempdima<0pt\relax + \multiply\pgfutil@tempdima -1 + \fi + \ifdim\pgfutil@tempdima<\forest@getedgeofpath@precision\relax + \else + \pgfsyssoftpath@lineto\forest@last@x\forest@last@y + \let\forest@last@atan\forest@current@atan + \fi + \def\forest@last@x{#1}% + \def\forest@last@y{#2}% + \fi + \fi +} +\def\forest@getnegativerectangleedgeofpath#1#2{% + \forest@getnegativerectangleorbandedgeofpath{#1}{#2}{\the\pgf@xb}} +\def\forest@getpositiverectangleedgeofpath#1#2{% + \forest@getpositiverectangleorbandedgeofpath{#1}{#2}{\the\pgf@xb}} +\def\forest@getbothrectangleedgesofpath#1#2#3{% + \forest@getbothrectangleorbandedgesofpath{#1}{#2}{#3}{\the\pgf@xb}} +\def\forest@bandlength{5000pt} % something large (ca. 180cm), but still manageable for TeX without producing `too large' errors +\def\forest@getnegativebandedgeofpath#1#2{% + \forest@getnegativerectangleorbandedgeofpath{#1}{#2}{\forest@bandlength}} +\def\forest@getpositivebandedgeofpath#1#2{% + \forest@getpositiverectangleorbandedgeofpath{#1}{#2}{\forest@bandlength}} +\def\forest@getbothbandedgesofpath#1#2#3{% + \forest@getbothrectangleorbandedgesofpath{#1}{#2}{#3}{\forest@bandlength}} +\def\forest@getnegativerectangleorbandedgeofpath#1#2#3{% + \forest@path@getboundingrectangle@ls#1{\forest@grow}% + \edef\forest@gre@path{% + \noexpand\pgfsyssoftpath@movetotoken{\the\pgf@xa}{\the\pgf@ya}% + \noexpand\pgfsyssoftpath@linetotoken{#3}{\the\pgf@ya}% + }% + {% + \pgftransformreset + \pgftransformrotate{\forest@grow}% + \forest@pgfpathtransformed\forest@gre@path + }% + \pgfsyssoftpath@getcurrentpath#2% +} +\def\forest@getpositiverectangleorbandedgeofpath#1#2#3{% + \forest@path@getboundingrectangle@ls#1{\forest@grow}% + \edef\forest@gre@path{% + \noexpand\pgfsyssoftpath@movetotoken{\the\pgf@xa}{\the\pgf@yb}% + \noexpand\pgfsyssoftpath@linetotoken{#3}{\the\pgf@yb}% + }% + {% + \pgftransformreset + \pgftransformrotate{\forest@grow}% + \forest@pgfpathtransformed\forest@gre@path + }% + \pgfsyssoftpath@getcurrentpath#2% +} +\def\forest@getbothrectangleorbandedgesofpath#1#2#3#4{% + \forest@path@getboundingrectangle@ls#1{\forest@grow}% + \edef\forest@gre@negpath{% + \noexpand\pgfsyssoftpath@movetotoken{\the\pgf@xa}{\the\pgf@ya}% + \noexpand\pgfsyssoftpath@linetotoken{#4}{\the\pgf@ya}% + }% + \edef\forest@gre@pospath{% + \noexpand\pgfsyssoftpath@movetotoken{\the\pgf@xa}{\the\pgf@yb}% + \noexpand\pgfsyssoftpath@linetotoken{#4}{\the\pgf@yb}% + }% + {% + \pgftransformreset + \pgftransformrotate{\forest@grow}% + \forest@pgfpathtransformed\forest@gre@negpath + }% + \pgfsyssoftpath@getcurrentpath#2% + {% + \pgftransformreset + \pgftransformrotate{\forest@grow}% + \forest@pgfpathtransformed\forest@gre@pospath + }% + \pgfsyssoftpath@getcurrentpath#3% +} +\def\forest@distance@between@edge@paths#1#2#3{% + % #1, #2 = (edge) paths + % + % project paths + \forest@projectpathtogrowline#1{forest@p1@}% + \forest@projectpathtogrowline#2{forest@p2@}% + % merge projections (the lists are sorted already, because edge + % paths are |sorted|) + \forest@dbep@mergeprojections + {forest@p1@}{forest@p2@}% + {forest@P1@}{forest@P2@}% + % process projections + \forest@processprojectioninfo{forest@P1@}{forest@PI1@}% + \forest@processprojectioninfo{forest@P2@}{forest@PI2@}% + % break paths + \forest@breakpath#1{forest@PI1@}\forest@broken@one + \forest@breakpath#2{forest@PI2@}\forest@broken@two + % sort inner arrays ---optimize: it's enough to find max and min + \forest@sort@inner@arrays{forest@PI1@}\forest@sort@descending + \forest@sort@inner@arrays{forest@PI2@}\forest@sort@ascending + % compute the distance + \let\forest@distance\relax + \c@pgf@countc=0 + \forest@loop + \ifnum\c@pgf@countc<\csname forest@PI1@n\endcsname\relax + \ifnum\csname forest@PI1@\the\c@pgf@countc @n\endcsname=0 \else + \ifnum\csname forest@PI2@\the\c@pgf@countc @n\endcsname=0 \else + \pgfutil@tempdima=\csname forest@PI2@\the\c@pgf@countc @0d\endcsname\relax + \advance\pgfutil@tempdima -\csname forest@PI1@\the\c@pgf@countc @0d\endcsname\relax + \ifx\forest@distance\relax + \edef\forest@distance{\the\pgfutil@tempdima}% + \else + \ifdim\pgfutil@tempdima<\forest@distance\relax + \edef\forest@distance{\the\pgfutil@tempdima}% + \fi + \fi + \fi + \fi + \advance\c@pgf@countc 1 + \forest@repeat + \let#3\forest@distance +} + % merge projections: we need two projection arrays, both containing + % projection points from both paths, but each with the original + % points from only one path +\def\forest@dbep@mergeprojections#1#2#3#4{% + % TODO: optimize: v bistvu ni treba sortirat, ker je edge path že sortiran + \forest@sortprojections{#1}% + \forest@sortprojections{#2}% + \c@pgf@counta=0 + \c@pgf@countb=0 + \c@pgf@countc=0 + \edef\forest@input@prefix@one{#1}% + \edef\forest@input@prefix@two{#2}% + \edef\forest@output@prefix@one{#3}% + \edef\forest@output@prefix@two{#4}% + \forest@dbep@mp@iterate + \csedef{#3n}{\the\c@pgf@countc}% + \csedef{#4n}{\the\c@pgf@countc}% +} +\def\forest@dbep@mp@iterate{% + \let\forest@dbep@mp@next\forest@dbep@mp@iterate + \ifnum\c@pgf@counta<\csname\forest@input@prefix@one n\endcsname\relax + \ifnum\c@pgf@countb<\csname\forest@input@prefix@two n\endcsname\relax + \let\forest@dbep@mp@next\forest@dbep@mp@do + \else + \let\forest@dbep@mp@next\forest@dbep@mp@iteratefirst + \fi + \else + \ifnum\c@pgf@countb<\csname\forest@input@prefix@two n\endcsname\relax + \let\forest@dbep@mp@next\forest@dbep@mp@iteratesecond + \else + \let\forest@dbep@mp@next\relax + \fi + \fi + \forest@dbep@mp@next +} +\def\forest@dbep@mp@do{% + \forest@sort@cmptwodimcs% + {\forest@input@prefix@one\the\c@pgf@counta xp}% + {\forest@input@prefix@one\the\c@pgf@counta yp}% + {\forest@input@prefix@two\the\c@pgf@countb xp}% + {\forest@input@prefix@two\the\c@pgf@countb yp}% + \if\forest@sort@cmp@result=% + \forest@dbep@mp@@store@p\forest@input@prefix@one\c@pgf@counta + \forest@dbep@mp@@store@o\forest@input@prefix@one + \c@pgf@counta\forest@output@prefix@one + \forest@dbep@mp@@store@o\forest@input@prefix@two + \c@pgf@countb\forest@output@prefix@two + \advance\c@pgf@counta 1 + \advance\c@pgf@countb 1 + \else + \if\forest@sort@cmp@result>% + \forest@dbep@mp@@store@p\forest@input@prefix@two\c@pgf@countb + \forest@dbep@mp@@store@o\forest@input@prefix@two + \c@pgf@countb\forest@output@prefix@two + \advance\c@pgf@countb 1 + \else%< + \forest@dbep@mp@@store@p\forest@input@prefix@one\c@pgf@counta + \forest@dbep@mp@@store@o\forest@input@prefix@one + \c@pgf@counta\forest@output@prefix@one + \advance\c@pgf@counta 1 + \fi + \fi + \advance\c@pgf@countc 1 + \forest@dbep@mp@iterate +} +\def\forest@dbep@mp@@store@p#1#2{% + \csletcs + {\forest@output@prefix@one\the\c@pgf@countc xp}% + {#1\the#2xp}% + \csletcs + {\forest@output@prefix@one\the\c@pgf@countc yp}% + {#1\the#2yp}% + \csletcs + {\forest@output@prefix@two\the\c@pgf@countc xp}% + {#1\the#2xp}% + \csletcs + {\forest@output@prefix@two\the\c@pgf@countc yp}% + {#1\the#2yp}% +} +\def\forest@dbep@mp@@store@o#1#2#3{% + \csletcs{#3\the\c@pgf@countc xo}{#1\the#2xo}% + \csletcs{#3\the\c@pgf@countc yo}{#1\the#2yo}% +} +\def\forest@dbep@mp@iteratefirst{% + \forest@dbep@mp@iterateone\forest@input@prefix@one\c@pgf@counta\forest@output@prefix@one +} +\def\forest@dbep@mp@iteratesecond{% + \forest@dbep@mp@iterateone\forest@input@prefix@two\c@pgf@countb\forest@output@prefix@two +} +\def\forest@dbep@mp@iterateone#1#2#3{% + \forest@loop + \ifnum#2<\csname#1n\endcsname\relax + \forest@dbep@mp@@store@p#1#2% + \forest@dbep@mp@@store@o#1#2#3% + \advance\c@pgf@countc 1 + \advance#21 + \forest@repeat +} +\newif\ifforest@equaltotolerance +\def\forest@equaltotolerance#1#2{{% + \pgfpointdiff{#1}{#2}% + \ifdim\pgf@x<0pt \multiply\pgf@x -1 \fi + \ifdim\pgf@y<0pt \multiply\pgf@y -1 \fi + \global\forest@equaltotolerancefalse + \ifdim\pgf@x<\pgfintersectiontolerance\relax + \ifdim\pgf@y<\pgfintersectiontolerance\relax + \global\forest@equaltotolerancetrue + \fi + \fi +}} +\def\forest@save@pgfsyssoftpath@tokendefs{% + \let\forest@origmovetotoken\pgfsyssoftpath@movetotoken + \let\forest@origlinetotoken\pgfsyssoftpath@linetotoken + \let\forest@origcurvetosupportatoken\pgfsyssoftpath@curvetosupportatoken + \let\forest@origcurvetosupportbtoken\pgfsyssoftpath@curvetosupportbtoken + \let\forest@origcurvetotoken\pgfsyssoftpath@curvetototoken + \let\forest@origrectcornertoken\pgfsyssoftpath@rectcornertoken + \let\forest@origrectsizetoken\pgfsyssoftpath@rectsizetoken + \let\forest@origclosepathtoken\pgfsyssoftpath@closepathtoken + \let\pgfsyssoftpath@movetotoken\forest@badtoken + \let\pgfsyssoftpath@linetotoken\forest@badtoken + \let\pgfsyssoftpath@curvetosupportatoken\forest@badtoken + \let\pgfsyssoftpath@curvetosupportbtoken\forest@badtoken + \let\pgfsyssoftpath@curvetototoken\forest@badtoken + \let\pgfsyssoftpath@rectcornertoken\forest@badtoken + \let\pgfsyssoftpath@rectsizetoken\forest@badtoken + \let\pgfsyssoftpath@closepathtoken\forest@badtoken +} +\def\forest@badtoken{% + \PackageError{forest}{This token should not be in this path}{}% +} +\def\forest@restore@pgfsyssoftpath@tokendefs{% + \let\pgfsyssoftpath@movetotoken\forest@origmovetotoken + \let\pgfsyssoftpath@linetotoken\forest@origlinetotoken + \let\pgfsyssoftpath@curvetosupportatoken\forest@origcurvetosupportatoken + \let\pgfsyssoftpath@curvetosupportbtoken\forest@origcurvetosupportbtoken + \let\pgfsyssoftpath@curvetototoken\forest@origcurvetotoken + \let\pgfsyssoftpath@rectcornertoken\forest@origrectcornertoken + \let\pgfsyssoftpath@rectsizetoken\forest@origrectsizetoken + \let\pgfsyssoftpath@closepathtoken\forest@origclosepathtoken +} +\def\forest@extendpath#1#2#3{% + \pgf@process{#3}% + \pgfsyssoftpath@setcurrentpath#1% + \forest@save@pgfsyssoftpath@tokendefs + \let\pgfsyssoftpath@movetotoken\forest@extendpath@moveto + \let\pgfsyssoftpath@linetotoken\forest@extendpath@lineto + #2% + \forest@restore@pgfsyssoftpath@tokendefs + \pgfsyssoftpath@getcurrentpath#1% +} +\def\forest@extendpath@moveto#1#2{% + \forest@extendpath@do{#1}{#2}\pgfsyssoftpath@moveto +} +\def\forest@extendpath@lineto#1#2{% + \forest@extendpath@do{#1}{#2}\pgfsyssoftpath@lineto +} +\def\forest@extendpath@do#1#2#3{% + {% + \advance\pgf@x #1 + \advance\pgf@y #2 + #3{\the\pgf@x}{\the\pgf@y}% + }% +} +\def\forest@path@getboundingrectangle@ls#1#2{% + {% + \pgftransformreset + \pgftransformrotate{-(#2)}% + \forest@pgfpathtransformed#1% + }% + \pgfsyssoftpath@getcurrentpath\forest@gbr@rotatedpath + \forest@path@getboundingrectangle@xy\forest@gbr@rotatedpath +} +\def\forest@path@getboundingrectangle@xy#1{% + \forest@save@pgfsyssoftpath@tokendefs + \let\pgfsyssoftpath@movetotoken\forest@gbr@firstpoint + \let\pgfsyssoftpath@linetotoken\forest@gbr@firstpoint + #1% + \forest@restore@pgfsyssoftpath@tokendefs +} +\def\forest@gbr@firstpoint#1#2{% + \pgf@xa=#1 \pgf@xb=#1 \pgf@ya=#2 \pgf@yb=#2 + \let\pgfsyssoftpath@movetotoken\forest@gbr@point + \let\pgfsyssoftpath@linetotoken\forest@gbr@point +} +\def\forest@gbr@point#1#2{% + \ifdim#1<\pgf@xa\relax\pgf@xa=#1 \fi + \ifdim#1>\pgf@xb\relax\pgf@xb=#1 \fi + \ifdim#2<\pgf@ya\relax\pgf@ya=#2 \fi + \ifdim#2>\pgf@yb\relax\pgf@yb=#2 \fi +} +\pgfkeys{/forest/external/.cd, + %copy command/.initial={cp "\source" "\target"}, + copy command/.initial={}, + optimize/.is if=forest@external@optimize@, + context/.initial={% + \forestOve{\csname forest@id@of@standard node\endcsname}{environment@formula}}, + depends on macro/.style={context/.append/.expanded={% + \expandafter\detokenize\expandafter{#1}}}, +} +\def\forest@file@copy#1#2{% + \IfFileExists{#1}{% + \pgfkeysgetvalue{/forest/external/copy command}\forest@copy@command + \ifdefempty\forest@copy@command{% + \forest@file@copy@{#1}{#2}% + }{ % copy by external command + \def\source{#1}% + \def\target{#2}% + \immediate\write18{\forest@copy@command}% + }% + }{}% +} +\def\forest@file@copy@#1#2{% + \newread\forest@copy@in + \openin\forest@copy@in=#1 + \newwrite\forest@copy@out + \immediate\openout\forest@copy@out#2 + \endlinechar-1 + \loop + \unless\ifeof\forest@copy@in + \readline\forest@copy@in to\forest@temp + \immediate\write\forest@copy@out{\forest@temp}% + \repeat + \immediate\closeout\forest@copy@out + \closein\forest@copy@in +} +\newif\ifforest@external@optimize@ +\forest@external@optimize@true +\ifforest@install@keys@to@tikz@path@ +\tikzset{ + fit to/.style={ + /forest/for nodewalk=% + {TeX={\def\forest@fitto{}},#1}% + {TeX={\eappto\forest@fitto{(\forestove{name})}}}, + fit/.expanded={\forest@fitto} + }, +} +\fi +\ifforest@external@ + \ifdefined\tikzexternal@tikz@replacement\else + \usetikzlibrary{external}% + \fi + \pgfkeys{% + /tikz/external/failed ref warnings for={}, + /pgf/images/aux in dpth=false, + }% + \tikzifexternalizing{}{% + \forest@file@copy{\jobname.aux}{\jobname.aux.copy}% + }% + \AtBeginDocument{% + \tikzifexternalizing{% + \IfFileExists{\tikzexternalrealjob.aux.copy}{% + \makeatletter + \input\tikzexternalrealjob.aux.copy\relax + \makeatother + }{}% + }{% + \newwrite\forest@auxout + \immediate\openout\forest@auxout=\tikzexternalrealjob.for.tmp + }% + \IfFileExists{\tikzexternalrealjob.for}{% + {% + \makehashother\makeatletter + \input\tikzexternalrealjob.for\relax + }% + }{}% + }% + \AtEndDocument{% + \tikzifexternalizing{}{% + \immediate\closeout\forest@auxout + \forest@file@copy{\jobname.for.tmp}{\jobname.for}% + }% + }% +\fi +\NewDocumentEnvironment{forest}{D(){}}{% + \forest@config{#1}% + \Collect@Body + \forest@env +}{} +\NewDocumentCommand{\Forest}{s D(){} m}{% + \forest@config{#2}% + \IfBooleanTF{#1}{\let\forest@next\forest@env}{\let\forest@next\forest@group@env}% + \forest@next{#3}% +} +\def\forest@config#1{% + \def\forest@stages{stages}% + \forestset{@config/.cd,#1}% +} +\forestset{@config/.cd, + stages/.store in=\forest@stages, + .unknown/.code={\PackageError{forest}{Unknown config option for forest environment/command.}{In Forest v2.0.0 and v2.0.1, this (parenthesized) argument accepted the definition of style stages for the current forest environment/macro. Since v2.0.2, you should write "\string\begin{forest}(stages={...})...\string\end{forest}", or "\string\Forest(stages={...}){...}" instead.}} +} +\def\forest@group@env#1{{\forest@env{#1}}} +\newif\ifforest@externalize@tree@ +\newif\ifforest@was@tikzexternalwasenable +\newcommand\forest@env[1]{% + \let\forest@external@next\forest@begin + \forest@was@tikzexternalwasenablefalse + \ifdefined\tikzexternal@tikz@replacement + \ifx\tikz\tikzexternal@tikz@replacement + \forest@was@tikzexternalwasenabletrue + \tikzexternaldisable + \fi + \fi + \forest@externalize@tree@false + \ifforest@external@ + \ifforest@was@tikzexternalwasenable + \forest@env@ + \fi + \fi + \forest@standardnode@calibrate + \forest@external@next{#1}% +} +\def\forest@env@{% + \iftikzexternalexportnext + \tikzifexternalizing{% + \let\forest@external@next\forest@begin@externalizing + }{% + \let\forest@external@next\forest@begin@externalize + }% + \else + \tikzexternalexportnexttrue + \fi +} +\long\def\forest@begin@externalizing#1{% + \forest@external@setup{#1}% + \let\forest@external@next\forest@begin + \forest@externalize@inner@n=-1 + \ifforest@external@optimize@\forest@externalizing@maybeoptimize\fi + \forest@external@next{#1}% + \tikzexternalenable +} +\def\forest@externalizing@maybeoptimize{% + \edef\forest@temp{\tikzexternalrealjob-forest-\forest@externalize@outer@n}% + \edef\forest@marshal{% + \noexpand\pgfutil@in@ + {\expandafter\detokenize\expandafter{\forest@temp}.} + {\expandafter\detokenize\expandafter{\pgfactualjobname}.}% + }\forest@marshal + \ifpgfutil@in@ + \else + \let\forest@external@next\@gobble + \fi +} +\long\def\forest@begin@externalize#1{% + \forest@external@setup{#1}% + \iftikzexternal@file@isuptodate + \setbox0=\hbox{% + \csname forest@externalcheck@\forest@externalize@outer@n\endcsname + }% + \fi + \iftikzexternal@file@isuptodate + \csname forest@externalload@\forest@externalize@outer@n\endcsname + \else + \forest@externalize@tree@true + \forest@externalize@inner@n=-1 + \forest@begin{#1}% + \ifcsdef{forest@externalize@@\forest@externalize@id}{}{% + \immediate\write\forest@auxout{% + \noexpand\forest@external + {\forest@externalize@outer@n}% + {\expandafter\detokenize\expandafter{\forest@externalize@id}}% + {\expandonce\forest@externalize@checkimages}% + {\expandonce\forest@externalize@loadimages}% + }% + }% + \fi + \tikzexternalenable +} +\def\forest@includeexternal@check#1{% + \tikzsetnextfilename{#1}% + \IfFileExists{\tikzexternal@filenameprefix/#1}{\tikzexternal@file@isuptodatetrue}{\tikzexternal@file@isuptodatefalse}% +} +\def\makehashother{\catcode`\#=12}% +\long\def\forest@external@setup#1{% + % set up \forest@externalize@id and \forest@externalize@outer@n + % we need to deal with #s correctly (\write doubles them) + \setbox0=\hbox{\makehashother\makeatletter + \scantokens{\forest@temp@toks{#1}}\expandafter + }% + \expandafter\forest@temp@toks\expandafter{\the\forest@temp@toks}% + \edef\forest@temp{\pgfkeysvalueof{/forest/external/context}}% + \edef\forest@externalize@id{% + \expandafter\detokenize\expandafter{\forest@temp}% + @@% + \expandafter\detokenize\expandafter{\the\forest@temp@toks}% + }% + \letcs\forest@externalize@outer@n{forest@externalize@@\forest@externalize@id}% + \ifdefined\forest@externalize@outer@n + \global\tikzexternal@file@isuptodatetrue + \else + \global\advance\forest@externalize@max@outer@n 1 + \edef\forest@externalize@outer@n{\the\forest@externalize@max@outer@n}% + \global\tikzexternal@file@isuptodatefalse + \fi + \def\forest@externalize@loadimages{}% + \def\forest@externalize@checkimages{}% +} +\newcount\forest@externalize@max@outer@n +\global\forest@externalize@max@outer@n=0 +\newcount\forest@externalize@inner@n +\long\def\forest@external#1#2#3#4{% #1=n,#2=context+source code,#3=update check code, #4=load code + \ifnum\forest@externalize@max@outer@n<#1 + \global\forest@externalize@max@outer@n=#1 + \fi + \global\csdef{forest@externalize@@\detokenize{#2}}{#1}% + \global\csdef{forest@externalcheck@#1}{#3}% + \global\csdef{forest@externalload@#1}{#4}% + \tikzifexternalizing{}{% + \immediate\write\forest@auxout{% + \noexpand\forest@external{#1}% + {\expandafter\detokenize\expandafter{#2}}% + {\unexpanded{#3}}% + {\unexpanded{#4}}% + }% + }% +} +\def\forest@includeexternal#1{% + \edef\forest@temp{\pgfkeysvalueof{/forest/external/context}}% + %\typeout{forest: Including external picture '#1' for forest context+code: '\expandafter\detokenize\expandafter{\forest@externalize@id}'}% + {% + %\def\pgf@declaredraftimage##1##2{\def\pgf@image{\hbox{}}}% + \tikzsetnextfilename{#1}% + \tikzexternalenable + \tikz{}% + }% +} +\def\forest@includeexternal@box#1#2{% + \global\setbox#1=\hbox{\forest@includeexternal{#2}}% +} +\long\def\forest@begin#1{% + \iffalse{\fi\forest@parsebracket#1}% +} +\def\forest@parsebracket{% + \bracketParse{\forest@get@root@afterthought}\forest@root=% +} +\def\forest@get@root@afterthought{% + \expandafter\forest@get@root@afterthought@\expandafter{\iffalse}\fi +} +\long\def\forest@get@root@afterthought@#1{% + \ifblank{#1}{}{% + \forestOeappto{\forest@root}{given options}{,afterthought={\unexpanded{#1}}}% + }% + \forest@do +} +\def\forest@do{% + \forest@node@Compute@numeric@ts@info{\forest@root}% + \expandafter\forestset\expandafter{\forest@stages}% + \ifforest@was@tikzexternalwasenable + \tikzexternalenable + \fi +} +\def\forest@standardnode@new{% + \advance\forest@node@maxid1 + \forest@fornode{\the\forest@node@maxid}{% + \forest@node@init + \forestoeset{id}{\forest@cn}% + \forest@node@setname@silent{standard node}% + }% +} +\def\forest@standardnode@calibrate{% + \forest@fornode{\forest@node@Nametoid{standard node}}{% + \edef\forest@environment{\forestove{environment@formula}}% + \forestoget{previous@environment}\forest@previous@environment + \ifx\forest@environment\forest@previous@environment\else + \forestolet{previous@environment}\forest@environment + \forest@node@typeset + \forestoget{calibration@procedure}\forest@temp + \expandafter\forestset\expandafter{\forest@temp}% + \fi + }% +} +\def\forestStandardNode[#1]#2#3#4{% + \let\forest@standardnode@restoretikzexternal\relax + \ifdefined\tikzexternaldisable + \ifx\tikz\tikzexternal@tikz@replacement + \tikzexternaldisable + \let\forest@standardnode@restoretikzexternal\tikzexternalenable + \fi + \fi + \forest@standardnode@new + \forest@fornode{\forest@node@Nametoid{standard node}}{% + \forestset{content=#1}% + \forestoset{environment@formula}{#2}% + \edef\forest@temp{\unexpanded{#3}}% + \forestolet{calibration@procedure}\forest@temp + \def\forest@calibration@initializing@code{}% + \pgfqkeys{/forest/initializing@code}{#4}% + \forestolet{initializing@code}\forest@calibration@initializing@code + \forest@standardnode@restoretikzexternal + } +} +\forestset{initializing@code/.unknown/.code={% + \eappto\forest@calibration@initializing@code{% + \noexpand\forestOget{\forest@node@Nametoid{standard node}}{\pgfkeyscurrentname}\noexpand\forest@temp + \noexpand\forestolet{\pgfkeyscurrentname}\noexpand\forest@temp + }% + } +} +\def\forest@initializefromstandardnode{% + \forestOve{\forest@node@Nametoid{standard node}}{initializing@code}% +} +\forestStandardNode[dj] + {% + \forestOve{\forest@node@Nametoid{standard node}}{content},% + \the\ht\strutbox,\the\pgflinewidth,% + \pgfkeysvalueof{/pgf/inner ysep},\pgfkeysvalueof{/pgf/outer ysep},% + \pgfkeysvalueof{/pgf/inner xsep},\pgfkeysvalueof{/pgf/outer xsep}% + } + { + l sep={\the\ht\strutbox+\pgfkeysvalueof{/pgf/inner ysep}}, + l={l_sep()+abs(max_y()-min_y())+2*\pgfkeysvalueof{/pgf/outer ysep}}, + s sep={2*\pgfkeysvalueof{/pgf/inner xsep}} + } + {l sep,l,s sep} +\pgfqkeys{/forest/@cs}{% + name/.code={% + \edef\forest@cn{\forest@node@Nametoid{#1}}% + \forest@forestcs@resetxy}, + id/.code={% + \edef\forest@cn{#1}% + \forest@forestcs@resetxy}, + go/.code={% + \forest@go{#1}% + \forest@forestcs@resetxy}, + anchor/.code={\forest@forestcs@anchor{#1}}, + l/.code={% + \pgfmathsetlengthmacro\forest@forestcs@l{#1}% + \forest@forestcs@ls + }, + s/.code={% + \pgfmathsetlengthmacro\forest@forestcs@s{#1}% + \forest@forestcs@ls + }, + .unknown/.code={% + \expandafter\pgfutil@in@\expandafter.\expandafter{\pgfkeyscurrentname}% + \ifpgfutil@in@ + \expandafter\forest@forestcs@namegoanchor\pgfkeyscurrentname\forest@end + \else + \expandafter\forest@nameandgo\expandafter{\pgfkeyscurrentname}% + \forest@forestcs@resetxy + \fi + } +} +\def\forest@forestcs@resetxy{% + \ifnum\forest@cn=0 \forest@cs@invalidnodeerror\fi + \global\pgf@x\forestove{x}% + \global\pgf@y\forestove{y}% +} +\def\forest@forestcs@ls{% + \ifdefined\forest@forestcs@l + \ifdefined\forest@forestcs@s + {% + \pgftransformreset + \pgftransformrotate{\forestove{grow}}% + \pgfpointtransformed{\pgfpoint{\forest@forestcs@l}{\forest@forestcs@s}}% + }% + \global\advance\pgf@x\forestove{x}% + \global\advance\pgf@y\forestove{y}% + \fi + \fi +} +\def\forest@forestcs@anchor#1{% + \edef\forest@marshal{% + \noexpand\forest@original@tikz@parse@node\relax + (\forestove{name}\ifx\relax#1\relax\else.\fi#1)% + }\forest@marshal +} +\def\forest@forestcs@namegoanchor#1.#2\forest@end{% + \forest@nameandgo{#1}% + \ifnum\forest@cn=0 \forest@cs@invalidnodeerror\fi + \forest@forestcs@anchor{#2}% +} +\def\forest@cs@invalidnodeerror{% + \PackageError{forest}{Attempt to refer to the invalid node by "forest cs"}{}% +} +\tikzdeclarecoordinatesystem{forest}{% + \forest@forthis{% + \forest@forestcs@resetxy + \ifdefined\forest@forestcs@l\undef\forest@forestcs@l\fi + \ifdefined\forest@forestcs@s\undef\forest@forestcs@s\fi + \pgfqkeys{/forest/@cs}{#1}% + }% +} +\def\forest@tikz@parse@node#1(#2){% + \pgfutil@in@.{#2}% + \ifpgfutil@in@ + \expandafter\forest@tikz@parse@node@checkiftikzname@withdot + \else% + \expandafter\forest@tikz@parse@node@checkiftikzname@withoutdot + \fi% + #1(#2)\forest@end +} +\def\forest@tikz@parse@node@checkiftikzname@withdot#1(#2.#3)\forest@end{% + \forest@tikz@parse@node@checkiftikzname#1{#2}{.#3}} +\def\forest@tikz@parse@node@checkiftikzname@withoutdot#1(#2)\forest@end{% + \forest@tikz@parse@node@checkiftikzname#1{#2}{}} +\def\forest@tikz@parse@node@checkiftikzname#1#2#3{% + \expandafter\ifx\csname pgf@sh@ns@#2\endcsname\relax + \forest@forthis{% + \forest@nameandgo{#2}% + \ifnum\forest@cn=0 \forest@cs@invalidnodeerror\fi + \edef\forest@temp@relativenodename{\forestove{name}}% + }% + \else + \def\forest@temp@relativenodename{#2}% + \fi + \expandafter\forest@original@tikz@parse@node\expandafter#1\expandafter(\forest@temp@relativenodename#3)% +} +\def\forest@nameandgo#1{% + \pgfutil@in@!{#1}% + \ifpgfutil@in@ + \forest@nameandgo@(#1)% + \else + \ifstrempty{#1}{}{\edef\forest@cn{\forest@node@Nametoid{#1}}}% + \fi +} +\def\forest@nameandgo@(#1!#2){% + \ifstrempty{#1}{}{\edef\forest@cn{\forest@node@Nametoid{#1}}}% + \forest@go{#2}% +} +\forestset{ + declare count={rotate}{0}, + autoforward'={rotate}{node options}, +} +\newif\ifforest@anchor@snapbordertocompass +\newif\ifforest@anchor@forwardtotikz +\newif\ifforest@anchor@isborder +\def\forestanchortotikzanchor#1#2{% #1 = forest anchor, #2 = macro to receive the tikz anchor + \forest@anchor@forwardtotikzfalse + \forest@anchor@do{}{#1}{\forest@cn}% + \let#2\forest@temp@anchor +} +\pgfdeclaregenericanchor{child anchor}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{child anchor}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{parent anchor}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{parent anchor}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{anchor}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{anchor}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{children}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{children}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{children first}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{children first}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{first}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{first}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{parent first}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{parent first}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{parent}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{parent}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{parent last}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{parent last}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{last}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{last}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{children last}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{children last}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{children'}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{children'}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{children first'}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{children first'}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{first'}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{first'}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{parent first'}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{parent first'}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{parent'}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{parent'}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{parent last'}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{parent last'}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{last'}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{last'}{\forest@referencednodeid}% +} +\pgfdeclaregenericanchor{children last'}{% + \forest@anchor@forwardtotikztrue + \forest@anchor@do{#1}{children last'}{\forest@referencednodeid}% +} +\def\forest@anchor@do#1#2#3{% #1 = shape name, #2 = (potentially) forest anchor, #3 = node id + \forest@fornode{#3}{% + \def\forest@temp@anchor{#2}% + \forest@anchor@snapbordertocompassfalse + \forest@anchor@isborderfalse + \forest@anchor@to@tikz@anchor + \forest@anchor@border@to@compass + \ifforest@anchor@forwardtotikz + \forest@anchor@forward{#1}% + \else + \fi + }% +} +\def\forest@anchor@to@tikz@anchor{% + \ifcsdef{forest@anchor@@\forest@temp@anchor}{% + \csuse{forest@anchor@@\forest@temp@anchor}% + \forest@anchor@to@tikz@anchor + }{}% +} +\csdef{forest@anchor@@parent anchor}{% + \forestoget{parent anchor}\forest@temp@anchor} +\csdef{forest@anchor@@child anchor}{% + \forestoget{child anchor}\forest@temp@anchor} +\csdef{forest@anchor@@anchor}{% + \forestoget{anchor}\forest@temp@anchor} +\csdef{forest@anchor@@children'}{% + \forest@anchor@isbordertrue + \edef\forest@temp@anchor{\number\numexpr\forestove{grow}-\forestove{rotate}}% +} +\csdef{forest@anchor@@parent'}{% + \forest@anchor@isbordertrue + \edef\forest@temp@anchor{\number\numexpr\forestove{grow}-\forestove{rotate}+180}% +} +\csdef{forest@anchor@@first'}{% + \forest@anchor@isbordertrue + \edef\forest@temp@anchor{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 -\else+\fi90}% +} +\csdef{forest@anchor@@last'}{% + \forest@anchor@isbordertrue + \edef\forest@temp@anchor{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 +\else-\fi90}% +} +\csdef{forest@anchor@@parent first'}{% + \forest@anchor@isbordertrue + \edef\forest@temp@anchor@parent{\number\numexpr\forestove{grow}-\forestove{rotate}+180}% + \edef\forest@temp@anchor@first{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 -\else+\fi90}% + \forest@getaverageangle{\forest@temp@anchor@parent}{\forest@temp@anchor@first}\forest@temp@anchor +} +\csdef{forest@anchor@@parent last'}{% + \forest@anchor@isbordertrue + \edef\forest@temp@anchor@parent{\number\numexpr\forestove{grow}-\forestove{rotate}+180}% + \edef\forest@temp@anchor@last{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 +\else-\fi90}% + \forest@getaverageangle{\forest@temp@anchor@parent}{\forest@temp@anchor@last}\forest@temp@anchor +} +\csdef{forest@anchor@@children first'}{% + \forest@anchor@isbordertrue + \edef\forest@temp@anchor@first{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 -\else+\fi90}% + \forest@getaverageangle{\forestove{grow}-\forestove{rotate}}{\forest@temp@anchor@first}\forest@temp@anchor +} +\csdef{forest@anchor@@children last'}{% + \forest@anchor@isbordertrue + \edef\forest@temp@anchor@last{\number\numexpr\forestove{grow}-\forestove{rotate}\ifnum\forestove{reversed}=0 +\else-\fi90}% + \forest@getaverageangle{\forestove{grow}-\forestove{rotate}}{\forest@temp@anchor@last}\forest@temp@anchor +} +\csdef{forest@anchor@@children}{% + \forest@anchor@snapbordertocompasstrue + \csuse{forest@anchor@@children'}% +} +\csdef{forest@anchor@@parent}{% + \forest@anchor@snapbordertocompasstrue + \csuse{forest@anchor@@parent'}% +} +\csdef{forest@anchor@@first}{% + \forest@anchor@snapbordertocompasstrue + \csuse{forest@anchor@@first'}% +} +\csdef{forest@anchor@@last}{% + \forest@anchor@snapbordertocompasstrue + \csuse{forest@anchor@@last'}% +} +\csdef{forest@anchor@@parent first}{% + \forest@anchor@snapbordertocompasstrue + \csuse{forest@anchor@@parent first'}% +} +\csdef{forest@anchor@@parent last}{% + \forest@anchor@snapbordertocompasstrue + \csuse{forest@anchor@@parent last'}% +} +\csdef{forest@anchor@@children first}{% + \forest@anchor@snapbordertocompasstrue + \csuse{forest@anchor@@children first'}% +} +\csdef{forest@anchor@@children last}{% + \forest@anchor@snapbordertocompasstrue + \csuse{forest@anchor@@children last'}% +} +\def\forest@getaverageangle#1#2#3{% + \edef\forest@temp{\number\numexpr #1-#2+540}% + \pgfmathMod{\forest@temp}{360}\pgfmathtruncatemacro\pgfmathresult{\pgfmathresult} + \edef\forest@temp{360+#2+((\pgfmathresult-180)/2)}% + \pgfmathMod{\forest@temp}{360}\pgfmathtruncatemacro#3{\pgfmathresult}% +} +\def\forest@anchor@border@to@compass{% + \ifforest@anchor@isborder + \ifforest@anchor@snapbordertocompass + \forest@anchor@snap@border@to@compass + \else + \pgfmathMod{\forest@temp@anchor}{360}% + \pgfmathtruncatemacro\forest@temp@anchor{\pgfmathresult}% + \fi + \ifforest@anchor@forwardtotikz + \ifcsname pgf@anchor% + @\csname pgf@sh@ns@\pgfreferencednodename\endcsname + @\csname forest@compass@\forest@temp@anchor\endcsname + \endcsname + \letcs\forest@temp@anchor{forest@compass@\forest@temp@anchor}% + \fi + \else + \ifforest@anchor@snapbordertocompass + \letcs\forest@temp@anchor{forest@compass@\forest@temp@anchor}% + \fi + \fi + \fi +} +\csdef{forest@compass@0}{east} +\csdef{forest@compass@45}{north east} +\csdef{forest@compass@90}{north} +\csdef{forest@compass@135}{north west} +\csdef{forest@compass@180}{west} +\csdef{forest@compass@225}{south west} +\csdef{forest@compass@270}{south} +\csdef{forest@compass@315}{south east} +\csdef{forest@compass@360}{east} +\def\forest@anchor@snap@border@to@compass{% + \pgfmathMod{\forest@temp@anchor}{360}% + \pgfmathdivide{\pgfmathresult}{45}% + \pgfmathround{\pgfmathresult}% + \pgfmathmultiply{\pgfmathresult}{45}% + \pgfmathtruncatemacro\forest@temp@anchor{\pgfmathresult}% +} +\def\forest@anchor@forward#1{% #1 = shape name + \ifdefempty\forest@temp@anchor{% + \pgf@sh@reanchor{#1}{center}% + \xdef\forest@hack@tikzshapeborder{% + \noexpand\tikz@shapebordertrue + \def\noexpand\tikz@shapeborder@name{\pgfreferencednodename}% + }\aftergroup\forest@hack@tikzshapeborder + }{% + \pgf@sh@reanchor{#1}{\forest@temp@anchor}% + }% +} +\def\forest@referencednodeid{\forest@node@Nametoid{\forest@referencednodename}}% +\def\forest@referencednodename{% + \expandafter\expandafter\expandafter\forest@referencednodename@\expandafter\pgfreferencednodename\forest@pgf@notyetpositioned\relax +} +\expandafter\def\expandafter\forest@referencednodename@\expandafter#\expandafter1\forest@pgf@notyetpositioned#2\relax{% + \if\relax#1\relax\forest@referencednodename@stripafter#2\relax\fi + \if\relax#2\relax#1\fi +} +\expandafter\def\expandafter\forest@referencednodename@stripafter\expandafter#\expandafter1\forest@pgf@notyetpositioned\relax{#1} +\def\forest@Pointanchor#1#2{% #1 = node id, #2 = anchor + {% + \def\forest@pa@temp@name{name}% + \forestOifdefined{#1}{@box}{% + \forestOget{#1}{@box}\forest@temp + \ifdefempty\forest@temp{}{% + \def\forest@pa@temp@name{later@name}% + }% + }{}% + \setbox0\hbox{% + \begin{pgfpicture}% + \if\relax\forestOve{#1}{#2}\relax + \pgfpointanchor{\forestOve{#1}{\forest@pa@temp@name}}{center}% + \else + \pgfpointanchor{\forestOve{#1}{\forest@pa@temp@name}}{\forestOve{#1}{#2}}% + \fi + \xdef\forest@global@marshal{% + \noexpand\global\noexpand\pgf@x=\the\pgf@x\relax + \noexpand\global\noexpand\pgf@y=\the\pgf@y + }% + \end{pgfpicture}% + }% + }% + \forest@global@marshal +} +\def\forest@pointanchor#1{% #1 = anchor + \forest@Pointanchor{\forest@cn}{#1}% +} +\ifdefempty{\forest@compat}{}{% + \RequirePackage{forest-compat} +} +\endinput +%% +%% End of file `forest.sty'. diff --git a/growingwave.sty b/growingwave.sty new file mode 100755 index 0000000..9420e8d --- /dev/null +++ b/growingwave.sty @@ -0,0 +1,125 @@ +\def\pgfdecorationgrowthstart{0cm} +\def\pgfdecorationgrowthendsizelist{0cm} +\def\pgfdecorationgrowthwavelengthlist{0cm} +\def\pgfdecorationgrowthendstepslist{1} +\def\pgfdecorationgrowthendstep{1} +\newif\ifpgfdecorationgrowthsine +\newif\ifpgfdecorationgrowthcosine +\newif\ifpgfdecorationonewavelength +\pgfdecorationgrowthcosinefalse +\pgfdecorationgrowthsinetrue +\pgfkeys{% + /pgf/decoration/.cd, + growth start size/.initial=0.5cm, + growth end size/.initial=3cm, + growth end steps/.initial=1, + growth wave length/.initial=3pt, + growth sine/.code={\pgfdecorationgrowthsinetrue\pgfdecorationgrowthcosinefalse}, + growth cosine/.code={\pgfdecorationgrowthsinefalse\pgfdecorationgrowthcosinetrue} +} +\def\pgfdecorationgrowthsetup{% + \global\edef\pgfdecorationgrowthstart{\pgfkeysvalueof{/pgf/decoration/growth start size}}% + \global\edef\pgfdecorationgrowthendsizelist{\pgfkeysvalueof{/pgf/decoration/growth end size}}% + \global\edef\pgfdecorationgrowthendstepslist{\pgfkeysvalueof{/pgf/decoration/growth end steps}}% + \global\edef\pgfdecorationgrowthwavelengthlist{\pgfkeysvalueof{/pgf/decoration/growth wave length}}% +} + +\def\pgfdecorationgrowthsteps{1} % To keep track of steps from ending +\def\pgfdecorationliststeps{2} % To keep track of list items from ending, has to start from 2 + +\pgfdeclaredecoration{growth wave}{initial}% +{ + \state{initial}[width=0pt,next state=first] {% + \pgfdecorationgrowthsetup% + \pgfpathlineto{\pgfqpoint{0pt}{0pt}}% + \global\edef\pgfdecorationgrowthsteps{0}% + \global\edef\pgfdecorationliststeps{2}% + \foreach \endsize in \pgfdecorationgrowthendsizelist {% + \global\edef\pgfdecorationgrowthendsize{\endsize}% + \breakforeach% + }% + \foreach \growthstep in \pgfdecorationgrowthendstepslist {% + \global\edef\pgfdecorationgrowthendstep{\growthstep}% + \breakforeach% + }% + \foreach \wavelength in \pgfdecorationgrowthwavelengthlist {% + \global\edef\pgfdecorationgrowthwavelength{\wavelength}% + \breakforeach% + }% + \pgfmathparse{(\pgfdecorationgrowthendsize - \pgfdecorationgrowthstart) * 2 * % + \pgfdecorationgrowthwavelength / ( \pgfdecoratedremainingdistance * \pgfdecorationgrowthendstep)}% + \global\edef\pgfdecorationgrowth{\pgfmathresult}% + }% + + \state{first}[width=2*\pgfdecorationgrowthwavelength,next state=second] {% + \pgfdecorationgrowthstepcounters% + \pgfmathparse{\pgfdecorationgrowthstart + \pgfdecorationgrowthsteps * \pgfdecorationgrowth}% + % The wave starts + \ifpgfdecorationgrowthsine% + \pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}% + \pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}% + \fi% + \ifpgfdecorationgrowthcosine% + \pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}% + \pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}% + \fi% + \pgfdecorationgrowthstateend% + }% + + \state{second}[width=2*\pgfdecorationgrowthwavelength,next state=first] {% + \pgfdecorationgrowthstepcounters% + \pgfmathparse{\pgfdecorationgrowthstart + \pgfdecorationgrowthsteps * \pgfdecorationgrowth}% + % The wave continues + \ifpgfdecorationgrowthsine% + \pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}% + \pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}% + \fi% + \ifpgfdecorationgrowthcosine% + \pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}% + \pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}% + \fi% + \pgfdecorationgrowthstateend% + } + \state{final} {% + \pgfpathlineto{\pgfpointdecoratedpathlast}% + }% +} +\def\pgfdecorationgrowthstateend{% + \pgfmathadd{\pgfdecorationgrowthsteps}{1}% + \global\edef\pgfdecorationgrowthsteps{\pgfmathresult} % Redefine the steps counter, globally. +} + +\def\pgfdecorationgrowthstepcounters{% + \pgfmathparse{\pgfdecorationgrowthendstep * \pgfdecoratedpathlength} + \ifdim\pgfdecoratedcompleteddistance>\pgfmathresult pt% + \foreach \endsize [count=\count] in \pgfdecorationgrowthendsizelist {% + \ifnum\count=\pgfdecorationliststeps% + \global\edef\pgfdecorationgrowthendsize{\endsize}% + \breakforeach% + \else% + \global\edef\pgfdecorationgrowthstart{\endsize}% + \fi% + }% + \global\edef\tempa{0}% + \foreach \growthstep [count=\count] in \pgfdecorationgrowthendstepslist {% + \ifnum\count=\pgfdecorationliststeps% + \global\edef\pgfdecorationgrowthendstep{\growthstep}% + \breakforeach% + \else% + \global\edef\tempa{\growthstep}% + \fi% + }% + \foreach \wavelength [count=\count] in \pgfdecorationgrowthwavelengthlist {% + \ifnum\count=\pgfdecorationliststeps% + \global\edef\pgfdecorationgrowthwavelength{\wavelength}% + \breakforeach% + \fi% + }% + \pgfmathparse{int(\pgfdecorationliststeps+1)}% + \global\edef\pgfdecorationliststeps{\pgfmathresult}% + \global\edef\pgfdecorationgrowthsteps{0}% Redefine the steps counter, globally. + \pgfmathparse{(\pgfdecorationgrowthendsize-\pgfdecorationgrowthstart) * 2 % + * \pgfdecorationgrowthwavelength / (\pgfdecoratedpathlength * (\pgfdecorationgrowthendstep -\tempa))}% + \global\edef\pgfdecorationgrowth{\pgfmathresult}% + \fi% +} diff --git a/justtrees.sty b/justtrees.sty new file mode 100755 index 0000000..db694f2 --- /dev/null +++ b/justtrees.sty @@ -0,0 +1,165 @@ +x%% Copyright 2016 Clea F. Rees +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3 +% of this license or (at your option) any later version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3 or later is part of all distributions of LaTeX +% version 2005/12/01 or later. +% +% This work has the LPPL maintenance status `maintained'. +% +% The Current Maintainer of this work is Clea F. Rees. +% +% This work consists of the file justtrees.sty. +%% +\NeedsTeXFormat{LaTeX2e} +\RequirePackage{svn-prov} +\ProvidesPackageSVN{$Id: justtrees.sty 4959 2016-05-27 23:00:49Z cfrees $}[v0.08 \revinfo] +\RequirePackage{forest} +\newlength{\justtrees@tempa} +\tikzset{% + justifier format/.style={font=\justtrees@justifier@font}, + justifier font/.store in=\justtrees@justifier@font, + justifier font=\normalfont\normalsize, + left justifier format/.style={}, + right justifier format/.style={}, +} +\forestset{% + declare boolean register={left justifiers},% left justifications + not left justifieers, + declare boolean register={right justifiers},% right justifications + not right justifiers, + declare dimen register={left justifiers width}, + left justifiers width'=0pt, + declare dimen register={right justifiers width}, + right justifiers width'=0pt, + declare toks register={left justifiers align}, + left justifiers align={right}, + declare toks register={right justifiers align}, + right justifiers align={left}, + declare boolean register={empty nodes}, + empty nodes, + just format/.style={% + /tikz/justifier format/.append style={#1}, + }, + left just format/.style={% + /tikz/left justifier format/.append style={#1}, + }, + right just format/.style={% + /tikz/right justifier format/.append style={#1}, + }, + left justifications/.style={% + left justifiers, + }, + right justifications/.style={% + right justifiers, + }, + left just align/.style={% + left justifiers align=#1, + if={strequal(left_justifiers_align,"right")}{} + {% + left just/.append style={% + TeX={\settowidth\justtrees@tempa{\justtrees@justifier@font ##1}}, + if={\justtrees@tempa>left_justifiers_width} + {% + left justifiers width=\justtrees@tempa, + }{} + }, + }, + }, + right just align/.style={% + right justifiers align=#1, + if={strequal(right_justifiers_align,"left")}{} + {% + right just/.append style={% + TeX={\settowidth\justtrees@tempa{\justtrees@justifier@font ##1}}, + if={\justtrees@tempa>right_justifiers_width} + {% + right justifiers width=\justtrees@tempa, + }{} + }, + }, + }, + right just/.style={% + right justifiers, + tikz+/.wrap pgfmath arg={% + \node (right just ##1) [anchor=base west, justifier format, right justifier format] at (.base -| just tree east) {#1}; + }{level()} + }, + left just/.style={% + left justifiers, + tikz+/.wrap pgfmath arg={% + \node (left just ##1) [anchor=base east, justifier format, left justifier format] at (.base -| just tree west) {#1}; + }{level()} + }, + just/.style={% + if right justifiers={% + right just={#1} + }{% + if left justifiers={% + left just={#1}, + }{% + right just={#1}, + }, + }, + }, + just tree/.style={% + for tree={% + parent anchor=children, + before typesetting nodes={% + if empty nodes={% + where content={}{% + shape=coordinate, + }{} + }{}, + }, + }, + where level=0{% + tikz+={% + \coordinate (just tree north) at (current bounding box.north); + \coordinate (just tree south) at (current bounding box.south); + \coordinate (just tree west) at (current bounding box.west); + \coordinate (just tree east) at (current bounding box.east); + }, + for children={% + no edge, + }, + before typesetting nodes={% + if content={}{phantom}{}, + }, + }{}, + before packing={% + for tree={% + tier/.wrap pgfmath arg={tier ##1}{level()}, + }, + }, + before drawing tree={% + if={strequal(left_justifiers_align,"right")}{} + {% + left just format={% + text width/.register=left justifiers width, + align/.register=left justifiers align, + }, + }, + if={strequal(right_justifiers_align,"left")}{} + {% + right just format={% + text width/.register=right justifiers width, + align/.register=right justifiers align, + }, + }, + }, + }, +} +\environbodyname\justtreebody +\bracketset{action character=@} +\NewEnviron{justtree}[1]{% \forest/\endforest from egreg's answer at http://tex.stackexchange.com/a/229608/ + \forest + just tree, + #1, + [@\justtreebody] + \endforest} +\endinput +%% end justtrees.sty \ No newline at end of file diff --git a/main.tex b/main.tex index 9132705..9f68101 100644 --- a/main.tex +++ b/main.tex @@ -33,8 +33,8 @@ \usepackage{forest} \usepackage{tikz,datetime} \usetikzlibrary{decorations.pathreplacing,trees,calc,fit,positioning,chains,arrows,arrows.meta,automata,shapes,graphs,shapes.geometric,shapes.symbols, -decorations.markings,patterns,matrix,decorations.pathmorphing,mindmap,math} -%,triangle-fit,decorations.growingwave,oni-squiggly} +decorations.markings,patterns,matrix,decorations.pathmorphing,mindmap,math, +triangle-fit,decorations.growingwave,oni-squiggly} \usepackage{pgf} \usepackage{pgfplots} \usepackage{graphicx} @@ -53,20 +53,19 @@ decorations.markings,patterns,matrix,decorations.pathmorphing,mindmap,math} \restoresymbol{bb}{Cross}% Restore original \Cross from marvosym + rename bbding's \Cross to \bbCross. \usepackage{relsize} \usepackage{wasysym} -%\usepackage{growingwave} +\usepackage{growingwave} \pgfdeclarelayer{background} \pgfdeclarelayer{foreground} \pgfsetlayers{background,main,foreground} \usepackage{epigraph} -%\usepackage{oni-trees} -%\usepackage{oni-tree-defaults} +\usepackage{oni-trees} +\usepackage{oni-tree-defaults} %\usepackage[backend=bibtex,style=authoryear,natbib=true,maxbibnames=99]{biblatex} %% User the bibtex backend with the authoryear citation style (which %% resembles APA) \usepackage{tikz,datetime} \usetikzlibrary{decorations.pathreplacing,trees,calc,fit,positioning,chains,arrows,arrows.meta,automata,shapes,graphs,shapes.geometric,shapes.symbols, -decorations.markings,patterns,matrix,decorations.pathmorphing,mindmap,math} -%,triangle-fit,decorations.growingwave,oni-squiggly} +decorations.markings,patterns,matrix,decorations.pathmorphing,mindmap,math,triangle-fit,decorations.growingwave,oni-squiggly} \usepackage{pgf} \usepackage{pgfplots} \usepackage{graphicx} @@ -413,6 +412,7 @@ subset that is disjoint from an operation's \emph{frame}, i.e. the state subset it modifies. \subsection{Methodology} +\label{sec:methodology} To this end, we propose a solution based on static analysis which does not require any additional frame annotations. By detecting the subset @@ -2241,6 +2241,235 @@ ti $\mapsto$ $\top$\\ \subsection{An inter-procedural extension} \section{Correlation analysis} +\input{correlation-macros} + +Recall from Section~\ref{sec:methodology} that our overall methodology +for tackling the frame problem consists in combining a dependency +analysis with a correlation analysis, that identifies what part of the +input is copied to the output without being modified. +% +In this section, we present a static +\emph{correlation} analysis which, when given a predicate that manipulates a +structured input, determines automatically the subset of the input that remains +unchanged and is further propagated into the output. Thus, the behaviour of a +predicate is summarised by computing relations between parts of the input and +parts of the output. + +%The computed \emph{correlation summaries} are a safe +%approximation of what part of an input state of a predicate is copied to the +%output state. + +The correlation analysis is a conservative static analysis inferring what is +modified by an operation and to what extent. It approximates the flow of input +values into output values, by uncovering \emph{equalities} and computing +\emph{correlations} as pairs between input parts and the output parts +into which these are injected. What is marked as being equal is +definitely equal. As equalities iin general only pertain to parts of a data +structure, we shall formalize them as \emph{partial equivalence +relations} on structured data. + +\begin{figure}[!h] +\minipage[c]{\textwidth} +\centering + \centering + \begin{forest} + oni tree defaults, + [, % Start directly with a comma: no node contents + phantom,% phantom == invisible node, just here for the layout. It is the fake "common ancestor" to both trees shown in this diagram + s sep=3.5cm,% Trees have two axes for layout s (sibling), the "horizontal" axis, and l (level), the "vertical" axis. Make the two trees separated by a centimeter + % + % Do not leave blank lines, always put a % when you want to skip a line, otherwise it crashes forest + %First + [, dot tree,name=ba1, triangle fit whole subtree={bottom space=.15cm},% start squiggly tree, + [,zag=6mm, + [;$\pi$, zig=3mm, + [,name=o1, zag=3mm, triangle fit whole subtree={triangle sep=1mm, bottom space=0.01cm, iburg,}, %pattern=north east lines, pattern color=iburg}, + [, name=d1, invisible tree, + ] + ] + ] + ] + [,zig=5mm, + [,zag=2mm, + [, zig=1mm, + [;$\rho$,name=g1, zag=2mm,triangle fit whole subtree={triangle sep=0.5mm, bottom space=0.01cm,draw=caribbeangreen, fill=caribbeangreen}, + [, invisible tree, + ] + ] + ] + ] + ] + ] + %Second + [, dot tree,name=ba2, triangle fit whole subtree={bottom space=.1cm},% start squiggly tree, + [,zag=8mm + [, zig=2mm, + [,name=ax2, zag=7mm, + [,zig =2mm, + [;$\pi'$, name=o2, zag=6mm,triangle fit whole subtree={triangle sep=1mm, bottom space=0.01cm,thick, iburg}, + [, name=d2, invisible tree, + ] + ] + ] + ] + ] + ] + [,zig=4mm + [, zag=2mm, + [;$\rho'$,name=g2, zig=1mm, triangle fit whole subtree={triangle sep=0.5mm, bottom space=0.01cm, draw=caribbeangreen, fill=caribbeangreen}, + [, invisible tree, + ] + ] + ] + ] + ] + ] + \draw[<->, shorten=2pt, thick, caribbeangreen] (g1) edge[bend left] node[above]{$\rel'$} (g2); + \draw[<->, shorten=2pt, thick, iburg] (o1) edge[bend right, out=60] node[below]{$\rel$} (o2); + \end{forest} +\endminipage\hfill +\caption{Intraprocedural Correlations -- General Representation} +\label{cor:fig:intra} +\end{figure} + +Outputs are often complex compounds of different subparts of different +input variables: a subset of the input is modified, while the rest is +injected as is. We track the origin of subparts of the output and +relate it to subparts of the input. As previously illustrated on our +\disp{stop_thread} example predicate, in order to prevent avoidable +over-approximations, we need to avoid dealing with data in a +monolithic manner. To this end, it is imperative to consider pairs of +different types and granularities as well. As a consequence, we are +forced to introduce an additional level of granularity allowing us to +refer not only to variables, but also to substructures within them. At +the intraprocedural level, illustrated in Figure~\ref{cor:fig:intra}, +we define correlations as mappings between pairs of inputs and outputs +to which we associate mappings between pairs of valid inner paths and +the relations binding them. Correlations for arrays and variants are +exemplified in +Figures~\ref{fig:cor:examples}-a)~and~\ref{fig:cor:examples}-b). + +\begin{figure}[!hbt]\centering +\begin{tabular}{@{}cc@{}} +\toprule +\minipage{0.38\textwidth} + \centering + \begin{tikzpicture}[thick,scale=0.5, every node/.style={scale=0.5}] + % \node[shape=multipart rectangle,parts=2] {a\second b}; + \matrix[matrix of nodes, row sep=0pt, column sep=0pt] (m) { + \phantom{i} & + \phantom{i} & + |[fill=gray!20!white,alias=mi]| \large{i} & + \phantom{i} & + \phantom{i} & + \phantom{i} & + \phantom{i} & + \phantom{i} \\ + }; + + \draw (m-1-1.north west) -- (m-1-8.north east) -- (m-1-8.south east) -- (m-1-1.south west) -- cycle; + \foreach \i in {1,...,7} {% 8 - 1 to not have double line on the last cell. + \draw (m-1-\i.north east) -- (m-1-\i.south east); + } + + \matrix[matrix of nodes, row sep=0pt, column sep=0pt, right=0.5cm of m] (n) { + \phantom{i} & + \phantom{i} & + |[fill=gray!20!white,alias=ni]| \large{i} & + \phantom{i} & + \phantom{i} & + \phantom{i} & + \phantom{i} & + \phantom{i} \\ + }; + + \draw (n-1-1.north west) -- (n-1-8.north east) -- (n-1-8.south east) -- (n-1-1.south west) -- cycle; + \foreach \i in {1,...,7} {% 8 - 1 to not have double line on the last cell. + \draw (n-1-\i.north east) -- (n-1-\i.south east); + } + + \def\braceAmplitude{6pt} + \def\braceRaise{2pt} + + % decoration={…,mirror,…} to have the brace the other way round + \draw (m-1-1.south west) edge[decorate,decoration={brace,amplitude=\braceAmplitude,raise=\braceRaise,mirror}] node[coordinate,yshift=8pt] (mx) {} (m-1-8.south east); + \draw (n-1-1.south west) edge[decorate,decoration={brace,amplitude=\braceAmplitude,raise=\braceRaise,mirror}] node[coordinate,yshift=8pt] (nx) {} (n-1-8.south east); + + % \draw (mi.south) edge[<->,>=stealth,looseness=.5,out=-70,in=-110,shorten <=1.5pt, shorten >=1.5pt] node[below]{\large$\mathcal{R}$} (ni.south); + \draw ([yshift=-1cm]mx) edge[<->,>=stealth,looseness=.5,out=-70,in=-110] node[below]{\large$\rel$} ([yshift=-1cm]nx); + + % Background: + \path[fill=white,opacity=.3] + ($(mi.north west) + (0, \braceAmplitude*0.5+\braceRaise) + (0,1pt)$) + rectangle + ($(mi.north east) + (0, \braceAmplitude*0.5+\braceRaise) - (0,1pt)$); + + \coordinate (miX) at ($(mi.north west) + (0, \braceAmplitude*0.5+\braceRaise) + (1pt,0)$); + \coordinate (miY) at ($(mi.north east) + (0, \braceAmplitude*0.5+\braceRaise) - (.5pt,0)$); + + % \foreach \i in {0,0.2,...,1} { + % \draw[black!70] ($(miX)!\i!(miY)-(1pt,1pt)$) -- ($(miX)!\i!(miY)+(1pt,1pt)$); + % } + + %%%% + + % Background: + \path[fill=white,opacity=.3] + ($(ni.north west) + (0, \braceAmplitude*0.5+\braceRaise) + (0,1pt)$) + rectangle + ($(ni.north east) + (0, \braceAmplitude*0.5+\braceRaise) - (0,1pt)$); + + \coordinate (niX) at ($(ni.north west) + (0, \braceAmplitude*0.5+\braceRaise) + (1pt,0)$); + \coordinate (niY) at ($(ni.north east) + (0, \braceAmplitude*0.5+\braceRaise) - (.5pt,0)$); + \end{tikzpicture} + +\endminipage +\minipage{0.35\textwidth} + \centering + \begin{tikzpicture} [thick,scale=0.55, every node/.style={scale=0.55}] + \pgfmathsetseed{\rndseed} + \triangleArray{n}{(0,0)} + + \pgfmathsetseed{\rndseed} + \triangleArray{m}{($(n-0.south west) + (.5cm,-1cm)$)} + + % Arrows: + \foreach \i in {0,...,\nbnodes} {% + % Centers: tc + % Top: tt, left: tl, right: tr, bottom: tb + \draw (n-tb-\i) edge[<->,>=stealth,out=-90,in=90, shorten <=.5pt, shorten >=.5pt] (m-tt-\i); + } + + \end{tikzpicture} +\endminipage% +\\ +\hspace{-0.1\textwidth}\minipage{0.48\textwidth} +\centering\small a) Arrays: $\;\forall i, \; a{\left[i\right]} \mathbin{\rel} b{\left[i\right]}$ +\endminipage\hspace{-0.1\textwidth} +\minipage{0.25\textwidth} +\centering\small b) Variants +\endminipage +\\ +\bottomrule +\end{tabular} +\caption{Intraprocedural Domain -- Examples} +\label{fig:cor:examples} +\end{figure} + +Similarly to our dependency analysis presented in Chapter~\ref{chapter5}, the +correlation analysis is an interprocedural, flow-sensitive, field-sensitive, +label-sensitive analysis that handles associative arrays, structures and variant +data types. However, unlike the dependency analysis for which we introduced a +relaxed form of context-sensitivity in Chapter~\ref{chapter6}, the correlation +analysis is context-insensitive. Fine-grained equivalence relations between the +inputs and outputs of a predicate are computed once and subsequently propagated +to its callers. + +Our correlation analysis is meant to be used in an interactive verification +context. Precise correlation summaries must be computed quickly in order to +answer effectively, when combined with dependency summaries, queries +regarding the preservation of certain invariants. + \subsection{Introductory example} diff --git a/oni-tree-defaults.sty b/oni-tree-defaults.sty new file mode 100755 index 0000000..e9c9d4c --- /dev/null +++ b/oni-tree-defaults.sty @@ -0,0 +1,35 @@ +\forestset{ + oni tree defaults/.style={ + % These options apply to all nodes in the tree + for tree={ + fit=band,% Use fit=tight for a more compact tree (see the docs at http://mirrors.ctan.org/graphics/pgf/contrib/forest/forest-doc.pdf ) + label style+={% style for labels next to dots: + label distance=1pt, + ellipse, + inner sep=0.5pt, + fill=white!80!black, + fill opacity=0.4,% draw a semi-transparent background + text opacity=1,% but draw the text fully opaque + }, + edge label distance={1mm}, + edge label node style+={% Style for labels next to edges + ellipse, + inner sep=0.5pt, + fill=white!80!black, + fill opacity=0.4,% draw a semi-transparent background + text opacity=1,% but draw the text fully opaque + }, + edge label pin style={ + draw=none, + % draw, + % if edge label swap={bend left}{bend right}, + % densely dotted, + }, + l sep=5mm,% default inter-line separation + }, + for level<={3}{l sep=2mm},% Make the first three rows much thinner + % Adjust a bit the horizontal (sibbling) spacing, because the labels currently are not taken into account. + for level={4}{s sep=.5cm}, + for level={5}{s sep=.5cm}, + } +} \ No newline at end of file diff --git a/oni-trees.sty b/oni-trees.sty new file mode 100755 index 0000000..5c3be7e --- /dev/null +++ b/oni-trees.sty @@ -0,0 +1,308 @@ +\usetikzlibrary{decorations.markings} + +% From http://tex.stackexchange.com/questions/20425/z-level-in-tikz, does not work in this case. +% \makeatletter +% \pgfkeys{% +% /tikz/on layer/.code={ +% \def\tikz@path@do@at@end{\endpgfonlayer\endgroup\tikz@path@do@at@end}% +% \pgfonlayer{#1}\begingroup% +% }% +% } +% \makeatother + + +%%%%%%%%%%% +% Hairy stuff copied from the manual, nothing interesting to see… +\forestStandardNode[.]{% + \forestOve{\csname forest@id@of@standard node\endcsname}{content},% + \the\ht\strutbox,\the\pgflinewidth,% + \pgfkeysvalueof{/pgf/inner ysep},\pgfkeysvalueof{/pgf/outer ysep},% + \pgfkeysvalueof{/pgf/inner xsep},\pgfkeysvalueof{/pgf/outer xsep}% +}{ + l sep={0},%\the\ht\strutbox+\pgfkeysvalueof{/pgf/inner ysep}}, + l={l_sep()+abs(max_y()-min_y())+2*\pgfkeysvalueof{/pgf/outer ysep}}, + s sep={2*\pgfkeysvalueof{/pgf/inner xsep}} +}{ + l sep,l,s sep +} +%%%%%%%%%%% + +% Beamer animation stuff: +\forestset{ + all opacities/.style={opacity=#1,draw opacity=#1,fill opacity=#1,text opacity=#1,}, + invisible/.style={ + all opacities=0, + edge={/forest/all opacities=0,}, + label style={/forest/all opacities=0,}, + edge label node style={opacity=0,draw opacity=0,fill opacity=0,text opacity=0,}, + edge label pin style={opacity=0,draw opacity=0,fill opacity=0,text opacity=0,}, + }, + invisible tree/.style={for tree={invisible},}, + alt/.code args={<#1>#2#3}{ + \alt<#1>{ + \pgfkeysalso{#2} + }{ + \pgfkeysalso{#3} + } + }, + only/.code args={<#1>#2}{ + \only<#1>{ + \pgfkeysalso{#2} + } + }, + only not/.code args={<#1>#2}{ + \alt<#1>{ + }{ + \pgfkeysalso{#2} + } + }, +} + +\tikzset{ + % only/.forward to={/forest/only}, + % only not/.forward to={/forest/only not}, + % all opacities/.forward to={/forest/all opacities}, + all opacities/.style={opacity=#1,draw opacity=#1,fill opacity=#1,text opacity=#1,}, + invisible/.style={all opacities=0,}, + alt/.code args={<#1>#2#3}{ + \alt<#1>{ + \pgfkeysalso{#2} + }{ + \pgfkeysalso{#3} + } + }, + only/.code args={<#1>#2}{ + \only<#1>{ + \pgfkeysalso{#2} + } + }, + only not/.code args={<#1>#2}{ + \alt<#1>{ + }{ + \pgfkeysalso{#2} + } + }, +} + +% Handy node walk from one node to some ancestor +\forestset{ + define long step={current if not name}{n args=1}{if={strequal(name("!current"),"#1")}{}{current}}, + define long step={ancestors from after name until before name}{n args=2}{if={strequal("#1","#2")}{}{fake={name=#1},ancestors until before name=#2}}, + define long step= {ancestors until before name}{n args=1}{if={strequal(name("!parent"),"#1")}{}{parent,ancestors until before name=#1,last valid}}, + define long step={current and ancestors until before name}{n args=1}{current if not name=#1,ancestors until before name=#1}, + define long step= {ancestors until name}{n args=1}{ancestors until before name=#1,name=#1}, + define long step={current and ancestors until name}{n args=1}{current if not name=#1,ancestors until before name=#1,name=#1}, + declare toks={highlight path/from}{}, + declare toks={highlight path/to}{}, + declare toks={highlight path/first}{}, + declare toks={highlight path/mid}{}, + declare toks={highlight path/last}{}, + declare toks={highlight path/edges}{}, + highlight path/.style={ + highlight path/.cd, + #1 + /forest/.cd, + if={strequal(\forestoption{highlight path/from}, "")}{ + /utils/exec={\pgfmathsetmacro\highlightPathFrom{name()}}, + highlight path/from={\highlightPathFrom}, + }{ + }, + for name/.expanded={\forestoption{highlight path/from}}{ + \forestoption{highlight path/first}, + if={strequal("\foresteoption{highlight path/from}","\foresteoption{highlight path/to}")}{ + }{ + edge+={\forestoption{highlight path/edges},}, + }, + }, + % For some reason, putting \foresteoption{highlight path/to} directly in + % the second argument of "for ancestors from after name until before name" + % causes an error, so we're expanding it first into a macro. + /utils/exec={\edef\highlightPathTo{\foresteoption{highlight path/to}}}, + for ancestors from after name until before name/.expanded={\foresteoption{highlight path/from}}{\highlightPathTo}{ + \forestoption{highlight path/mid}, + edge+={\forestoption{highlight path/edges},}, + }, + for name/.expanded={\forestoption{highlight path/to}}{\forestoption{highlight path/last}}, + }, +} + +% These keys are available by default only in "\begin{forest}…\end{forest}", +% but not in "\begin{tikzpicture}…\end{tikzpicture}". This is because the +% full key name is "/forest/foo", instead of "/tikz/foo", and +% "\begin{forest}" searches inside "/forest/" by default, whereas +% "\begin{tikzpicture}" searches inside "/tikz/" by default. +\tikzset{ + shorten/.style={shorten <=#1, shorten >=#1,},% Convenient alias to shorten the edge on both sides by the same amount + edge label distance/.forward to={/forest/edge label distance},% Alias for the forest-specific edge label distance declared below +} +\forestset{ + % Circumvent bug in if={strequal("a","b")}{}{} when a or b contain math accents. + % Because math accents are expressed with \mathaccent "1234, the extra " character + % breaks the string, and I don't see an obvious way to escape it. This bug probably + % still lurks in all uses of strequal() in this and other files. + % Note this is defined as the /forest/ifstrequal key, not as /tikz/ifstrequal + ifstrequal/.code n args={4}{ + \ifthenelse{\equal{#1}{#2}}{% + \forestset{#3}% + }{% + \forestset{#4}% + }% + },% + % + % Copied and adjusted from the forest manual, section "5.1 Decision tree" page 73 of manual version 2.0.3: + % http://mirrors.ctan.org/graphics/pgf/contrib/forest/forest-doc.pdf + anchors/.style={anchor=#1, child anchor=#1, parent anchor=#1}, + declare keylist={label style}{}, + declare keylist={edge label node style}{}, + declare keylist={edge label pin style}{}, + % edge label node/.style={}, + % edge label pin/.style={}, + declare boolean={edge label swapped}{false}, + edge label swap/.style={ + if={\forestoption{edge label swapped}}{ + edge label swapped=false, + }{ + edge label swapped=true, + } + }, + if edge label swap/.style 2 args={ + if={\forestoption{edge label swapped}}{ + #1 + }{ + #2 + } + }, + /tikz/if edge label swap/.style 2 args={ + /forest/if={\forestoption{edge label swapped}}{ + #1 + }{ + #2 + } + }, + declare dimen={edge label distance}{0pt}, + dot/.default=2pt, + label content/.style={ + ifstrequal={#1}{}{ + % Nothing to do, label is empty. + }{ + % The label is implicitly named (xxx-label), where xxx is the node's name as given with [some label, name=xxx, …] + % But it currently doesn't work + /utils/exec={\pgfmathsetmacro{\dottreenode}{name()}}, + label/.expanded={[alias=\dottreenode-label,\forestoption{label style}]:#1},% #1 is the label content. + }, + }, + % + edge label content/.style={ + % edge label/.expanded={node[\forestoption{edge label style}] {#1}}, + ifstrequal={#1}{}{ + % No label, nothing to do. + }{ + edge={ + postaction={ + draw, + decorate, + decoration={ + markings, + mark=at position 0.5 with { + \tikzmath{ + real \edgeLabelDirection; + if \forestoption{edge label swapped} then { + \edgeLabelDirection = 1; + } else { + \edgeLabelDirection = -1; + }; + } + \coordinate (-mark1) at (0,0); + \coordinate (-mark2) at (0,-\edgeLabelDirection); + \pgftransformresetnontranslations + \tikzmath{ + coordinate \markdiff,\marknorm; + real \markangle; + %% + %% + \markdiff=(-mark2) - (-mark1); + \marknormx=\markdiffx / sqrt(\markdiffx*\markdiffx + \markdiffy*\markdiffy); + \marknormy=\markdiffy / sqrt(\markdiffx*\markdiffx + \markdiffy*\markdiffy); + if \markdiffy == 0 then { + if \markdiffx > 0 then { + if \forestoption{edge label swapped} then { + \markangle = 0; + } else { + \markangle = 180; + }; + } else { + if \forestoption{edge label swapped} then { + \markangle = 0; + } else { + \markangle = 180; + }; + }; + } else { + if \markdiffy > 0 then { + \markangle = acos(\marknormx); + } else { + \markangle = 180+acos(-\marknormx); + }; + }; + } + \tikzset{ + edge label node style exp/.style/.expanded={\forestoption{edge label node style}}, + edge label pin style exp/.style/.expanded={\forestoption{edge label pin style}}, + } + \path (-mark1) ++(\markangle:\forestoption{edge label distance}) node[anchor=180+\markangle, edge label node style exp] (edge label) {#1}; + \path (-mark1) edge[edge label pin style exp] (edge label);%++(\markangle:\forestoption{edge label distance}); + }, + }, + }, + }, + }, + }, + dot/.style={ + % This is delayed into a second processing pass, otheriwse the "content" is re-overridden by the explicitly set content + delay={ + split option={content}{;}{label content,edge label content}, + content={},% Remove the content from the node, as it is typeset into a separate label node. + }, + ellipse, + fill, + inner sep=0pt, + minimum size=2*#1,% You can use […, dot] to get the default radius ("dot/.default=2pt", see just above), or […, dot=5pt] to choose the radius. + }, + dot tree/.style={ + for tree={% These options apply to all nodes in the (sub-)tree + dot,% Draw as a dot, defined above + % Position of the label: + if n children=0{% Leaf node, has "0 children" + label style+={label position=below}, + }{% Non-leaf node + if n=1{% First (leftmost) child, has "current node index = 1" + label style+={label position=left}, + }{% Other child + label style+={label position=right}, + }, + }, + % Position of the edge label: + if n=1{% First (leftmost) child, has "current node index = 1" + edge label swap, + }{% Other child + edge label swap, + }, + }, + label style+={label position=above},% Override the label position for the label of the root node (for this subtree). + % There is no edge label style to override for the root, as it has no incoming edge label. + }, + % Zig-zag distances + declare dimen={zig distance}{.3cm}, + declare dimen={Zig distance}{.5cm}, + declare dimen={ZIG distance}{.7cm}, + % Zigs and zags can easily be swapped globally by puting the minus "-" sign in the zigs instead of the zags, if needed. + zig/.style={edge label swap, calign with current={#1},}, + zig/.default={\forestoption{zig distance}}, + Zig/.style={edge label swap, calign with current={\forestoption{Zig distance}},}, + ZIG/.style={edge label swap, calign with current={\forestoption{ZIG distance}}, for parent={l sep+=.2cm,},}, + % + zag/.style={calign with current={-#1},}, + zag/.default={\forestoption{zig distance}}, + Zag/.style={calign with current={-\forestoption{Zig distance}},}, + ZAG/.style={calign with current={-\forestoption{ZIG distance}}, for parent={l sep+=.2cm,},}, +} diff --git a/tikzlibrarydecorations.growingwave.code.tex b/tikzlibrarydecorations.growingwave.code.tex new file mode 100755 index 0000000..7faad16 --- /dev/null +++ b/tikzlibrarydecorations.growingwave.code.tex @@ -0,0 +1,126 @@ +\usetikzlibrary{decorations.pathreplacing} +\def\pgfdecorationgrowthstart{0cm} +\def\pgfdecorationgrowthendsizelist{0cm} +\def\pgfdecorationgrowthwavelengthlist{0cm} +\def\pgfdecorationgrowthendstepslist{1} +\def\pgfdecorationgrowthendstep{1} +\newif\ifpgfdecorationgrowthsine +\newif\ifpgfdecorationgrowthcosine +\newif\ifpgfdecorationonewavelength +\pgfdecorationgrowthcosinefalse +\pgfdecorationgrowthsinetrue +\pgfkeys{% + /pgf/decoration/.cd, + growth start size/.initial=0.5cm, + growth end size/.initial=3cm, + growth end steps/.initial=1, + growth wave length/.initial=3pt, + growth sine/.code={\pgfdecorationgrowthsinetrue\pgfdecorationgrowthcosinefalse}, + growth cosine/.code={\pgfdecorationgrowthsinefalse\pgfdecorationgrowthcosinetrue} +} +\def\pgfdecorationgrowthsetup{% + \global\edef\pgfdecorationgrowthstart{\pgfkeysvalueof{/pgf/decoration/growth start size}}% + \global\edef\pgfdecorationgrowthendsizelist{\pgfkeysvalueof{/pgf/decoration/growth end size}}% + \global\edef\pgfdecorationgrowthendstepslist{\pgfkeysvalueof{/pgf/decoration/growth end steps}}% + \global\edef\pgfdecorationgrowthwavelengthlist{\pgfkeysvalueof{/pgf/decoration/growth wave length}}% +} + +\def\pgfdecorationgrowthsteps{1} % To keep track of steps from ending +\def\pgfdecorationliststeps{2} % To keep track of list items from ending, has to start from 2 + +\pgfdeclaredecoration{growth wave}{initial}% +{ + \state{initial}[width=0pt,next state=first] {% + \pgfdecorationgrowthsetup% + \pgfpathlineto{\pgfqpoint{0pt}{0pt}}% + \global\edef\pgfdecorationgrowthsteps{0}% + \global\edef\pgfdecorationliststeps{2}% + \foreach \endsize in \pgfdecorationgrowthendsizelist {% + \global\edef\pgfdecorationgrowthendsize{\endsize}% + \breakforeach% + }% + \foreach \growthstep in \pgfdecorationgrowthendstepslist {% + \global\edef\pgfdecorationgrowthendstep{\growthstep}% + \breakforeach% + }% + \foreach \wavelength in \pgfdecorationgrowthwavelengthlist {% + \global\edef\pgfdecorationgrowthwavelength{\wavelength}% + \breakforeach% + }% + \pgfmathparse{(\pgfdecorationgrowthendsize - \pgfdecorationgrowthstart) * 2 * % + \pgfdecorationgrowthwavelength / ( \pgfdecoratedremainingdistance * \pgfdecorationgrowthendstep)}% + \global\edef\pgfdecorationgrowth{\pgfmathresult}% + }% + + \state{first}[width=2*\pgfdecorationgrowthwavelength,next state=second] {% + \pgfdecorationgrowthstepcounters% + \pgfmathparse{\pgfdecorationgrowthstart + \pgfdecorationgrowthsteps * \pgfdecorationgrowth}% + % The wave starts + \ifpgfdecorationgrowthsine% + \pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}% + \pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}% + \fi% + \ifpgfdecorationgrowthcosine% + \pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}% + \pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}% + \fi% + \pgfdecorationgrowthstateend% + }% + + \state{second}[width=2*\pgfdecorationgrowthwavelength,next state=first] {% + \pgfdecorationgrowthstepcounters% + \pgfmathparse{\pgfdecorationgrowthstart + \pgfdecorationgrowthsteps * \pgfdecorationgrowth}% + % The wave continues + \ifpgfdecorationgrowthsine% + \pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}% + \pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}% + \fi% + \ifpgfdecorationgrowthcosine% + \pgfpathsine{\pgfqpoint{\pgfdecorationgrowthwavelength}{\pgfmathresult pt}}% + \pgfpathcosine{\pgfqpoint{\pgfdecorationgrowthwavelength}{-\pgfmathresult pt}}% + \fi% + \pgfdecorationgrowthstateend% + } + \state{final} {% + \pgfpathlineto{\pgfpointdecoratedpathlast}% + }% +} +\def\pgfdecorationgrowthstateend{% + \pgfmathadd{\pgfdecorationgrowthsteps}{1}% + \global\edef\pgfdecorationgrowthsteps{\pgfmathresult} % Redefine the steps counter, globally. +} + +\def\pgfdecorationgrowthstepcounters{% + \pgfmathparse{\pgfdecorationgrowthendstep * \pgfdecoratedpathlength} + \ifdim\pgfdecoratedcompleteddistance>\pgfmathresult pt% + \foreach \endsize [count=\count] in \pgfdecorationgrowthendsizelist {% + \ifnum\count=\pgfdecorationliststeps% + \global\edef\pgfdecorationgrowthendsize{\endsize}% + \breakforeach% + \else% + \global\edef\pgfdecorationgrowthstart{\endsize}% + \fi% + }% + \global\edef\tempa{0}% + \foreach \growthstep [count=\count] in \pgfdecorationgrowthendstepslist {% + \ifnum\count=\pgfdecorationliststeps% + \global\edef\pgfdecorationgrowthendstep{\growthstep}% + \breakforeach% + \else% + \global\edef\tempa{\growthstep}% + \fi% + }% + \foreach \wavelength [count=\count] in \pgfdecorationgrowthwavelengthlist {% + \ifnum\count=\pgfdecorationliststeps% + \global\edef\pgfdecorationgrowthwavelength{\wavelength}% + \breakforeach% + \fi% + }% + \pgfmathparse{int(\pgfdecorationliststeps+1)}% + \global\edef\pgfdecorationliststeps{\pgfmathresult}% + \global\edef\pgfdecorationgrowthsteps{0}% Redefine the steps counter, globally. + \pgfmathparse{(\pgfdecorationgrowthendsize-\pgfdecorationgrowthstart) * 2 % + * \pgfdecorationgrowthwavelength / (\pgfdecoratedpathlength * (\pgfdecorationgrowthendstep -\tempa))}% + \global\edef\pgfdecorationgrowth{\pgfmathresult}% + \fi% +} diff --git a/tikzlibraryoni-squiggly.code.tex b/tikzlibraryoni-squiggly.code.tex new file mode 100755 index 0000000..385d3d1 --- /dev/null +++ b/tikzlibraryoni-squiggly.code.tex @@ -0,0 +1,83 @@ +\usetikzlibrary{decorations.growingwave} +\tikzset{ + small squiggly line fade in/.style={ + -,% No arrow head + shorten >=0pt,%%%%%%%%%%%%%%%%%%%%%%%%% + decorate, + decoration={ + growth wave, + growth start size=0pt, + growth end size=-1pt,%{-1pt,-1pt,0pt},%%%%%%%%% + % growth end steps={0.6,.7}, + %growth end steps={0.2,0.6,1},%%%%%%%% + growth wave length=1pt,%{1pt,1pt,1pt},%%%%% + growth cosine, + % pre length=5mm, + post length=0mm,%%%%%%%%%%%%%%%%%%%%%% + }, + }, + small squiggly line no fade/.style={ + -,% No arrow head + shorten >=0pt,%%%%%%%%%%%%%%%%%%%%%%%%% + decorate, + decoration={ + growth wave, + growth start size=-1pt, + growth end size=-1pt,%{-1pt,-1pt,0pt},%%%%%%%%% + % growth end steps={0.6,.7}, + % growth end steps={0.2,0.6,1}, + growth wave length=1pt,%{1pt,1pt,1pt},%%%%% + growth cosine, + pre length=1pt,%%%%%%%%%%%%%%%% + post length=1pt,%%%%%%%%%%%%%%%%%%%%%% + }, + }, + squiggly line/.style={ + -,% No arrow head + shorten >=0pt,%%%%%%%%%%%%%%%%%%%%%%%%% + decorate, + decoration={ + growth wave, + growth start size=0pt, + growth end size=2pt,%{3pt,0pt}, + % growth end steps={0.6,.7}, + % growth end steps={0.8,1}, + growth wave length=2pt,%{2pt,1pt}, + growth cosine, + % pre length=5mm, + post length=0mm%%%%%%%%%%%%%%%%%%%%%% + }, + }, + squiggly arrow/.style={ + ->, + shorten >=1.5pt, + decorate, + decoration={ + growth wave, + growth start size=0pt, + growth end size=2pt,%{3pt,0pt}, + % growth end steps={0.6,.7}, + % growth end steps={0.8,1}, + growth wave length=2pt,%{2pt,1pt}, + growth cosine, + % pre length=5mm, + post length=2mm + }, + }, +} + +\tikzset{ + /forest/.cd, % Set forest styles + start squiggly tree/.style={ + for children={ + edge={small squiggly line fade in,}, + continue squiggly tree, + } + }, + continue squiggly tree/.style={ + for children={ + edge={small squiggly line no fade,}, + continue squiggly tree, + } + } +} diff --git a/tikzlibrarytree-triangle-fit.code.tex b/tikzlibrarytree-triangle-fit.code.tex new file mode 100755 index 0000000..ec20300 --- /dev/null +++ b/tikzlibrarytree-triangle-fit.code.tex @@ -0,0 +1,182 @@ +% %%%%%%% +% % 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‌​} +% } +% } +% } +% %%%%%%% + +\tikzmath{ + function sign(\x) { + if (\x < 0) then { + return -1; + } else { + if (\x > 0) then { + return 1; + } else { + return 0; + }; + }; + }; +} + +\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 +% }]; +% }, +% }, +% }, +% }, +% } diff --git a/tikzlibrarytriangle-fit.code.tex b/tikzlibrarytriangle-fit.code.tex new file mode 100755 index 0000000..ac5d7c2 --- /dev/null +++ b/tikzlibrarytriangle-fit.code.tex @@ -0,0 +1,189 @@ +% %%%%%%% +% % 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‌​} +% } +% } +% } +% %%%%%%% + +\tikzmath{ + function sign(\x) { + if (\x < 0) then { + return -1; + } else { + if (\x > 0) then { + return 1; + } else { + return 0; + }; + }; + }; +} + +\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/top xshift/.initial=0pt, + triangle fit/top xshift/.default=0pt, + 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=(\pgfkeysvalueof{/tikz/triangle fit/top}) + (\pgfkeysvalueof{/tikz/triangle fit/top xshift},\pgfkeysvalueof{/tikz/triangle fit/top space}+\pgfkeysvalueof{/tikz/triangle fit/triangle sep}); + \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/\sgx/\sgy in {(\i.north east)/1/1,(\i.south east)/1/-1,(\i.south west)/-1/-1,(\i.north west)/-1/1} { + \tikzmath{ + \pt = \ii; + \dx = \ptx - \ttopx; + \dx = \dx + \pgfkeysvalueof{/tikz/triangle fit/triangle sep} * \sgx;%sign(\dx); + \dy = \ttopy - \pty; + \dy = \dy + \pgfkeysvalueof{/tikz/triangle fit/triangle sep} * \sgy;%sign(\dy); + \slope = \dx / \dy; + if \slope > \sloperight then { + \sloperight = \slope; + }; + if \slope < \slopeleft then { + \slopeleft = \slope; + }; + if \dy > \maxdy then { + \maxdy = \dy; + }; + } +% \begin{pgfonlayer}{foreground} +% \path (\ttopx,\ttopy) ++(\dx pt,-\dy pt) node[fill=blue,circle,inner sep=0.3pt] {}; +% \end{pgfonlayer} + \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 background + \begin{pgfonlayer}{background} + \path[/tikz/triangle fit current style, /tikz/triangle fit current background style] + (\ttopx,\ttopy) + -- +(\sloperight*\maxdy pt,-\maxdy pt) + -- +(\slopeleft*\maxdy pt,-\maxdy pt) + -- cycle; + \end{pgfonlayer} + % + % Draw the triangle: + \begin{pgfonlayer}{background}% Draw it on the background, it gives better results for now. + \draw[/tikz/triangle fit current 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.parent anchor, + nodes={\fittriangletop\foresteoption{fit these}}, + #1 + }]; + }, + }, + }, + }, +}