summaryrefslogtreecommitdiff
path: root/graphics
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-03-15 03:01:24 +0000
committerNorbert Preining <norbert@preining.info>2021-03-15 03:01:24 +0000
commit36607734949d1736c36ed7b9f3a12a74d7a8ce86 (patch)
tree16f4b95c6487768dc8c9ab93a82bbcfe6e7f35df /graphics
parent954d393d844eacce4354b6174613f467bcd7a257 (diff)
CTAN sync 202103150301
Diffstat (limited to 'graphics')
-rw-r--r--graphics/pgf/contrib/circuitikz/doc/changelog.tex15
-rw-r--r--graphics/pgf/contrib/circuitikz/doc/circuitikz-context.pdfbin17743 -> 17743 bytes
-rw-r--r--graphics/pgf/contrib/circuitikz/doc/circuitikzmanual.pdfbin1128438 -> 1133938 bytes
-rw-r--r--graphics/pgf/contrib/circuitikz/doc/circuitikzmanual.tex21
-rw-r--r--graphics/pgf/contrib/circuitikz/tex/circuitikz.sty4
-rw-r--r--graphics/pgf/contrib/circuitikz/tex/pgfcircmultipoles.tex2
-rw-r--r--graphics/pgf/contrib/circuitikz/tex/pgfcircquadpoles.tex132
-rw-r--r--graphics/pgf/contrib/circuitikz/tex/pgfcirctripoles.tex257
-rw-r--r--graphics/pgf/contrib/circuitikz/tex/t-circuitikz.tex4
-rw-r--r--graphics/pgf/contrib/sankey/README9
-rw-r--r--graphics/pgf/contrib/sankey/sankey-doc.pdfbin672933 -> 0 bytes
-rw-r--r--graphics/pgf/contrib/sankey/sankey-doc.tex1599
-rw-r--r--graphics/pgf/contrib/sankey/sankey.dtx4678
-rw-r--r--graphics/pgf/contrib/sankey/sankey.ins85
-rw-r--r--graphics/pgf/contrib/sankey/sankey.pdfbin0 -> 942336 bytes
-rw-r--r--graphics/pgf/contrib/sankey/sankey.sty722
-rw-r--r--graphics/pgf/contrib/sankey/tikzlibrarydubins.code.tex361
17 files changed, 5194 insertions, 2695 deletions
diff --git a/graphics/pgf/contrib/circuitikz/doc/changelog.tex b/graphics/pgf/contrib/circuitikz/doc/changelog.tex
index cbf38e1cf8..5b4be6d089 100644
--- a/graphics/pgf/contrib/circuitikz/doc/changelog.tex
+++ b/graphics/pgf/contrib/circuitikz/doc/changelog.tex
@@ -5,6 +5,21 @@ full list of changes.
\begin{itemize}
\item
+ Version 1.3.2 (2021-03-14)
+
+ \begin{itemize}
+ \tightlist
+ \item
+ Added the simplified (2-waves) highpass and lowpass blocks
+ \item
+ Added graphene FETs (suggested by Cees Keyer)
+ \item
+ Added left/right anchors to transistors
+ \item
+ Fixed a bug in flip-flops
+ (https://tex.stackexchange.com/q/587213/38080)
+ \end{itemize}
+\item
Version 1.3.1 (2021-02-20)
\begin{itemize}
diff --git a/graphics/pgf/contrib/circuitikz/doc/circuitikz-context.pdf b/graphics/pgf/contrib/circuitikz/doc/circuitikz-context.pdf
index 047b3dd378..f26913dd19 100644
--- a/graphics/pgf/contrib/circuitikz/doc/circuitikz-context.pdf
+++ b/graphics/pgf/contrib/circuitikz/doc/circuitikz-context.pdf
Binary files differ
diff --git a/graphics/pgf/contrib/circuitikz/doc/circuitikzmanual.pdf b/graphics/pgf/contrib/circuitikz/doc/circuitikzmanual.pdf
index 00a4f91763..d0a6ea3ea3 100644
--- a/graphics/pgf/contrib/circuitikz/doc/circuitikzmanual.pdf
+++ b/graphics/pgf/contrib/circuitikz/doc/circuitikzmanual.pdf
Binary files differ
diff --git a/graphics/pgf/contrib/circuitikz/doc/circuitikzmanual.tex b/graphics/pgf/contrib/circuitikz/doc/circuitikzmanual.tex
index f69ca43b06..1f3d694044 100644
--- a/graphics/pgf/contrib/circuitikz/doc/circuitikzmanual.tex
+++ b/graphics/pgf/contrib/circuitikz/doc/circuitikzmanual.tex
@@ -2595,6 +2595,8 @@ It also has a \texttt{zero} anchor if you need to rotate it about its real cente
\circuitdescbip*{highpass}{highpass}{}
\circuitdescbip*{lowpass}{lowpass}{}
\circuitdescbip*{allpass}{allpass}{}
+ \circuitdescbip*{highpass2}{simplified highpass (with only 2 waves)}{}
+ \circuitdescbip*{lowpass2}{simplified lowpass (with only 2 waves)}{}
\circuitdescbip*{adc}{A/D converter}{}
\circuitdescbip*{dac}{D/A converter}{}
\circuitdescbip*{dsp}{DSP}{}
@@ -2867,6 +2869,13 @@ Basically they are the same as the normal \texttt{npn} and \texttt{pnp}, and the
\circuitdesc{isfet}{isfet}{Q}
\end{groupdesc}
+\textsc{Graphene fet} have been added in version \texttt{1.3.2}\footnote{added by Romano Giannetti after a suggestion by Cees Keyer.}. They look better if you set \texttt{transistors/arrow pos=end} and \texttt{transistor/thickness=3} or higher for them, so they are plotted with this option here.
+\begin{groupdesc}
+ \ctikzset{transistors/thickness=3, transistors/arrow pos=end}
+ \circuitdesc*{ngfet}{N-type graphene FET}{Q}(outer hex up/45/0.3, outer hex down/-45/0.3, right/0/0.4)
+ \circuitdesc*{pgfet}{pgfet}{Q}(inner hex up/135/0.3, inner hex down/-135/0.3)
+\end{groupdesc}
+
\subsubsection{Transistor texts (labels)}\label{sec:transistors-labels}
In versions before \texttt{0.9.7}, transistors text (the node text) was positioned near the collector terminal; since version \texttt{0.9.7} the default has been changed to a more natural position near the center of the device, similar to the multi-teminal transistors. You can revert to the old behavior locally with the key \texttt{legacy transistors text}, or globally by setting the package option \texttt{legacytransistorstext}.
@@ -2918,7 +2927,7 @@ You can go back to the no-arrows mos with \texttt{noarrowmos} locally or with
\texttt{\textbackslash ctikzset\{tripoles/mos style/no arrows\}}.
-\paragraph{Circles.} Since \texttt{1.2.6}, you can add a circle\footnote{Suggested by Matthias Jung \href{https://github.com/circuitikz/circuitikz/issues/442}{on GitHub}} to most of the transistor shapes --- with the exception of multi-terminal ones (\texttt{bjtnpn} and \texttt{bjtpnp}, where it would be awkward anyway). The circle is intended in some case as the component's housing, and used to distinguish discrete components from integrated ones.
+\paragraph{Circles.} Since \texttt{1.2.6}, you can add a circle\footnote{Suggested by Matthias Jung \href{https://github.com/circuitikz/circuitikz/issues/442}{on GitHub}} to most of the transistor shapes --- with the exception of multi-terminal (\texttt{bjtnpn} and \texttt{bjtpnp}, where it would be awkward anyway) and graphene FETs. The circle is intended in some case as the component's housing, and used to distinguish discrete components from integrated ones.
To add the circle to a single transistor, you use the \texttt{tr circle} keys in the node; if you want all of your transistors with a circle, you can set the property \texttt{tr circle} with a \verb|\ctikzset| command (it will respect normal grouping, of course); in that case, you can use \texttt{tr circle=false} to locally disable them.
@@ -3218,7 +3227,15 @@ For \textsc{npn}, \textsc{pnp}, \textsc{nigbt} and \textsc{pigbt} transistors, t
;\end{circuitikz}
\end{LTXexample}
-Finally, all transistors, except the multi-terminal \texttt{bjtnpn} and \texttt{bjtpnp}, (since \texttt{0.9.6}) have internal nodes on the terminal corners, called \texttt{inner up} and \texttt{inner down}; you do not normally need them, but they are here for special applications:
+
+Notice that the geographical anchors of transistors are \emph{not} affected by either the bodydiode and the circle options; the label text is also outside of them. This is to permit to align the components independently from that features. On the other hand, that can sometimes create problems because that element are outside the bounding box automatically calculated by \TikZ{}.
+
+The exception is the \texttt{right} anchor which, when a circle is present, indicates the edge of the circle itself (since \texttt{v1.3.2})
+
+{\geolrcoord{npn} \geolrcoord{npn, bodydiode} \geolrcoord{npn, bodydiode, tr circle}}
+
+
+All transistors, except the multi-terminal \texttt{bjtnpn} and \texttt{bjtpnp}, (since \texttt{0.9.6}) have internal nodes on the terminal corners, called \texttt{inner up} and \texttt{inner down}; you do not normally need them, but they are here for special applications:
\begin{LTXexample}[varwidth=true]
\begin{circuitikz}
diff --git a/graphics/pgf/contrib/circuitikz/tex/circuitikz.sty b/graphics/pgf/contrib/circuitikz/tex/circuitikz.sty
index a5ec75f3af..83ac0f569d 100644
--- a/graphics/pgf/contrib/circuitikz/tex/circuitikz.sty
+++ b/graphics/pgf/contrib/circuitikz/tex/circuitikz.sty
@@ -12,8 +12,8 @@
\NeedsTeXFormat{LaTeX2e}
-\def\pgfcircversion{1.3.1}
-\def\pgfcircversiondate{2021/02/20}
+\def\pgfcircversion{1.3.2}
+\def\pgfcircversiondate{2021/03/14}
\ProvidesPackage{circuitikz}%
[\pgfcircversiondate{} The CircuiTikz circuit drawing package version \pgfcircversion]
diff --git a/graphics/pgf/contrib/circuitikz/tex/pgfcircmultipoles.tex b/graphics/pgf/contrib/circuitikz/tex/pgfcircmultipoles.tex
index 3454f6dd34..82b156c46d 100644
--- a/graphics/pgf/contrib/circuitikz/tex/pgfcircmultipoles.tex
+++ b/graphics/pgf/contrib/circuitikz/tex/pgfcircmultipoles.tex
@@ -1406,7 +1406,7 @@
\ifx\@@tmp\@@x\else\edef\@@or{1}\fi
\edef\@@tmp{\ctikzvalof{multipoles/flipflop/cd}}
\ifnum\@@tmp>0\edef\@@or{1}\fi
- \edef\@@tmp{\ctikzvalof{multipoles/flipflop/nu}}
+ \edef\@@tmp{\ctikzvalof{multipoles/flipflop/nd}}
\ifnum\@@tmp>0\edef\@@or{1}\fi
% \typeout{TEST\space\@@tmp\space\@@x}
\ifnum\@@or>0
diff --git a/graphics/pgf/contrib/circuitikz/tex/pgfcircquadpoles.tex b/graphics/pgf/contrib/circuitikz/tex/pgfcircquadpoles.tex
index e00b33ad59..7b26709540 100644
--- a/graphics/pgf/contrib/circuitikz/tex/pgfcircquadpoles.tex
+++ b/graphics/pgf/contrib/circuitikz/tex/pgfcircquadpoles.tex
@@ -417,7 +417,9 @@
\ctikzset{bipoles/bandpass/width/.initial=.7}
\ctikzset{bipoles/bandstop/width/.initial=.7}
\ctikzset{bipoles/highpass/width/.initial=.7}
+\ctikzset{bipoles/highpass2/width/.initial=.7}
\ctikzset{bipoles/lowpass/width/.initial=.7}
+\ctikzset{bipoles/lowpass2/width/.initial=.7}
\ctikzset{bipoles/allpass/width/.initial=.7}
\ctikzset{bipoles/adc/width/.initial=.7}
\ctikzset{bipoles/dac/width/.initial=.7}
@@ -870,6 +872,70 @@
\pgfusepath{draw}
}
+%% highpass2 filter ---simplyfied with just two waves
+\pgfcircdeclarebipolescaled{blocks}
+{}
+{\ctikzvalof{bipoles/highpass2/width}}
+{highpass2}
+{\ctikzvalof{bipoles/highpass2/width}}
+{\ctikzvalof{bipoles/highpass2/width}}
+{
+ \pgf@circ@res@step = \ctikzvalof{bipoles/highpass2/width}\pgf@circ@scaled@Rlen
+ \divide \pgf@circ@res@step by 2
+
+ \pgfpathmoveto{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@zero}}
+ \pgf@circ@res@other = \pgf@circ@res@left
+ \advance\pgf@circ@res@other by \pgf@circ@res@step
+
+ \ifpgf@circuit@dashed
+ \pgfsetdash{{0.1cm}{0.1cm}}{0cm}
+ \fi
+
+ % draw outer box
+ \pgf@circ@twoportbox
+
+ \ifpgf@circuit@inputarrow
+ {
+ \advance \pgf@circ@res@left by -.5\ctikzvalof{bipoles/thickness}\pgfstartlinewidth
+ \pgftransformshift{\pgfpoint{\pgf@circ@res@left}{0pt}}
+ \pgfnode{inputarrow}{tip}{}{pgf@inputarrow}{\pgfusepath{fill}}
+ }
+ \fi
+
+ % rotate inner symbol
+ \def\pgfcircmathresult{\expandafter\pgf@circ@stripdecimals\pgf@circ@direction\pgf@nil}
+ \ifnum \pgfcircmathresult > 45 \ifnum \pgfcircmathresult < 135
+ \pgftransformrotate{270}
+ \fi\fi
+ \ifnum \pgfcircmathresult > 134 \ifnum \pgfcircmathresult < 225 % 134 degree, because >= 135 is not possible
+ \pgftransformrotate{180}
+ \fi\fi
+ \ifnum \pgfcircmathresult > 224 \ifnum \pgfcircmathresult < 315
+ \pgftransformrotate{90}
+ \fi\fi
+
+ % draw inner symbol
+ \pgfsetdash{}{0pt} % always draw solid line for inner symbol
+ \pgfsetarrows{-} %never draw arrows
+ \pgfsetlinewidth{\pgfstartlinewidth}
+ \pgfpathmoveto{\pgfpoint{-0.5\pgf@circ@res@step}{0.25\pgf@circ@res@step}}
+ \pgfpathsine{\pgfpoint{.25\pgf@circ@res@step}{.25\pgf@circ@res@step}}
+ \pgfpathcosine{\pgfpoint{.25\pgf@circ@res@step}{-.25\pgf@circ@res@step}}
+ \pgfpathsine{\pgfpoint{.25\pgf@circ@res@step}{-.25\pgf@circ@res@step}}
+ \pgfpathcosine{\pgfpoint{.25\pgf@circ@res@step}{.25\pgf@circ@res@step}}
+ \pgfusepath{draw}
+
+ \pgfpathmoveto{\pgfpoint{-0.5\pgf@circ@res@step}{-0.25\pgf@circ@res@step}}
+ \pgfpathsine{\pgfpoint{.25\pgf@circ@res@step}{.25\pgf@circ@res@step}}
+ \pgfpathcosine{\pgfpoint{.25\pgf@circ@res@step}{-.25\pgf@circ@res@step}}
+ \pgfpathsine{\pgfpoint{.25\pgf@circ@res@step}{-.25\pgf@circ@res@step}}
+ \pgfpathcosine{\pgfpoint{.25\pgf@circ@res@step}{.25\pgf@circ@res@step}}
+ \pgfusepath{draw}
+ \pgfpathmoveto{\pgfpoint{-0.3\pgf@circ@res@step}{-0.5\pgf@circ@res@step}}
+ \pgfpathlineto{\pgfpoint{0.3\pgf@circ@res@step}{-0.1\pgf@circ@res@step}}
+ \pgfusepath{draw}
+}
+
%% lowpass filter
\pgfcircdeclarebipolescaled{blocks}
{}
@@ -944,6 +1010,70 @@
\pgfusepath{draw}
}
+%% lowpass2 filter: simplyfied with just two waves
+\pgfcircdeclarebipolescaled{blocks}
+{}
+{\ctikzvalof{bipoles/lowpass2/width}}
+{lowpass2}
+{\ctikzvalof{bipoles/lowpass2/width}}
+{\ctikzvalof{bipoles/lowpass2/width}}
+{
+ \pgf@circ@res@step = \ctikzvalof{bipoles/lowpass2/width}\pgf@circ@scaled@Rlen
+ \divide \pgf@circ@res@step by 2
+
+ \pgfpathmoveto{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@zero}}
+ \pgf@circ@res@other = \pgf@circ@res@left
+ \advance\pgf@circ@res@other by \pgf@circ@res@step
+
+ \ifpgf@circuit@dashed
+ \pgfsetdash{{0.1cm}{0.1cm}}{0cm}
+ \fi
+
+ % draw outer box
+ \pgf@circ@twoportbox
+
+ \ifpgf@circuit@inputarrow
+ {
+ \advance \pgf@circ@res@left by -.5\ctikzvalof{bipoles/thickness}\pgfstartlinewidth
+ \pgftransformshift{\pgfpoint{\pgf@circ@res@left}{0pt}}
+ \pgfnode{inputarrow}{tip}{}{pgf@inputarrow}{\pgfusepath{fill}}
+ }
+ \fi
+
+ % rotate inner symbol
+ \def\pgfcircmathresult{\expandafter\pgf@circ@stripdecimals\pgf@circ@direction\pgf@nil}
+ \ifnum \pgfcircmathresult > 45 \ifnum \pgfcircmathresult < 135
+ \pgftransformrotate{270}
+ \fi\fi
+ \ifnum \pgfcircmathresult > 134 \ifnum \pgfcircmathresult < 225 % 134 degree, because >= 135 is not possible
+ \pgftransformrotate{180}
+ \fi\fi
+ \ifnum \pgfcircmathresult > 224 \ifnum \pgfcircmathresult < 315
+ \pgftransformrotate{90}
+ \fi\fi
+
+ % draw inner symbol
+ \pgfsetdash{}{0pt} % always draw solid line for inner symbol
+ \pgfsetarrows{-} %never draw arrows
+ \pgfsetlinewidth{\pgfstartlinewidth}
+ \pgfpathmoveto{\pgfpoint{-0.5\pgf@circ@res@step}{0.25\pgf@circ@res@step}}
+ \pgfpathsine{\pgfpoint{.25\pgf@circ@res@step}{.25\pgf@circ@res@step}}
+ \pgfpathcosine{\pgfpoint{.25\pgf@circ@res@step}{-.25\pgf@circ@res@step}}
+ \pgfpathsine{\pgfpoint{.25\pgf@circ@res@step}{-.25\pgf@circ@res@step}}
+ \pgfpathcosine{\pgfpoint{.25\pgf@circ@res@step}{.25\pgf@circ@res@step}}
+ \pgfusepath{draw}
+ \pgfpathmoveto{\pgfpoint{-0.3\pgf@circ@res@step}{0.1\pgf@circ@res@step}}
+ \pgfpathlineto{\pgfpoint{0.3\pgf@circ@res@step}{0.5\pgf@circ@res@step}}
+ \pgfusepath{draw}
+
+ \pgfpathmoveto{\pgfpoint{-0.5\pgf@circ@res@step}{-0.25\pgf@circ@res@step}}
+ \pgfpathsine{\pgfpoint{.25\pgf@circ@res@step}{.25\pgf@circ@res@step}}
+ \pgfpathcosine{\pgfpoint{.25\pgf@circ@res@step}{-.25\pgf@circ@res@step}}
+ \pgfpathsine{\pgfpoint{.25\pgf@circ@res@step}{-.25\pgf@circ@res@step}}
+ \pgfpathcosine{\pgfpoint{.25\pgf@circ@res@step}{.25\pgf@circ@res@step}}
+ \pgfusepath{draw}
+}
+
%% allpass filter
\pgfcircdeclarebipolescaled{blocks}
{}
@@ -2121,7 +2251,9 @@
\pgfcirc@activate@bipole@simple{l}{bandpass}
\pgfcirc@activate@bipole@simple{l}{bandstop}
\pgfcirc@activate@bipole@simple{l}{highpass}
+\pgfcirc@activate@bipole@simple{l}{highpass2}
\pgfcirc@activate@bipole@simple{l}{lowpass}
+\pgfcirc@activate@bipole@simple{l}{lowpass2}
\pgfcirc@activate@bipole@simple{l}{allpass}
\pgfcirc@activate@bipole@simple{l}{adc}
\pgfcirc@activate@bipole@simple{l}{dac}
diff --git a/graphics/pgf/contrib/circuitikz/tex/pgfcirctripoles.tex b/graphics/pgf/contrib/circuitikz/tex/pgfcirctripoles.tex
index f6ebcf61a3..1fa81e7326 100644
--- a/graphics/pgf/contrib/circuitikz/tex/pgfcirctripoles.tex
+++ b/graphics/pgf/contrib/circuitikz/tex/pgfcirctripoles.tex
@@ -3255,6 +3255,38 @@
\ctikzset{tripoles/isfet/bodydiode conn/.initial=.6}
\ctikzset{tripoles/isfet/curr direction/.initial=1}
%
+% graphene FET
+%
+\ctikzset{tripoles/pgfet/width/.initial=.6}
+\ctikzset{tripoles/pgfet/gate height/.initial=.5}
+\ctikzset{tripoles/pgfet/gate height 2/.initial=0.25} % must be "gate height"/2
+\ctikzset{tripoles/pgfet/base height/.initial=.5} % must be "gate height"
+\ctikzset{tripoles/pgfet/outer base height/.initial=.25} % must be "gate height 2"
+\ctikzset{tripoles/pgfet/outer base thickness/.initial=1}
+\ctikzset{tripoles/pgfet/conn height/.initial=0}
+\ctikzset{tripoles/pgfet/height/.initial=1.1}
+\ctikzset{tripoles/pgfet/gate width/.initial=.5}
+\ctikzset{tripoles/pgfet/base width/.initial=0.36084} % must be "gate height"*cos(60)/(2*width)
+\ctikzset{tripoles/pgfet/bodydiode scale/.initial=.3}
+\ctikzset{tripoles/pgfet/bodydiode distance/.initial=.6}
+\ctikzset{tripoles/pgfet/bodydiode conn/.initial=.6}
+\ctikzset{tripoles/pgfet/curr direction/.initial=-1}
+
+\ctikzset{tripoles/ngfet/width/.initial=.6}
+\ctikzset{tripoles/ngfet/gate height/.initial=.5}
+\ctikzset{tripoles/ngfet/gate height 2/.initial=0.25} % must be "gate height"/2
+\ctikzset{tripoles/ngfet/base height/.initial=.5} % must be "gate height"
+\ctikzset{tripoles/ngfet/outer base height/.initial=.25} % must be "gate height 2"
+\ctikzset{tripoles/ngfet/outer base thickness/.initial=1}
+\ctikzset{tripoles/ngfet/conn height/.initial=0}
+\ctikzset{tripoles/ngfet/height/.initial=1.1}
+\ctikzset{tripoles/ngfet/gate width/.initial=.5}
+\ctikzset{tripoles/ngfet/base width/.initial=0.36084} % must be "gate height"*cos(60)/(2*width)
+\ctikzset{tripoles/ngfet/bodydiode scale/.initial=.3}
+\ctikzset{tripoles/ngfet/bodydiode distance/.initial=.6}
+\ctikzset{tripoles/ngfet/bodydiode conn/.initial=.6}
+\ctikzset{tripoles/ngfet/curr direction/.initial=1}
+%
% multi-emitter and multi-collector BJTs by Romano Giannetti
%
\ctikzset{tripoles/bjt/emitters/.initial=1}
@@ -3349,7 +3381,7 @@
\pgf@x=0pt\relax
\fi
}
- \savedmacro{\scaecircleradius}{
+ \savedmacro{\scalecircleradius}{
\edef\scalecircleradius{\ctikzvalof{transistor circle/scale circle radius}}
}
\saveddimen{\circleradius}{
@@ -3400,9 +3432,39 @@
\pgfmathsetlength{\pgf@circ@scaled@Rlen}{\ctikzvalof{\ctikzclass/scale}\pgf@circ@Rlen}
\pgf@x=-\ctikzvalof{tripoles/#1/width}\pgf@circ@scaled@Rlen
}
- \savedanchor\right{%center right -- added by Burak Kelleci % this is really 0,0
- \pgf@y=0pt
- \pgf@x=0pt
+ \savedanchor\right{
+ \pgf@x=0pt\pgf@y=0pt
+ \ifpgf@circ@trcircle
+ % repeat the \circleradius computation (GRRRR)
+ \pgfmathsetlength{\pgf@circ@scaled@Rlen}{\ctikzvalof{\ctikzclass/scale}\pgf@circ@Rlen}
+ % repeat the extrabodydiodelen (grrr)
+ \ifpgf@circuit@fet@bodydiode
+ % try to put the text to the right of the flyback diode
+ \pgfmathsetlength{\pgf@circ@res@other}{(
+ \ctikzvalof{tripoles/#1/bodydiode distance}*
+ \ctikzvalof{tripoles/#1/width} +
+ \ctikzvalof{tripoles/#1/bodydiode scale}*
+ \ctikzvalof{bipoles/diode/height}/2
+ )*\pgf@circ@scaled@Rlen}
+ \else
+ \pgf@circ@res@other=0pt\relax
+ \fi
+ % left
+ \pgf@xa=-\ctikzvalof{tripoles/#1/width}\pgf@circ@scaled@Rlen
+ \pgf@xa=\circlebase\pgf@xa % this is the base point of the circle
+ % northeast
+ \pgf@yb=\ctikzvalof{tripoles/#1/height}\pgf@circ@scaled@Rlen % y of the left point of circle
+ \pgf@yb=.5\pgf@yb
+ \pgf@xb=\pgf@circ@res@other % this is the x of the right points of the circle
+ %
+ \pgf@yb=\ctikzvalof{tripoles/#1/bodydiode conn}\pgf@yb %this is #3 of the circle
+ % find the radius of the circle
+ \pgfmathsetlength{\pgf@circ@res@other}{((\pgf@xb)-(\pgf@xa)+(\pgf@yb)*(\pgf@yb)/((\pgf@xb)-(\pgf@xa)))/2*\scalecircleradius}
+ % repeat the circleleft computation
+ \pgf@xa=-\ctikzvalof{tripoles/#1/width}\pgf@circ@scaled@Rlen
+ \pgf@xb=\circlebase\pgf@xa
+ \pgfmathsetlength{\pgf@x}{\pgf@xb+2*\pgf@circ@res@other}
+ \fi
}
\anchor{text}{
\northeast
@@ -3442,10 +3504,16 @@
\anchor{west}{
\left
}
+ \anchor{left}{
+ \left
+ }
\anchor{east}{
\northeast
\pgf@y=0pt
}
+ \anchor{right}{
+ \right
+ }
\anchor{south}{
\northeast
\pgf@circ@res@step=\pgf@y
@@ -4302,6 +4370,187 @@
\declareigbt{Lnigbt}
\declareigbt{Lpigbt}
+% Graphene FET, See https://github.com/circuitikz/circuitikz/issues/496
+\long\def\declaregfet#1{
+ \pgfcircdeclaretransistor{#1}{
+ \anchor{inner up}{
+ \northeast
+ \pgf@y=\ctikzvalof{tripoles/#1/gate height}\pgf@y
+ }
+ \anchor{inner down}{
+ \northeast
+ \pgf@y=-\ctikzvalof{tripoles/#1/gate height}\pgf@y
+ }
+ \anchor{outer hex up}{
+ \left
+ \pgf@xa=\ctikzvalof{tripoles/#1/base width}\pgf@x
+ \northeast
+ \pgf@y=\ctikzvalof{tripoles/#1/gate height 2}\pgf@y
+ \pgf@x=-\pgf@xa
+ }
+ \anchor{outer hex down}{
+ \left
+ \pgf@xa=\ctikzvalof{tripoles/#1/base width}\pgf@x
+ \northeast
+ \pgf@y=\ctikzvalof{tripoles/#1/gate height 2}\pgf@y
+ \pgf@y=-\pgf@y
+ \pgf@x=-\pgf@xa
+ }
+ \anchor{inner hex up}{
+ \left
+ \pgf@xa=\ctikzvalof{tripoles/#1/base width}\pgf@x
+ \northeast
+ \pgf@y=\ctikzvalof{tripoles/#1/gate height 2}\pgf@y
+ \pgf@x=\pgf@xa
+ }
+ \anchor{inner hex down}{
+ \left
+ \pgf@xa=\ctikzvalof{tripoles/#1/base width}\pgf@x
+ \northeast
+ \pgf@y=\ctikzvalof{tripoles/#1/gate height 2}\pgf@y
+ \pgf@y=-\pgf@y
+ \pgf@x=\pgf@xa
+ }
+ \anchor{right}{
+ \northeast\pgf@y=0pt\relax
+ \pgfmathsetlength{\pgf@xa}{\ctikzvalof{tripoles/#1/base width}*
+ \ctikzvalof{tripoles/#1/width}*\pgf@circ@scaled@Rlen}
+ \advance \pgf@x by \pgf@xa
+ }
+ \anchor{text}{% need a different text: no circle, shift to the right
+ \northeast
+ \pgfmathsetlength{\pgf@circ@scaled@Rlen}{\ctikzvalof{\ctikzclass/scale}\pgf@circ@Rlen}
+ \ifpgf@circuit@transisors@fixlabels
+ \ifpgf@circuit@fet@bodydiode
+ \advance \pgf@x by \extrabodydiodelen
+ \else
+ \pgfmathsetlength{\pgf@xa}{\ctikzvalof{tripoles/#1/base width}*
+ \ctikzvalof{tripoles/#1/width}*\pgf@circ@scaled@Rlen}
+ \advance \pgf@x by \pgf@xa
+ \fi
+ % no circle for gfets
+ % add a bit of space to avoid central (substrate) terminal if drawn
+ \advance\pgf@x by 0.05\pgf@circ@scaled@Rlen\relax
+ \pgf@y=\dimexpr.5\dp\pgfnodeparttextbox-.5\ht\pgfnodeparttextbox\relax
+ \else
+ \pgf@y=.7\pgf@y
+ \pgf@x= \pgf@circ@scaled@Rlen
+ \pgf@x=0.1\pgf@x
+ \fi
+ }
+ }
+ {
+ % no circle for gfets (clearly!)
+ %draw upper connection to hexagon
+ \pgfpathmoveto{\pgfpoint{\pgf@circ@res@right}{\pgf@circ@res@up+\pgfverticaltransformationadjustment*.5*\pgflinewidth}}
+ \pgfpathlineto{\pgfpoint{\pgf@circ@res@right}
+ {\ctikzvalof{tripoles/#1/gate height}\pgf@circ@res@up}}
+ \pgfpathmoveto{\pgfpoint{\pgf@circ@res@right}
+ {\ctikzvalof{tripoles/#1/gate height}\pgf@circ@res@down}}
+ \pgfpathlineto{\pgfpoint{\pgf@circ@res@right}{\pgf@circ@res@down-\pgfverticaltransformationadjustment*.5*\pgflinewidth}}
+ \pgfusepath{draw}
+ % draw (fillable) hexagon
+ \pgfscope
+ \pgfpathmoveto{\pgfpoint
+ {\ctikzvalof{tripoles/#1/base width}\pgf@circ@res@left}
+ {\ctikzvalof{tripoles/#1/gate height 2}\pgf@circ@res@up}}
+ \pgfpathlineto{\pgfpoint{\pgf@circ@res@right}
+ {\ctikzvalof{tripoles/#1/gate height}\pgf@circ@res@up}}
+ \pgfpathlineto{\pgfpoint
+ {-\ctikzvalof{tripoles/#1/base width}\pgf@circ@res@left}
+ {\ctikzvalof{tripoles/#1/gate height 2}\pgf@circ@res@up}}
+ \pgfpathlineto{\pgfpoint
+ {-\ctikzvalof{tripoles/#1/base width}\pgf@circ@res@left}
+ {\ctikzvalof{tripoles/#1/gate height 2}\pgf@circ@res@down}}
+ \pgfpathlineto{\pgfpoint{\pgf@circ@res@right}
+ {\ctikzvalof{tripoles/#1/gate height}\pgf@circ@res@down}}
+ \pgfpathlineto{\pgfpoint
+ {\ctikzvalof{tripoles/#1/base width}\pgf@circ@res@left}
+ {-\ctikzvalof{tripoles/#1/gate height 2}\pgf@circ@res@up}}
+ \pgfpathclose
+ \pgf@circ@draworfill
+ \endpgfscope
+ %draw thicker gate lines
+ \pgfscope
+ \pgfscope
+ \pgfpathmoveto{\pgfpoint
+ {\ctikzvalof{tripoles/#1/gate width}\pgf@circ@res@left}
+ {\ctikzvalof{tripoles/#1/outer base height}\pgf@circ@res@up+\pgfverticaltransformationadjustment*.5\pgflinewidth}}
+ \pgfpathlineto{\pgfpoint
+ {\ctikzvalof{tripoles/#1/gate width}\pgf@circ@res@left}
+ {\ctikzvalof{tripoles/#1/outer base height}\pgf@circ@res@down-\pgfverticaltransformationadjustment*.5\pgflinewidth}}
+ % set the normal thickness
+ \pgf@circ@setlinewidth{tripoles}{\pgflinewidth}
+ \edef\@@extrat{\ctikzvalof{tripoles/#1/outer base thickness}}
+ \pgfsetlinewidth{\@@extrat\pgflinewidth}
+ \pgfusepath{draw}
+ \endpgfscope
+ \pgfpathmoveto{\pgfpoint
+ {\ctikzvalof{tripoles/#1/base width}\pgf@circ@res@left}
+ {\ctikzvalof{tripoles/#1/base height}\pgf@circ@res@up+\pgfverticaltransformationadjustment*.5\pgflinewidth}}
+ \pgfpathlineto{\pgfpoint
+ {\ctikzvalof{tripoles/#1/base width}\pgf@circ@res@left}
+ {\ctikzvalof{tripoles/#1/base height}\pgf@circ@res@down-\pgfverticaltransformationadjustment*.5\pgflinewidth}}
+ \pgf@circ@setlinewidth{tripoles}{\pgflinewidth}
+ \pgfusepath{draw}
+ \endpgfscope
+ %draw arrow depending on type of transistor
+ \pgfscope
+ \pgfslopedattimetrue
+ \pgfallowupsidedownattimetrue
+ \pgfresetnontranslationattimefalse
+ \ifpgf@circuit@trans@arrowatend
+ \ifpgf@circuit@trans@ntype
+ \edef\@@anchor{btip}\edef\@@pos{1.0}
+ \else
+ \edef\@@anchor{tip}\edef\@@pos{1.0}
+ \fi
+ \else
+ \edef\@@anchor{center}\edef\@@pos{0.5}
+ \fi
+ \ifpgf@circuit@trans@ntype
+ \pgftransformlineattime{\@@pos}{%
+ \pgfpoint%
+ {\ctikzvalof{tripoles/#1/base width}\pgf@circ@res@left}%
+ {\ctikzvalof{tripoles/#1/gate height 2}\pgf@circ@res@down}%
+ }{%
+ \pgfpoint{\pgf@circ@res@right}%
+ {\ctikzvalof{tripoles/#1/gate height}\pgf@circ@res@down}%
+ }
+ \else
+ \pgftransformlineattime{\@@pos}{%
+ \pgfpoint{\pgf@circ@res@right}%
+ {\ctikzvalof{tripoles/#1/gate height}\pgf@circ@res@up}%
+ }{%
+ \pgfpoint{\ctikzvalof{tripoles/#1/base width}\pgf@circ@res@left}%
+ {\ctikzvalof{tripoles/#1/gate height 2}\pgf@circ@res@up}%
+ }
+ \fi
+ \pgfnode{trarrow}{\@@anchor}{}{}{\pgfusepath{stroke}}
+ \endpgfscope
+ %draw gate
+ \ifpgf@circuit@trans@ntype
+ \pgfpathmoveto{\pgfpoint
+ {\ctikzvalof{tripoles/#1/gate width}\pgf@circ@res@left}
+ {\ctikzvalof{tripoles/#1/conn height}\pgf@circ@res@down}}
+ \pgfpathlineto{\pgfpoint{\pgf@circ@res@left-\pgfhorizontaltransformationadjustment*.5*\pgflinewidth}%
+ {\ctikzvalof{tripoles/#1/conn height}\pgf@circ@res@down}}
+ \else
+ \pgfpathmoveto{\pgfpoint
+ {\ctikzvalof{tripoles/#1/gate width}\pgf@circ@res@left}
+ {\ctikzvalof{tripoles/#1/conn height}\pgf@circ@res@up}}
+ \pgfpathlineto{\pgfpoint{\pgf@circ@res@left-\pgfhorizontaltransformationadjustment*.5*\pgflinewidth}%
+ {\ctikzvalof{tripoles/#1/conn height}\pgf@circ@res@up}}
+ \fi
+ \pgfusepath{draw}
+ }
+}
+
+\declaregfet{pgfet}
+\declaregfet{ngfet}
+
+% Plain MOSes
+
\pgfcircdeclaretransistor{nmos}{
\anchor{inner up}{
\northeast
diff --git a/graphics/pgf/contrib/circuitikz/tex/t-circuitikz.tex b/graphics/pgf/contrib/circuitikz/tex/t-circuitikz.tex
index 76090560e1..fcc31889fe 100644
--- a/graphics/pgf/contrib/circuitikz/tex/t-circuitikz.tex
+++ b/graphics/pgf/contrib/circuitikz/tex/t-circuitikz.tex
@@ -10,8 +10,8 @@
%
% See the files gpl-3.0_license.txt and lppl-1-3c_license.txt for more details.
-\def\pgfcircversion{1.3.1}
-\def\pgfcircversiondate{2021/02/20}
+\def\pgfcircversion{1.3.2}
+\def\pgfcircversiondate{2021/03/14}
\writestatus{loading}{\pgfcircversiondate{} The CircuiTikz circuit drawing package version \pgfcircversion}
\usemodule[tikz]
diff --git a/graphics/pgf/contrib/sankey/README b/graphics/pgf/contrib/sankey/README
index ae6f9721be..aa0a7f627a 100644
--- a/graphics/pgf/contrib/sankey/README
+++ b/graphics/pgf/contrib/sankey/README
@@ -1,8 +1,11 @@
sankey
======
-LaTeX package to build Sankey diagram.
+sankey – Draw Sankey diagrams with TikZ
+This package provides macros and environment to build Sankey diagrams,
+i.e. flow diagrams in which the width of the arrows is proportional to
+the flow rate.
license
=======
@@ -11,6 +14,8 @@ Copyright (C) 2016-2021 by Paul Gaborit
This file may be distributed and/or modified
- 1. under the LaTeX Project Public License and/or
+ 1. under the LaTeX Project Public License v1.3
+
+ and/or
2. under the GNU Public License.
diff --git a/graphics/pgf/contrib/sankey/sankey-doc.pdf b/graphics/pgf/contrib/sankey/sankey-doc.pdf
deleted file mode 100644
index f8d77bd13b..0000000000
--- a/graphics/pgf/contrib/sankey/sankey-doc.pdf
+++ /dev/null
Binary files differ
diff --git a/graphics/pgf/contrib/sankey/sankey-doc.tex b/graphics/pgf/contrib/sankey/sankey-doc.tex
deleted file mode 100644
index 768e2d0be1..0000000000
--- a/graphics/pgf/contrib/sankey/sankey-doc.tex
+++ /dev/null
@@ -1,1599 +0,0 @@
-% -*- coding: utf-8; -*-
-
-% Copyright (C) 2016-2021 by Paul Gaborit
-%
-% This file may be distributed and/or modified
-%
-% 1. under the LaTeX Project Public License and/or
-%
-% 2. under the GNU Public License.
-
-\documentclass[a4paper,onecolumn,10pt]{article}
-%\usepackage[rgb]{xcolor}
-\usepackage[paper=a4paper,vmargin=1.5cm,hmargin=4cm]{geometry}
-\usepackage[utf8]{inputenc}
-\usepackage[T1]{fontenc}
-\usepackage{xcolor}
-\usepackage[colorlinks]{hyperref}
-\usepackage{fancyvrb}
-\usepackage{listings}
-\usepackage{enumitem}
-\usepackage{pgfilecontents}
-\usepackage{microtype}
-\usepackage{bookmark}
-\usepackage{cmap}
-\usepackage{sankey}
-\usepackage{siunitx}
-\usepackage{mdframed}
-\usepackage{footnote}
-\usepackage{accsupp}
-\usetikzlibrary{positioning,patterns.meta}
-\usepackage[british]{babel}
-
-\colorlet{fondcode}{gray!5!white}
-\colorlet{keyword}{blue!50!cyan!50!black}
-\colorlet{comment}{red!75!black}
-
-\newcommand\emptyaccsupp[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}}
-
-\lstset{
- literate=
- {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ú}{{\'u}}1
- {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1
- {à}{{\`a}}1 {è}{{\`e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1
- {À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1
- {ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1
- {Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1
- {â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1
- {Â}{{\^A}}1 {Ê}{{\^E}}1 {Î}{{\^I}}1 {Ô}{{\^O}}1 {Û}{{\^U}}1
- {œ}{{\oe}}1 {Œ}{{\OE}}1 {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1
- {ç}{{\c c}}1 {Ç}{{\c C}}1 {ø}{{\o}}1 {å}{{\r a}}1 {Å}{{\r A}}1
- {€}{{\texteuro}}1 {£}{{\pounds}}1 {°}{{\degres}}1
- {’}{{\textquoteright}}1 {‘}{{\textquoteleft}}1
- {«}{{<<}}1 {»}{{>>}}1
- {—}{{---}}1 {−}{{$-$}}1
-}
-
-\lstset{
- fancyvrb=true,
- %fvcmdparams=samepage,
- escapechar=`, % pour introduire du latex dans un environnement verbatim
- extendedchars=true,
- fontadjust=true,
- columns=fullflexible, % pour pouvoir copier/coller les chaines de caractères
- flexiblecolumns=true,
- % frame=leftline,
- inputencoding=utf8,
- keepspaces=true, % keeps spaces in text, code indentation
- backgroundcolor=\color{fondcode},
- basicstyle=\mdseries\ttfamily,
- keywordstyle=\color{keyword}\bfseries,%
- stringstyle=\ttfamily\color{green!50!black},%
- commentstyle=\color{comment}\itshape,%
- emphstyle=\bfseries\color{red},
- numbersep=5pt,
- %numbers=left,
- numberstyle=\tiny\emptyaccsupp,
- showstringspaces=false,
- upquote=true, % pour pouvoir copier/coller le code avec des quotes
- aboveskip=\parskip,
- belowskip=\parskip,
- framexleftmargin=1pt,
- framexrightmargin=1pt,
-}
-
-\lstdefinestyle{textsmall}{basicstyle=\color{black}\small\mdseries\ttfamily}
-\lstdefinestyle{textfootnotesize}{basicstyle=\color{black}\footnotesize\mdseries\ttfamily}
-\lstdefinestyle{textscriptsize}{basicstyle=\color{black}\scriptsize\mdseries\ttfamily}
-\lstdefinestyle{texttiny}{basicstyle=\color{black}\tiny\mdseries\ttfamily}
-
-\lstdefinestyle{LaTeX}{
- language=[LaTeX]TeX,
- %backgroundcolor=\color{latexbg},
- moretexcs={
- coordinate,
- definecolor,
- draw,
- fill,
- foreach,
- hashband,
- node,
- sankeyadvance,
- sankeydubins,
- sankeyend,
- sankeyend,
- sankeyfork,
- sankeynode,
- sankeynodealias,
- sankeynodeend,
- sankeynodestart,
- sankeyoutin,
- sankeyset,
- sankeystart,
- sankeyturn,
- sisetup,
- tikzset,
- turnandstop,
- usepackage,
- }
-}
-\lstdefinestyle{LaTeXsmall}{style=LaTeX,style=textsmall}
-\lstdefinestyle{LaTeXfootnotesize}{style=LaTeX,style=textfootnotesize}
-\lstdefinestyle{LaTeXscriptsize}{style=LaTeX,style=textscriptsize}
-\lstdefinestyle{LaTeXtiny}{style=LaTeX,style=texttiny}
-
-\def\code{\lstinline[basicstyle=\mdseries\ttfamily\color{red!50!black}]}
-
-\edef\samplecodename{\jobname-code.vrb}
-
-\newcommand\constant[1]{\textcolor{violet}{\texttt{#1}}}
-\newcommand\ARG[1]{\texttt{\{#1\}}}
-\newcommand\OPTARG[1]{\textcolor{green!50!black}{\texttt{[#1]}}}
-\newcommand\VAR[1]{\textit{\texttt{<#1>}}}
-\newcommand\NOTE[1]{\leavevmode\marginpar{#1}}
-
-\makeatletter
-\def\mynobreakpar{\par\nobreak\@afterheading}
-\makeatother
-\def\docprefix#1{\texttt{\textcolor{gray}{#1}}}
-\def\sankeykeysprefix{/sankey}
-
-\newenvironment{sankeyoption}[5][]{% [prefix] key, val, default, initially
- % \begingroup
- \bgroup%
- %
- \def\path{#1}%
- \def\key{#2}%
- \def\val{#3}%
- \def\default{#4}%
- \def\initially{#5}%
- %\setlength\parindent{\dimexpr.5\parindent\relax}%
- % \vspace{.25\baselineskip plus .25\baselineskip minus 0mm}
- \parfillskip 0pt plus 1fil%
- \leavevmode%
- \ttfamily%
- \hspace*{-1cm}\textcolor{red!75!black}{\texttt{\docprefix{\ifdefempty{\path}{\sankeykeysprefix/}{\path/}}\key}}%
- \ifdefempty{\val}{}{=\textit{\val}}%
- \hfill
- \ifdefempty{\default}{\null}{(default:\,\constant{\default})}%
- \ifdefempty{\initially}{\null}{(initially:\,\constant{\initially})}%
- \mynobreakpar\egroup%
- \parskip=.5\baselineskip plus .25\baselineskip minus .25\baselineskip
- \parfillskip=30pt plus 1fil
- \itemize[topsep=0pt,partopsep=0pt,itemsep=0pt]\item[]
-}{%
- \enditemize%
-}
-
-\newcommand\MACRO{\hspace*{-1cm}}
-
-\newlist{sankeyconstantsdesc}{description}{1}
-\setlist[sankeyconstantsdesc]{align=right,labelindent=1.5em,labelsep=.5em,leftmargin=!,font=\normalfont}
-
-\newlength{\myparskip}
-\setlength{\myparskip}{.75\baselineskip plus 8\baselineskip minus .25\baselineskip}
-\usepackage[skip=\myparskip]{parskip}
-%\setlength{\parskip}{\myparskip}
-\newenvironment{miniblock}{%
- \vspace{.5\parskip}%
- \csname minipage*\endcsname[t]{1.0\linewidth}%
- \setlength{\parskip}{\myparskip}%
-}{%
- \csname endminipage*\endcsname%
-}
-
-
-\makeatletter
-\title{How to use the \texttt{sankey} package\\ to build Sankey diagrams\footnote{This file described version v\sankey@version.}}
-\date{Released \sankey@date}
-\author{Paul Gaborit\footnote{\href{mailto:paul.gaborit@gmail.com}{\texttt{paul.gaborit@gmail.com}}}}
-
-\hypersetup{
- pdftitle=How to use the sankey package to buid Sankey diagrams (v\sankey@version),
- pdfauthor=Paul Gaborit,
-}
-\makeatother
-
-
-\begin{document}
-\maketitle
-
-\begin{abstract}
- The \texttt{sankey} package provides macros and environments to build
- \emph{Sankey diagrams}%
- \footnote{\url{https://en.wikipedia.org/wiki/Sankey_diagram}} (or
- \emph{flow diagram} in which the width of the arrows is proportional
- to the flow rate). The idea cames out from
- \href{https://tex.stackexchange.com/q/40159/14500}{this question} on
- \href{https://tex.stackexchange.com/}{TeX.StackExchange}.
- %
-\end{abstract}
-
-{
- \setlength{\parskip}{0pt}
- \tableofcontents
- \listoffigures
-}
-
-% ------------------------------------------------------------
-\section{Preamble}
-% ------------------------------------------------------------
-
-To use the \code{sankey} package, insert the following line in your preamble:
-
-\begin{lstlisting}[style=LaTeXsmall]
-\usepackage{sankey}
-\end{lstlisting}
-
-% ------------------------------------------------------------
-\section{The \texttt{sankeydiagram} environment}
-% ------------------------------------------------------------
-
-A \code{sankeydiagram} environment nested in a \code{tikzpicture}
-environment activates the sankey macros:
-
-\begin{lstlisting}[style=LaTeXsmall]
-\begin{tikzpicture}
- \begin{sankeydiagram}[... options ...]
- ... sankey macros ...
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{lstlisting}
-
-% ------------------------------------------------------------
-\section{Sankey diagram options}
-% ------------------------------------------------------------
-
-The \code{sankey} package uses \code{pgfkeys} to define options via
-\emph{key=value} pairs.
-
-The options can be defined via the optional argument of the
-\code{sankeydiagram} environment:
-
-\begin{lstlisting}[style=LaTeXsmall]
-\begin{sankeydiagram}[debug=true]
- \sankeynode{name=a,quantity=1,angle=0,at={0,0}}
-\end{sankeydiagram}
-\end{lstlisting}
-
-The options can also be modified via the \code{\sankeyset} macro:
-
-\begin{lstlisting}[style=LaTeXsmall]
-\begin{sankeydiagram}
- \sankeyset{debug=true}
- \sankeynode{name=a,quantity=1,angle=0,at={0,0}}
-\end{sankeydiagram}
-\end{lstlisting}
-
-The options can be temporarily modified for a single macro:
-\begin{lstlisting}[style=LaTeXsmall]
-\begin{sankeydiagram}
- \sankeynode[debug=true]{name=a,quantity=1,angle=0,at={0,0}}
-\end{sankeydiagram}
-\end{lstlisting}
-% ------------------------------------------------------------
-\subsection{Keys to choose the scale}
-% ------------------------------------------------------------
-
-The scale or ratio of the Sankey diagram is the ratio between the %
-\code{ratio length} and the \code{ratio quantity}.
-
-\begin{sankeyoption}{ratio quantity}{\VAR{number}}{}{10}
- Quantity (in units of flow) to define ratio. The \VAR{number} can be
- any math expression.
-\end{sankeyoption}
-
-\begin{sankeyoption}{ratio length}{\VAR{distance}}{}{1cm}
- Distance (a graphical distance) to define scale.
-\end{sankeyoption}
-
-\begin{sankeyoption}{ratio}{\VAR{distance}/\VAR{number}}{}{1cm/10}
- Fix the ratio to \VAR{distance}/\VAR{number}.
-\end{sankeyoption}
-
-The initial ratio is 1\,cm/10 units.
-
-
-\textbf{Note:} the \code{sankey} package uses the \code{xfp} package to
-evaluate all math expressions that use quantities (in units of
-flow). You can therefore use quantities of a very large or very small
-order of magnitude. In contrast, for graphic distances, the sankey
-package uses the \code{pgfmath} package (all calculations must not
-exceed $\pm 16383.99999$).
-
-% ------------------------------------------------------------
-\subsection{Keys to define drawing parameters}
-% ------------------------------------------------------------
-
-\begin{sankeyoption}{minimum radius}{\VAR{distance}}{}{5mm}
- The minimum radius used by \code{\sankeyturn} and
- \code{\sankeydubins}.
-\end{sankeyoption}
-
-\begin{sankeyoption}{outin steps}{\VAR{integer}}{}{10}
- Number of steps used by the \code{\sankeyoutin} macro to simulate flow
- lanes with constant width.
-\end{sankeyoption}
-
-% ------------------------------------------------------------
-\subsection{Keys to choose drawing styles}
-% ------------------------------------------------------------
-
-\begin{sankeyoption}{fill/.style}{\VAR{style}}{}{{line width=0pt,fill=white}}
- This TikZ style is used to \emph{fill} all sankey paths.
-\end{sankeyoption}
-
-\begin{sankeyoption}{draw/.style}{\VAR{style}}{}{draw=black,line width=.4pt}
- This TikZ style is used to \emph{draw} all sankey paths.
-\end{sankeyoption}
-
-\begin{sankeyoption}{start style}{\VAR{style name}}{}{none}
- There are three predefined \emph{start} styles: \constant{none},
- \constant{simple}, \constant{arrow}.
-\end{sankeyoption}
-
-\begin{sankeyoption}{end style}{\VAR{style name}}{}{none}
- There are three predefined \emph{end} styles: \constant{none},
- \constant{simple}, \constant{arrow}.
-\end{sankeyoption}
-
-% ------------------------------------------------------------
-\subsection{Keys to define new \emph{start} and \emph{end} styles}
-% ------------------------------------------------------------
-
-\begin{sankeyoption}{new start style}{\{\VAR{name}\}\{\VAR{fill
- path}\}\{\VAR{draw path}\}}{}{}
- Define the new start style named \VAR{name} with its \VAR{fill
- path} and its \VAR{draw path}.
-\end{sankeyoption}
-
-\begin{sankeyoption}{new end style}{\{\VAR{name}\}\{\VAR{fill
- path}\}\{\VAR{draw path}\}}{}{}
- Define the new end style named \VAR{name} with its \VAR{fill
- path} and its \VAR{draw path}.
-\end{sankeyoption}
-
-\emph{Fill} and \emph{draw} paths are composed in a TikZ scope where
-the origin is the current Sankey node center (and its name is
-\code{\name}) and the coordinate system is rotated by its orientation.
-
-% ------------------------------------------------------------
-\subsection{The \emph{debug} key}
-% ------------------------------------------------------------
-
-\begin{sankeyoption}{debug}{\VAR{boolean}}{true}{false}
- To debug a sankey diagram.
-\end{sankeyoption}
-
-% ------------------------------------------------------------
-\section{Sankey nodes and flows}
-% ------------------------------------------------------------
-
-% ------------------------------------------------------------
-\subsection{Create Sankey nodes}
-% ------------------------------------------------------------
-
-% ------------------------------------------------------------
-
-\begin{miniblock}
-\MACRO\code{\sankeynode}\OPTARG{\VAR{options}}\ARG{\VAR{node parameters}}
-
-The \code{\sankeynode} macro defines a Sankey node. The \VAR{options}
-can be any Sankey diagram keys. To define a Sankey node, you must
-provide a \emph{name}, a \emph{quantity}, an \emph{angle} and a
-\emph{position} as \VAR{node parameters}.
-
-\begin{sankeyoption}[/sankey/node parameters]{name}{\VAR{name}}{}{}
- The \VAR{name} of the new Sankey node (and the associated TikZ node).
-\end{sankeyoption}
-
-\begin{sankeyoption}[/sankey/node parameters]{quantity}{\VAR{quantity}}{}{}
- The quantity (in flow unit) of the new Sankey node. The \VAR{quantity}
- can be any math expression.
-\end{sankeyoption}
-
-\begin{sankeyoption}[/sankey/node parameters]{angle}{\VAR{angle}}{}{}
- The orientation of the flow (0 points to the right) of the new Sankey
- node.
-\end{sankeyoption}
-
-\begin{sankeyoption}[/sankey/node parameters]{at}{\VAR{at}}{}{}
- The position of the new Sankey node (a TikZ coordinate \emph{without}
- round brackets or parentheses).
-\end{sankeyoption}
-
-\begin{sankeyoption}[/sankey/node parameters]{anchor}{\VAR{anchor}}{center}{center}
- Specify the anchor of the Sankey node. Possible values are
- \constant{center}, \constant{left} or \constant{right}.
-\end{sankeyoption}
-
-\begin{sankeyoption}[/sankey/node parameters]{as}{\VAR{name}}{}{}
- Copy the \emph{name}, the \emph{quantity}, the \emph{angle} and the
- \emph{position} of the Sankey node named \VAR{name}.
-\end{sankeyoption}
-
-A Sankey node is also a Tikz node but with only three anchors:
-\code{left}, \code{center} and \code{right}.
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}[debug]
- \draw[gray!30] (-1,-1) grid (8,2);
- \sankeynode{name=a,quantity=10,angle=0,at={0,0}}
- \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left}
- \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
-
- \foreach \nodename/\pos in {a/left,b/below left,c/above}{
- \foreach \ancname in {left,center,right}{
- \node[node font=\ttfamily\footnotesize,\pos=1mm of \nodename.\ancname,
- inner sep=0pt,rotate=\sankeygetnodeorient{\nodename},anchor=east]
- {\ancname\vphantom{g}};
- \fill[black] (\nodename.\ancname) circle(1pt);
- }
- }
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-% ------------------------------------------------------------
-
-\begin{miniblock}
-\MACRO\code{\sankeynodestart}\OPTARG{\VAR{options}}\ARG{\VAR{node parameters}}
-
-The \code{\sankeynodestart} creates and fills/draws a starting Sankey node:
-
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}]
- \draw[gray!30] (-1,-1) grid (8,2);
- \sankeynodestart{name=a,quantity=10,angle=0,at={0,0}}
- \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left}
- \sankeynodestart{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-% ------------------------------------------------------------
-
-
-\begin{miniblock}
-\MACRO\code{\sankeynodeend}\OPTARG{\VAR{options}}\ARG{\VAR{node
- parameters}}
-
-The \code{\sankeynodeend} creates
-and fills/draws an ending Sankey node:
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}[end style=simple,fill/.style={fill=orange!20}]
- \draw[gray!30] (-1,-1) grid (8,2);
- \sankeynodeend{name=a,quantity=10,angle=0,at={0,0}}
- \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
- \sankeynodeend{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-
-\subsection{Retrieve informations from a Sankey node}
-
-\MACRO\code{\sankeygetnodeqty}\ARG{\VAR{node name}}
-
-The expandable command \code{\sankeygetnodeqty} returns the quantity
-assigned to the Sankey node named \VAR{node name}.
-
-\MACRO\code{\sankeygetnodeorient}\ARG{\VAR{node name}}
-
-The expandable command \code{\sankeygetnodeorient} returns the angle
-(orientation) assigned to the Sankey node named \VAR{node name}.
-
-% ------------------------------------------------------------
-\newpage
-\subsection{Move nodes}
-% ------------------------------------------------------------
-
-The \code{\sankeyadvance} and \code{\sankeyturn} commands move a Sankey
-node (and fill/draw a portion of the Sankey flow). Then the previous
-position of the Sankey node is accessible via the \code{-old} suffix (if
-you move the \code{a} node, its previous position is the \code{a-old}
-node).
-
-\subsubsection{forward commands}
-
-\begin{miniblock}
-\MACRO\code{\sankeyadvance}\OPTARG{\VAR{options}}\ARG{\VAR{node
- name}}\ARG{\VAR{distance}}
-
-The \code{\sankeyadvance} moves the sankey node straight ahead and
-fills/draws this portion of the sankey path.
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}]
- \draw[gray!30] (-1,-1) grid (8,2);
- \sankeynodestart{name=a,quantity=10,angle=0,at={0,0}}
- \sankeyadvance{a}{1cm}
- \sankeynode[debug]{as=a}
- \sankeynode[debug]{as=a-old}
- \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left}
- \sankeyadvance{b}{1cm}
- \sankeynodestart{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
- \sankeyadvance{c}{5mm}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-
-\begin{miniblock}
-\MACRO\code{\sankeyturn}\OPTARG{\VAR{options}}\ARG{\VAR{node
- name}}\ARG{\VAR{angle}}
-
-The \code{\sankeyturn} macro moves the sankey node by turning to one
-side or the other and fills/draws this portion of the sankey path. A
-\emph{positive} \VAR{angle} turns left while a \emph{negative}
-\VAR{angle} turns right.
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}]
- \draw[gray!30] (-1,-1) grid (8,2);
- \sankeynodestart{name=a,quantity=10,angle=0,at={0,0}}
- \sankeyturn{a}{90}
- \sankeynode[debug]{as=a}
- \sankeynode[debug]{as=a-old}
- \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left}
- \sankeyturn[minimum radius=1cm]{b}{-45}
- \sankeynodestart{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
- \sankeyturn{c}{180}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-
-\subsubsection{backward commands}
-
-\begin{miniblock}
-\MACRO\code{\sankeyadvance*}\OPTARG{\VAR{options}}\ARG{\VAR{node
- name}}\ARG{\VAR{distance}}
-
-The \code{\sankeyadvance*} moves the sankey node straight back and
-fills/draws this portion of the sankey path.
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}[end style=arrow,fill/.style={fill=orange!20}]
- \draw[gray!30] (-1,-1) grid (8,2);
- \sankeynodeend{name=a,quantity=10,angle=0,at={0,0}}
- \sankeyadvance*{a}{1cm}
- \sankeynode[debug]{as=a}
- \sankeynode[debug]{as=a-old}
- \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
- \sankeyadvance*{b}{1cm}
- \sankeynodeend{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
- \sankeyadvance*{c}{5mm}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-
-\begin{miniblock}
-\MACRO\code{\sankeyturn*}\OPTARG{\VAR{options}}\ARG{\VAR{node
- name}}\ARG{\VAR{angle}}
-
-The \code{\sankeyturn*} macro moves the sankey node backwards by turning
-right or left and fills/draws this portion of the sankey path. A
-\emph{positive} \VAR{angle} turns left while a \emph{negative}
-\VAR{angle} turns right.
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}[end style=simple,fill/.style={fill=orange!20}]
- \draw[gray!30] (-1,-1) grid (8,2);
- \sankeynodeend{name=a,quantity=10,angle=0,at={0,0}}
- \sankeyturn*{a}{90}
- \sankeynode[debug]{as=a}
- \sankeynode[debug]{as=a-old}
- \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
- \sankeyturn*[minimum radius=1cm]{b}{-45}
- \sankeynodeend{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
- \sankeyturn*{c}{180}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-
-\subsection{Links between nodes}
-
-\begin{miniblock}
- \MACRO\code{\sankeyoutin}\OPTARG{\VAR{options}}\ARG{\VAR{node
- A}}\ARG{\VAR{node B}}
-
- The \code{\sankeyoutin} macro fills/draws a lane between \VAR{node A}
- and \VAR{node B} using a Bézier curve with regular steps (10 steps by
- default) to simulate constant width lane.
-
- The constant width and the minimum curvature are \emph{not} guaranted!
-\end{miniblock}
-
-\begin{miniblock}
- \MACRO\code{\sankeydubins}\OPTARG{\VAR{options}}\ARG{\VAR{node
- A}}\ARG{\VAR{node B}}
-
- The \code{\sankeydubins} macro fills/draws a lane between \VAR{node A}
- and \VAR{node B} using a Dubins
- path\footnote{\url{https://en.wikipedia.org/wiki/Dubins_path}}.
-
- The constant width and the minimum curvature are guaranted.
-\end{miniblock}
-
-\subsubsection{Comparison betwen \texttt{outin} and \texttt{dubins}
- paths}
-
-\begin{miniblock}
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}[start style=simple,end style=arrow]
- \draw[gray!30] (0,-1) grid (10,3.5);
- %
- \sankeyset{fill/.style={fill=orange!20}}
- \sankeynodestart{name=a,at={1,0},angle=0,quantity=5}
- \sankeynodeend{name=b,at={5,3},angle=0,quantity=5}
- \sankeyoutin{a}{b}
- %
- \sankeyset{fill/.style={fill=red!20}}
- \sankeynodestart{name=a,at={3,0},angle=0,quantity=5}
- \sankeynodeend{name=b,at={7,3},angle=0,quantity=5}
- \sankeyoutin[outin steps=2]{a}{b}
- %
- \sankeyset{fill/.style={fill=lime!40}}
- \sankeynodestart{name=a,at={5,0},angle=0,quantity=5}
- \sankeynodeend{name=b,at={(9,3},angle=0,quantity=5}
- \sankeydubins[minimum radius=5mm]{a}{b}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-
-\begin{miniblock}
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}[start style=simple,end style=arrow]
- \draw[gray!30] (0,0) grid (8,4.5);
- %
- \sankeyset{fill/.style={fill=orange!20}}
- \sankeynodestart{name=a,at={1,1},angle=0,quantity=5}
- \sankeynodeend{name=b,at={3,4},angle=0,quantity=5}
- \sankeyoutin{a}{b}
- %
- \sankeyset{fill/.style={fill=red!20}}
- \sankeynodestart{name=a,at={3,1},angle=0,quantity=5}
- \sankeynodeend{name=b,at={5,4},angle=0,quantity=5}
- \sankeyoutin[outin steps=2]{a}{b}
- %
- \sankeyset{fill/.style={fill=lime!40}}
- \sankeynodestart{name=a,at={5,1},angle=0,quantity=5}
- \sankeynodeend{name=b,at={(7,4},angle=0,quantity=5}
- \sankeydubins[minimum radius=5mm]{a}{b}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-
-\begin{miniblock}
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}[start style=simple,end style=arrow]
- \draw[gray!30] (0,0) grid ((6,4.5);
- %
- \sankeyset{fill/.style={fill=orange!20}}
- \sankeynodestart{name=a,at={1,1},angle=0,quantity=5}
- \sankeynodeend{name=b,at={1,4},angle=0,quantity=5}
- \sankeyoutin{a}{b}
- %
- \sankeyset{fill/.style={fill=red!20}}
- \sankeynodestart{name=a,at={3,1},angle=0,quantity=5}
- \sankeynodeend{name=b,at={3,4},angle=0,quantity=5}
- \sankeyoutin[outin steps=2]{a}{b}
- %
- \sankeyset{fill/.style={fill=lime!40}}
- \sankeynodestart{name=a,at={5,1},angle=0,quantity=5}
- \sankeynodeend{name=b,at={(5,4},angle=0,quantity=5}
- \sankeydubins[minimum radius=5mm]{a}{b}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-
-\subsubsection{Examples of \texttt{dubins} paths}
-
-\begin{miniblock}
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}[start style=simple,end style=arrow]
- \draw[gray!30] (-1,-1) grid (10,2.5);
-
- \sankeyset{
- fill/.style={fill=lime!40},
- draw/.style={draw=green!50!black,line width=2pt},
- }
-
- \sankeynodestart{name=a,at={0,0},angle=0,quantity=5}
- \sankeynodeend{name=b,at={0,2},angle=0,quantity=5}
- \sankeydubins[minimum radius=2mm]{a}{b}
-
- \fill[green!50!black] (2,0) coordinate (c) circle(2pt);
- \sankeynodestart{name=a,at={[shift={(c)}]90:5mm},angle=0,quantity=5}
- \sankeynodeend{name=b,at={[shift={(c)}]150:5mm},angle=60,quantity=5}
- \sankeydubins[minimum radius=2.5mm]{a}{b}
-
- \sankeynodestart{name=a,at={3.5,0},angle=0,quantity=5}
- \sankeynodeend{name=b,at={3.5,.75},angle=-180,quantity=5}
- \sankeydubins[minimum radius=5mm]{a}{b}
-
- \sankeynodestart{name=a,at={7,1},angle=0,quantity=5}
- \sankeynodeend{name=b,at={7,1.75},angle=0,quantity=5}
- \sankeydubins[minimum radius=2.5mm]{a}{b}
-
- \sankeynodestart{name=a,at={9,0},angle=0,quantity=5}
- \sankeynodeend{name=b,at={9,2},angle=180,quantity=5}
- \sankeydubins[minimum radius=2.5mm]{a}{b}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-
-\subsection{Pure filling/drawing macros}
-
-\begin{miniblock}
-\MACRO\code{\sankeystart}\OPTARG{\VAR{options}}\ARG{\VAR{name}}
-
-The \code{\sankeystart} fills/draws a starting extremity attached to the
-preexistent Sankey node \VAR{name}:
-
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}
- [start style=arrow,fill/.style={fill=cyan!20},draw/.style={draw=blue}]
- \draw[gray!30] (-1,-1) grid (8,2);
- \sankeynode{name=a,quantity=10,angle=0,at={0,0}}
- \sankeystart{a}
- \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left}
- \sankeystart{b}
- \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
- \sankeystart{c}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-% ------------------------------------------------------------
-
-
-\begin{miniblock}
- \MACRO\code{\sankeyend}\OPTARG{\VAR{options}}\ARG{\VAR{name}}
-
- The \code{\sankeyend} fills/draws an ending extremity attached to the
- preexistent Sankey node \VAR{name}:
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}
- [end style=simple,fill/.style={fill=cyan!20},draw/.style={draw=blue}]
- \draw[gray!30] (-1,-1) grid (8,2);
- \sankeynode{name=a,quantity=10,angle=0,at={0,0}}
- \sankeyend{a}
- \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left}
- \sankeyend{b}
- \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
- \sankeyend{c}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-
-\subsection{Forked node}
-
-\begin{miniblock}
- \MACRO\code{\sankeyfork}\OPTARG{\VAR{options}}\ARG{\VAR{node}}\ARG{\VAR{quantity/name pairs}}
-
- The \code{\sankeyfork} macro splits a Sankey node in a list of new
- Sankey nodes. The \VAR{quantity/name pairs} is a comma separated list
- of \emph{quantity/name} pairs. The sum of all quantities \emph{must}
- be equal to the quantity of the node to fork.
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}[debug]
- \draw[gray!30] (-3,-2) grid (3,1);
- \sankeynode{name=a,quantity=50,angle=-80,at={0,0}}
- \sankeyfork{a}{30/b,10/c,10/d}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \begin{sankeydiagram}
- \sankeyset{
- start style=arrow,end style=arrow,
- fill/.style={fill=yellow!10,line width=0pt,draw=yellow!10},
- }
- \draw[gray!30] (-4,-3) grid (4,4);
- \sankeynode{name=a,quantity=40,angle=-90,at={0,0}}
- \sankeyfork{a}{25/b,10/c,5/d}
- \sankeyturn*{b}{90}
- \sankeyturn*[minimum radius=2cm]{c}{-45}
- \sankeyturn*[minimum radius=2cm]{c}{45}
- \sankeyturn*[minimum radius=5mm]{d}{-90}
- \sankeyadvance{a}{2cm}
- \foreach \nodename in {b,c,d}{
- \sankeystart{\nodename}
- }
- \sankeyend{a}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-{\centering\input{\samplecodename}\par}
-\end{miniblock}
-
-\section{Miscellaneous}
-
-\subsection{The \texttt{debug} layer}
-
-The \code{debug} option key uses the \code{sankeydebug} layer to draw
-above the \code{main} TikZ layer (via \code{\pgfsetlayers}, the
-\code{sankey} package installs four layers: \code{background},
-\code{main}, \code{foreground}, \code{sankeydebug}).
-
-The four following styles define how to display debug informations:
-
-
-\begin{lstlisting}[style=LaTeXsmall]
-\sankeyset{
- % debug color used by all debug macros
- debug color/.style={/utils/exec={\colorlet{debug color}{#1}}},
- debug color=red!75!black,
- % debug line between left and right anchors
- debug line/.style={draw=debug color,|-|},
- % debug line between center and label
- debug normal/.style={draw=debug color},
- % debug node label
- debug label/.style={
- draw,
- font=\ttfamily\tiny,
- text=debug color,text opacity=1,
- inner sep=.1em,
- fill=white,fill opacity=1,
- rounded corners=.1em,
- },
-}
-\end{lstlisting}
-
-\subsection{The \texttt{dubins} TikZ library}
-
-The \code{sankey} package uses the \code{dubins} TikZ library (the
-\code{tikzlibrarydubins.code.tex} file) to compute Dubins paths. The
-documentation for this library does not yet exist.
-
-\subsection{How to duplicate a Sankey node}
-
-\MACRO\code{\sankeynodealias}\ARG{\VAR{origname}}\ARG{\VAR{clonename}}
-
-The \code{\sankeynodealias} macro clones the Sankey node named
-\VAR{origname} into the Sankey node named \VAR{clonename}.
-
-So, you can clone a Sankey node via two methods:
-
-\begin{lstlisting}[style=LaTeXsmall]
-\sankeynode{name=a,quantity=10,angle=0,at={0,0}}
-\sankeynode{as=a,name=b}
-\end{lstlisting}
-
-\begin{lstlisting}[style=LaTeXsmall]
-\sankeynode{name=a,quantity=10,angle=0,at={0,0}}
-\sankeynodealias{a}{b}
-\end{lstlisting}
-
-\subsection{How to define new start and end styles}
-
-Here are the definitions of the \code{arrow} styles:
-
-\begin{lstlisting}[style=LaTeXsmall]
-\sankeyset{
- % arrow style
- new start style={arrow}{
- (\name.left) -- ++(-10pt,0)
- -- ([xshift=-10pt/6]\name.center)
- -- ([xshift=-10pt]\name.right)
- -- (\name.right) -- cycle
- }{
- (\name.left) -- ++(-10pt,0)
- -- ([xshift=-10pt/6]\name.center)
- -- ([xshift=-10pt]\name.right)
- -- (\name.right)
- },
- new end style={arrow}{
- (\name.left) -- ([yshift=1mm]\name.left)
- -- ([xshift=10pt]\name.center)
- -- ([yshift=-1mm]\name.right) -- (\name.right) -- cycle
- }{
- (\name.left) -- ([yshift=1mm]\name.left)
- -- ([xshift=10pt]\name.center)
- -- ([yshift=-1mm]\name.right) -- (\name.right)
- },
-}
-\end{lstlisting}
-
-\section{History}
-
-\begin{itemize}
-\item[v2.0] (2021/01/27)
- \begin{itemize}
- \item First public version (on CTAN).
- \end{itemize}
-\item[v1.0] (2016/03/06)
- \begin{itemize}
- \item First version.
- \end{itemize}
-\end{itemize}
-
-\clearpage
-\section{Examples}
-
-\subsection{Simple example}
-
-See figure~\ref{fig:simple-example}.
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \colorlet{cold}[rgb]{cyan!75!blue!50!white}
- \colorlet{hot}[rgb]{red!50!orange!75!white}
- \begin{sankeydiagram}
- \sankeyset{
- ratio=90pt/6,
- minimum radius=15pt,
- start style=simple,
- end style=simple,
- % debug,
- draw/.style={
- draw=blue!50!cyan,
- line width=1pt,
- line cap=round,line join=round,
- },
- cold/.style={
- fill/.style={
- draw=cold,
- line width=0pt,
- fill=cold,
- },
- },
- cold to hot/.style={
- fill/.style={
- fill=none,
- top color=cold,
- bottom color=hot,
- middle color=yellow,
- },
- },
- hot/.style={
- fill/.style={
- draw=hot,
- line width=0pt,
- fill=hot,
- },
- },
- }
-
- \sankeyset{cold}
- \sankeynodestart{name=p0,at={0,100},angle=-90,quantity=6}
- \sankeyadvance{p0}{50pt}
-
- \sankeyfork{p0}{3/p1,3/p2}
-
- \sankeyturn{p1}{90}
- \sankeyadvance{p1}{20pt}
-
- \sankeyadvance{p2}{60pt}
-
- \sankeyfork{p2}{2/p3,1/p4}
-
- \sankeyturn{p3}{90}
- \sankeyadvance{p3}{50pt}
-
- \sankeyfork{p3}{1/p5,1/p6}
-
- \sankeyadvance{p5}{70pt}
-
- \sankeyfork{p1}{1/p7,1/p8,1/p9}
- \sankeyadvance{p7}{50pt}
- \sankeyadvance{p9}{50pt}
-
- \sankeyadvance{p4}{40pt}
- \sankeyturn{p4}{90}
- \sankeyadvance{p4}{65pt}
-
- \sankeyadvance{p7}{40pt}
-
- \sankeynode{name=p11,at={[shift={(50pt,-15pt)}]p7},angle=0,quantity=3}
- \sankeyfork{p11}{1/p7a,1/p9a,1/p5a}
- \sankeyoutin{p7}{p7a}
- \sankeyoutin{p9}{p9a}
- \sankeyoutin{p5}{p5a}
- \sankeyadvance{p11}{30pt}
- \sankeyend{p11}
-
- \sankeyturn{p8}{-90}
- \sankeyturn{p6}{-90}
- \sankeyturn{p4}{-90}
-
- \sankeyset{hot}
-
- \sankeyadvance[cold to hot]{p8}{40pt}
-
- \sankeynode{name=p10,at={[shift={(-15pt,-60pt)}]p8},angle=-90,quantity=3}
- \sankeyfork{p10}{1/p8a,1/p6a,1/p4a}
- \sankeyoutin[cold to hot]{p4}{p4a}
- \sankeyoutin[cold to hot]{p6}{p6a}
- \sankeyoutin{p8}{p8a}
- \sankeyadvance{p10}{30pt}
- \sankeyend{p10}
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-\begin{figure}[b!]
- \centering
- \input{\samplecodename}
- \caption{Simple example}
- \label{fig:simple-example}
-\end{figure}
-\clearpage
-\subsection{Example from question on TeX.se}
-
-This example cames from
-\href{https://tex.stackexchange.com/q/40159/14500}{this question} on
-\href{https://tex.stackexchange.com/}{TeX.StackExchange}.
-
-See figure~\ref{fig:texse-example}.
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- \renewcommand*\sfdefault{txss}
-
- \begin{sankeydiagram}
-
- \sankeyset{
- ratio=4cm/524.3,
- minimum radius=3mm,
- start style=arrow,
- end style=arrow,
- % debug,
- fill/.style={
- line width=0pt,
- fill=cyan!50!blue!50!black,
- draw=cyan!50!blue!50!black,
- },
- draw/.style={draw=none},
- }
-
- \sankeynodestart{name=B,at={-.5,0},angle=-90,quantity=7.2}
- \coordinate[below=1mm of B.center] (B label);
- \sankeyadvance{B}{5mm}
- \sankeynodestart{name=GI,at={1,0},angle=-90,quantity=137.3}
- \coordinate[below=1mm of GI.center] (GI label);
- \sankeyadvance{GI}{5mm}
- \sankeynodestart{name=I,at={4,0},angle=-90,quantity=397.8}
- \coordinate[below=1mm of I.center] (I label);
- \sankeynode{name=EI,at={2.86,-3},angle=-90,quantity=542.3}
- \sankeyfork{EI}{397.8/Ia,137.3/GIa,7.2/Ba}
- \sankeydubins[minimum radius=1.2cm]{I}{Ia}
- \sankeyoutin{GI}{GIa}
- \sankeyoutin{B}{Ba}
- \sankeyadvance{EI}{5mm}
- \coordinate (EI label) at (EI);
- \sankeyadvance{EI}{5mm}
- \sankeyfork{EI}{63.1/EB,479.2/P}
-
- \sankeyturn{EB}{90}
- \sankeyadvance{EB}{4cm}
- \coordinate (EB label) at ($(EB)!.5!(EB-old)$);
- \sankeyend{EB}
-
- \sankeyadvance{P}{10mm}
- \coordinate (P label) at (P);
- \sankeyadvance{P}{5mm}
-
- \sankeyfork{P}{33.5/NV,445.7/P}
-
- {
- \colorlet{NV color}{cyan!80!lime!50!gray}
- \sankeyset{fill/.append style={fill=NV color,draw=NV color}}
- \sankeyturn{NV}{90}
- \sankeynode{as=NV,name=NV2,at=NV -| EB}
- \sankeyoutin{NV}{NV2}
- \coordinate (NV label) at (NV -| EB label);
- \sankeyend{NV2}
- }
-
- \sankeyadvance{P}{10mm}
- \sankeyfork{P}{118.1/U,327.6/P}
-
- {
- \sankeyset{
- fill/.style={fill=orange!70!gray!50,draw=orange!70!gray!50}
- }
- \sankeyturn{U}{90}
- \sankeynode{as=U,name=U2,at=U -| EB}
- \sankeyoutin{U}{U2}
- \coordinate (U label) at (U -| EB label);
- \sankeyend{U2}
- }
-
- \sankeyadvance{P}{10mm}
-
- \sankeyfork{P}{327.2/P,0.4/SD}
-
- {
- \sankeyturn{SD}{-90}
- \sankeyadvance{SD}{15mm}
- \coordinate (SD label) at (SD);
- \sankeyadvance{SD}{15mm}
- \sankeyend{SD}
- }
-
- \sankeyadvance{P}{8mm}
- \sankeyfork{P}{18.8/VE,308.4/E}
-
- {
- \sankeyset{fill/.append style={orange!70!gray!30}}
- \sankeyturn{VE}{90}
- \sankeynode{as=VE,name=VE2,at=VE -| EB}
- \sankeyoutin{VE}{VE2}
- \coordinate (VE label) at (VE -| EB label);
- \sankeyend{VE2}
- }
-
- \sankeyadvance{E}{8mm}
- \coordinate (E label) at (E);
- \sankeyadvance{E}{20mm}
-
- \sankeyfork{E}{135.1/H+GHD,87.2/V,86.1/In}
-
- \sankeyturn{In}{-90}
- \sankeyadvance{In}{10mm}
- \sankeyturn{In}{90}
- \sankeyadvance{In}{5mm}
- \coordinate (In label) at (In);
- \sankeyadvance{In}{10mm}
- \sankeyend{In}
-
- \sankeynode{as=V,name=V2,at=V|-In label}
- \sankeyoutin{V}{V2}
- \coordinate (V label) at (V2);
- \sankeyadvance{V2}{10mm}
- \sankeyend{V2}
-
- \sankeyturn{H+GHD}{90}
- \sankeyadvance{H+GHD}{5mm}
- \sankeyfork{H+GHD}{47.0/GHD,88.1/H}
-
- \sankeyturn{H}{-90}
- \sankeynode{as=H,name=H2,at=H|-In label}
- \sankeyoutin{H}{H2}
- \coordinate (H label) at (H2);
- \sankeyadvance{H2}{10mm}
- \sankeyend{H2}
-
- \sankeyadvance{GHD}{30mm}
- \sankeyturn{GHD}{-90}
- \sankeynode{as=GHD,name=GHD2,at=GHD|-In label}
- \sankeyoutin{GHD}{GHD2}
- \coordinate (GHD label) at (GHD2);
- \sankeyadvance{GHD2}{10mm}
- \sankeyend{GHD2}
- \end{sankeydiagram}
-
- % labels
- \tikzset{
- label/.style={
- fill=white,fill opacity=.8,text opacity=1,
- inner sep=1mm,
- text=cyan!50!blue!50!black,
- inner xsep=2mm,
- font=\sffamily\bfseries\footnotesize,
- align=center,
- },
- }
- \node[label,anchor=north] (B label) at (B label) {7.2};
- \node[label,left=1mm of B label] {Bestands-\\entnahme};
- \node[label,anchor=north] at (GI label) {137.3};
- \node[label,above=5mm of GI label] {Gewinnung\\im Inland};
- \node[label,anchor=north] at (I label) {397.8};
- \node[label,above=5mm of I label] {Import};
-
- \node[label] at (EI label) {542.3\\Energieaufkommen im Inland};
-
- \node[label,anchor=center] (EB label) at (EB label) {63.1};
- \node[label,above=1mm of EB label] {Export und\\Bunkerung};
-
- \node[label] at (P label) {479.2\\Primärenergieverbrauch};
-
- \node[label,anchor=center] (NV label) at (NV label) {33.5};
- \node[label,above=0mm of NV label] {Nichtenergetischer Verbrauch};
-
- \node[label,anchor=center] (U label) at (U label) {118.1};
- \node[label,below=3mm of U label] {Umwandlungsverluste};
-
- \node[label,anchor=center] (SD label) at (SD label) {0.4};
- \node[label,above=0mm of SD label] {Statistische\\Differenzen};
-
- \node[label,anchor=center] (VE label) at (VE label) {18.8};
- \node[label,below=0mm of VE label] {Verbrauch in den\\Energiesktoren};
-
- \node[label,anchor=north] (E label) at (E label)
- {308.4\\Endenergieverbrauch};
-
- \node[label,anchor=north] (In label) at (In label) {86.1};
- \node[label,anchor=north,below=1cm of In label] {Industrie};
-
- \node[label,anchor=north] (V label) at (V label) {87.2};
- \node[label,anchor=north,below=1cm of V label] {Verkehr};
-
- \node[label,anchor=north] (H label) at (H label) {88.1};
- \node[label,anchor=north,below=1cm of H label] {Haushalte};
-
- \node[label,anchor=north] (GHD label) at (GHD label) {47.0};
- \node[label,anchor=north,below=1cm of GHD label]
- {Gewerbe, Handel\\Diensleistungen};
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[style=LaTeXsmall]{\samplecodename}
-%
-\begin{figure}
- \centering
- %\rule{\linewidth}{1pt}\\
- \input{\samplecodename}
- \caption{Example from TeX.se question}
- \label{fig:texse-example}
-\end{figure}
-
-\clearpage
-\subsection{Very nice example -- Nadieh Bremer creation}
-
-Graphic designer Nadieh Bremer created this very nice Sankey
-diagram\footnote{\url{https://www.visualcinnamon.com/portfolio/adyen-report-2019/}}
-for Adyen's second half 2018 report to shareholders. It is coded here
-with her kind permission.
-
-You can change the data values between lines 28 and 53.
-
-See figure~\ref{fig:nice-example}.
-
-\begin{filecontents*}{\samplecodename}
-\begin{tikzpicture}
- %
- \renewcommand*\sfdefault{txss}
- \sffamily
- \sisetup{
- detect-all=true,
- group-separator={,},
- group-minimum-digits=4,
- }
- % storage of labels
- \newcommand\LabSet[2]{% none name, label
- \expandafter\edef\csname #1Lab\endcsname{#2}}
- \newcommand\Lab[1]{% node name
- \csname #1Lab\endcsname}
- % storage of quantities
- \newcommand\QtySet[2]{% node name, quantity
- \expandafter\edef\csname #1Qty\endcsname{\fpeval{#2}}}
- \newcommand\Qty[1]{% node name
- \csname #1Qty\endcsname}
- % all nodes with their name, label and quantity
- \sankeyset{
- def data/.code args={#1/#2/#3}{% node name/label/values
- \LabSet{#1}{#2}
- \QtySet{#1}{#3}
- \typeout{#1: \Qty{#1}€ (\Lab{#1})}
- },
- def data/.list={
- {Pf/Processing\\fees/71713},
- {Sog/Sales of\\good/4547},
- {Sf/Settlement\\fees/842075},
- {Os/Other\\services/37532},
- {R/Revenues/\Qty{Pf}+\Qty{Sog}+\Qty{Sf}+\Qty{Os}},
- {Coi/Cost of Inventory/5151},
- {Ciffi/Cost insecure from financial institutions/758234},
- {Nr/Net revenue/\Qty{R}-\Qty{Coi}-\Qty{Ciffi}},
- {Aadotaifa/Amortization and\\depreciation of tangible and\\%
- intangible fixed assets/4688},
- {Ssapc/Social securities and\\pension costs/7860},
- {Was/Wages and salaries/35627},
- {Ooe/Other operating expenses/37346},
- {Nr2/-/\Qty{Nr}-\Qty{Aadotaifa}-\Qty{Ssapc}-\Qty{Was}-\Qty{Ooe}},
- {Oi/Other income/47},
- {Ibiiieait/Income before interest income,\\interest expense and %
- income taxes/\Qty{Nr2}+\Qty{Oi}},
- {Fe/Finance expense/561},
- {Ofr/Other financial results/2533},
- {Ibiiieait2/-/\Qty{Ibiiieait}-\Qty{Fe}-\Qty{Ofr}},
- {Fi/Finance income/204},
- {Ibit/Income before income taxes/\Qty{Ibiiieait2}+\Qty{Fi}},
- {It/Income taxes/21134},
- {Niftp/Net income for the period/\Qty{Ibit}-\Qty{It}},
- {Octa/Other currency\\translation adjustments/785},
- {Tci/Total comprehensive income/\Qty{Niftp}+\Qty{Octa}}
- },
- }
-
- \definecolor{mygreen}{RGB}{9,192,82}
- \tikzset{
- cost node/.style 2 args={
- overlay,
- align=flush center,
- node font=\footnotesize\sffamily\bfseries,
- inner sep=0,
- node contents={%
- {\mdseries€\,\num{#1}}\\%
- #2\vphantom{g}%
- },
- },
- white hash/.style={
- draw=none,fill=none,
- pattern={Lines[angle=60,line width=2pt,distance=4pt]},
- pattern color=white,
- },
- line sep/.style={draw=white,line width=1pt},
- left label/.style={left=#1,align=flush right,anchor=north east},
- right label/.style={right=#1,align=flush left},
- right label hashed/.style={
- right=1mm of $(#1.left)!.5!(#1-old.left)$,align=flush left,
- },
- left label hashed/.style={
- left=1mm of $(#1.right)!.5!(#1-old.right)$,align=flush right,
- },
- }
-
- \newcommand\turnandstop[1]{
- \sankeyturn[green to greenwhite]{#1}{-90}
- \sankeynode{as=#1,name=#1-e,at={#1 -| Coi}}
- \sankeyoutin[greenwhite to white]{#1}{#1-e}
- \node[cost node={\Qty{#1}}{\Lab{#1}},left label={1mm of #1-e.right}];
- }
-
- \begin{sankeydiagram}
- \sankeyset{
- ratio=28em/1000000,
- minimum radius=2cm,
- start style=none,
- % default fill and draw styles
- fill/.style={
- line width=0pt,
- fill=mygreen,
- },
- draw/.style={draw=none},
- % specific fill and draw styles
- green to greenwhite/.style={
- fill/.style={
- line width=0pt,
- right color=mygreen,
- left color=mygreen!20!white,
- }
- },
- greenwhite to white/.style={
- fill/.style={
- line width=0pt,
- right color=mygreen!20!white,
- left color=mygreen!5!white,
- }
- },
- dashed/.style={draw/.style={draw=mygreen,dashed}},
- % debug,
- }
-
- \coordinate (top) at (0,2em);
-
- \sankeynodestart{name=Pf,quantity=\Qty{Pf},
- at={0,0},angle=-90}
- \node[cost node={\Qty{Pf}}{\Lab{Pf}},above=.5em of Pf.center];
-
- \sankeynodestart{name=Sog,quantity=\Qty{Sog},
- at={[xshift=4em]Pf.left},angle=-90,anchor=right}
- \node[cost node={\Qty{Sog}}{\Lab{Sog}},above=.5em of Sog.center];
-
- \sankeynodestart{name=Sf,quantity=\Qty{Sf},
- at={[xshift=2em]Sog.left},angle=-90,anchor=right}
- \node[cost node={\Qty{Sf}}{\Lab{Sf}},above=.5em of Sf.center];
-
- \sankeynodestart{name=Os,quantity=\Qty{Os},
- at={[xshift=2em]Sf.left},angle=-90,anchor=right}
- \node[cost node={\Qty{Os}}{\Lab{Os}},above=.5em of Os.center];
-
- \sankeynode{name=R,quantity=\Qty{R},
- at={[yshift=-10em]Sf.center},angle=-90}
- \sankeyfork{R}{\Qty{Os}/Os-a,\Qty{Sf}/Sf-a,\Qty{Sog}/Sog-a,\Qty{Pf}/Pf-a}
-
- \foreach \nodename in {Pf,Sog,Sf,Os}{
- \sankeyoutin[fill/.style={top color=white,bottom color=mygreen}]
- {\nodename}{\nodename-a}
- }
-
- \sankeyadvance{R}{1em}
- \node[cost node={\Qty{R}}{\Lab{R}},right label hashed=R];
-
- \sankeyfork{R}{\Qty{Ciffi}/Ciffi,\Qty{Nr}/Nr,\Qty{Coi}/Coi}
-
- \sankeyturn[minimum radius=1.cm]{Ciffi}{90}
- \node[cost node={\Qty{Ciffi}}{\Lab{Ciffi}},
- at={([shift={(1mm,0)}]Ciffi.center)},rotate=-90,
- anchor=south,align=flush left,node font=\scriptsize\sffamily\bfseries];
-
- \sankeyturn[green to greenwhite]{Coi}{-90}
- \sankeyadvance[greenwhite to white]{Coi}{1em}
- \node[cost node={\Qty{Coi}}{\Lab{Coi}},
- left={1mm of [yshift=.75ex]Coi.left},
- align=flush right,anchor=north east,overlay];
-
- \sankeyadvance{Nr}{9em}
- \sankeyadvance{Nr}{1em}
- \node[cost node={\Qty{Nr}}{\Lab{Nr}},
- left label hashed=Nr,node font=\large\sffamily\bfseries];
-
- \sankeyfork{Nr}{\Qty{Nr2}/Nr2,\Qty{Ooe}/Ooe,
- \Qty{Was}/Was,\Qty{Ssapc}/Ssapc,\Qty{Aadotaifa}/Aadotaifa}
-
- \turnandstop{Aadotaifa}
-
- \sankeyadvance{Ssapc}{5em}
- \turnandstop{Ssapc}
-
- \sankeyadvance{Was}{9em}
- \turnandstop{Was}
-
- \sankeyadvance{Ooe}{12em}
- \turnandstop{Ooe}
-
- \sankeyadvance{Nr2}{15em}
- \sankeynode{name=Ibiiieait,quantity=\Qty{Ibiiieait},
- angle=-90,anchor=right,at={Nr2.right}}
- \sankeyfork{Ibiiieait}{\Qty{Oi}/Oi,\Qty{Nr2}/Nr2-e}
-
- \sankeyturn*[minimum radius=1cm,dashed]{Oi}{90}
- \node[cost node={\Qty{Oi}}{\Lab{Oi}},right label=1mm of Oi.left];
-
- \sankeyadvance{Ibiiieait}{1em}
- \node[cost node={\Qty{Ibiiieait}}{\Lab{Ibiiieait}},
- right label hashed=Ibiiieait];
-
- \sankeyfork{Ibiiieait}
- {\Qty{Ibiiieait2}/Ibiiieait2,\Qty{Ofr}/Ofr,\Qty{Fe}/Fe}
-
- \turnandstop{Fe}
-
- \sankeyadvance{Ofr}{3em}
- \turnandstop{Ofr}
-
- \sankeyadvance{Ibiiieait2}{6em}
- \sankeynode{name=Ibit,quantity={\Qty{Ibiiieait2}+\Qty{Fi}},
- angle=-90,anchor=right,at={Ibiiieait2.right}}
- \sankeyfork{Ibit}{\Qty{Fi}/Fi,\Qty{Ibiiieait2}/Ibiiieait2-e}
-
- \sankeyturn*[minimum radius=1cm,dashed]{Fi}{90}
- \node[cost node={\Qty{Fi}}{\Lab{Fi}},right label=1mm of Fi.left];
-
- \sankeyadvance{Ibit}{1em}
- \node[cost node={\Qty{Ibit}}{\Lab{Ibit}},right label hashed=Ibit];
-
- \sankeyfork{Ibit}{\Qty{Niftp}/Niftp,\Qty{It}/It}
-
- \turnandstop{It}
-
- \sankeyadvance{Niftp}{6em}
-
- \sankeyadvance{Niftp}{1em}
- \node[cost node={\Qty{Niftp}}{\Lab{Niftp}},right label hashed=Niftp];
-
- \sankeynode{name=Tci,quantity=\Qty{Niftp}+\Qty{Octa},
- angle=-90,anchor=right,at={[yshift=-6em]Niftp.right}}
- \sankeyfork{Tci}{\Qty{Octa}/Octa,\Qty{Niftp}/Niftp-e}
- \sankeyoutin{Niftp}{Niftp-e}
-
- \sankeyturn*[minimum radius=1cm]{Octa}{90}
- \node[cost node={\Qty{Octa}}{\Lab{Octa}},right label=1mm of Octa.left];
-
- \sankeyadvance{Tci}{1em}
- \node[cost node={\Qty{Tci}}{\Lab{Tci}},right label hashed=Tci];
-
- \newcommand\hashband[1]{
- \draw[line sep] (#1-old.right) -- (#1-old.left);
- \draw[line sep] (#1.right) -- (#1.left);
- \path[white hash] (#1-old.right) rectangle (#1.left);
- }
-
- \foreach \nodename in {R,Nr,Nr,Ibiiieait,Ibit,Niftp,Tci}{
- \hashband{\nodename}
- }
-
- \end{sankeydiagram}
-\end{tikzpicture}
-\end{filecontents*}
-%
-\lstinputlisting[numbers=left,style=LaTeXsmall]{\samplecodename}
-%
-\begin{figure}
- \centering
- \input{\samplecodename}
- \caption{Very nice example -- Nadieh Bremer's creation}
- (from
- \href{https://www.visualcinnamon.com/portfolio/adyen-report-2019/}{Adyen's
- Shareholder Report})
- \label{fig:nice-example}
-\end{figure}
-\end{document}
-
-%%% Local Variables:
-%%% mode: latex
-%%% TeX-master: t
-%%% End:
diff --git a/graphics/pgf/contrib/sankey/sankey.dtx b/graphics/pgf/contrib/sankey/sankey.dtx
new file mode 100644
index 0000000000..451472c5b2
--- /dev/null
+++ b/graphics/pgf/contrib/sankey/sankey.dtx
@@ -0,0 +1,4678 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2016, 2021 by Paul Gaborit
+% -----------------------------------
+%
+% 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 Paul Gaborit.
+%
+% This work consists of the files sankey.dtx, sankey.ins and the derived
+% files sankey.sty, tikzlibrarydubins.code.tex, sankey-doc-preamble.sty,
+% sankey-example1.tex, sankey-example2.tex, sankey-example3.tex,
+% sankey-example3-variation.tex, sankey-example4.tex,
+% sankey-example-energy.tex
+%
+%
+% \fi
+%
+% \iffalse
+%
+%<*driver>
+\documentclass[a4paper,10pt,draft]{ltxdoc}
+\usepackage{sankey-doc-preamble}
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\begin{document}
+\DocInput{sankey.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+%
+% \CheckSum{1718}
+%
+%
+% \GetFileInfo{\jobname.dtx}
+%
+% \DoNotIndex{\newcommand,\newenvironment}
+% \DoNotIndex{\#,\$,\%,\&,\@,\\,\{,\},\^,\_,\~,\ }
+% \DoNotIndex{\begingroup,\endgroup,\begin,\end}
+% \DoNotIndex{\def,\edef,\gdef,\xdef,\ifx,\else,\string,\relax}
+% \DoNotIndex{\csname,\endcsname,\ifcsdef,\expandafter,\ifnumgreater}
+% \DoNotIndex{\NewDocumentCommand,\NewDocumentEnvironment,\IfBooleanTF}
+% \DoNotIndex{\NeedsTeXFormat,\ProvidesPackage,\RequirePackage,\PackageError,\PackageWarning}
+% \DoNotIndex{\newtoggle,\toggletrue,\togglefalse,\iftoggle,\ifdefempty,\ifundef,\ifdefstrequal}
+% \DoNotIndex{\ifbool,\ifdef,\ifnumequal,\ifpgfmathcond,\colorlet,\fpeval,\inteval,\newbool}
+% \DoNotIndex{\pgfmathsetmacro,\pgfdeclarelayer,\pgfdeclareshape,\pgfkeys,\pgfset,\usetikzlibrary}
+% \DoNotIndex{\the,\pgf@x,\pgf@y,\tikz@scan@one@point,\pgfutil@firstofone}
+% \DoNotIndex{\pgfsetlayers,\inheritsavedanchors,\inheritanchor,\inheritanchorborder,\anchor,\pgf@process,\northeast,\southwest}
+% \DoNotIndex{\pgfmathresult,\pgfinterruptpath,\endpgfinterruptpath,\pgfkeysvalueof,\pgfmathtruncatemacro,\pgfmathparse}
+% \DoNotIndex{\tikzset,\pgfextra,\pgflinewidth,\foreach,\coordinate}
+% \DoNotIndex{\path,\node,\pgfmathprintnumber,\n,\p,\x,\y}
+% \DoNotIndex{\tiny,\ttfamily,\space}
+%
+% \title{The \textsf{sankey} package\\
+% Draw Sankey diagrams via TikZ}
+%
+% \author{Paul Gaborit
+% (\href{mailto:paul.gaborit@gmail.com}{\texttt{paul.gaborit@gmail.com}})}
+% \date{\fileversion{} -- \filedate{}}
+%
+% \GetFileInfo{sankey.sty}
+%
+% \def\manualparts{
+% \begin{quote}
+% This manual contains three parts:
+% \nameref{usermanual} (p.\pageref{usermanual}),
+% \nameref{examples} (p.\pageref{examples})
+% and \nameref{implementation} (p.\pageref{implementation}).
+% \end{quote}
+% }
+%
+% \maketitle
+%
+% \hypersetup{
+% pdftitle=How to use the sankey package to build Sankey diagrams (\fileversion),
+% pdfauthor=Paul Gaborit,
+% }
+%
+%
+%
+% \begin{abstract}
+% The \texttt{sankey} package provides macros and environments to
+% build \emph{Sankey
+% diagrams}\footnote{\url{https://en.wikipedia.org/wiki/Sankey_diagram}},
+% i.e. \emph{flow diagrams} in which the width of the arrows is
+% proportional to the flow rate. The initial idea for the first
+% implementation came out from
+% \href{https://tex.stackexchange.com/q/40159/14500}{this question} on
+% \href{https://tex.stackexchange.com/}{TeX.StackExchange}.
+%
+%
+% \end{abstract}
+%
+% \manualparts
+%
+% \begin{quote}
+% {\footnotesize Note: the \code{sankey.dtx} and \code{sankey.ins}
+% files are attachments of the current PDF document.\par}
+% \end{quote}
+%
+%^^A % ------------------------------------------------------------
+% \part{User manual}
+% \label{usermanual}
+%^^A % ------------------------------------------------------------
+%
+% {
+% \setlength{\parskip}{0pt}
+% \localtableofcontents
+% }
+%
+%^^A % ------------------------------------------------------------
+% \section{Preamble}
+%^^A % ------------------------------------------------------------
+%
+% To use the \code{sankey} package, insert the following line in your preamble:
+%
+% \begin{lstlisting}[style=LaTeXsmall]
+% \usepackage{sankey}
+% \end{lstlisting}
+%
+% {\small Note: the
+% \code{sankey} package requires automatically the
+% \code{xparse}, \code{etoolbox}, \code{xfp} and
+% \code{tikz} packages, and the \code{calc},
+% \code{decorations.markings} and
+% \code{dubins} (cf. \vref{sec:dubins}) TikZ libraries.\par}
+%
+%
+%^^A % ------------------------------------------------------------
+% \section{The \texttt{sankeydiagram} environment}
+%^^A % ------------------------------------------------------------
+%
+% \DescribeEnv{sankeydiagram} %
+% A \code{sankeydiagram} environment nested in a \code{tikzpicture}
+% environment activates the sankey macros:
+%
+% \begin{lstlisting}[style=LaTeXsmall]
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[... options ...]
+% ... sankey macros ...
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{lstlisting}
+%
+%^^A % ------------------------------------------------------------
+% \section{Sankey diagram options}
+%^^A % ------------------------------------------------------------
+%
+% The \code{sankey} package uses \code{pgfkeys} to set options via
+% \emph{key=value} pairs with default path \texttt{/sankey} (and
+% \texttt{/sankey/node parameters} for Sankey node parameters).
+%
+% The options can be defined via the optional argument of the
+% \code{sankeydiagram} environment:
+%
+% \begin{lstlisting}[style=LaTeXsmall]
+% \begin{sankeydiagram}[debug=true]
+% \sankeynode{name=a,quantity=1,angle=0,at={0,0}}
+% \end{sankeydiagram}
+% \end{lstlisting}
+%
+% \DescribeMacro{\sankeyset} %
+% The options can also be modified via the \code{\sankeyset} macro:
+%
+% \begin{lstlisting}[style=LaTeXsmall]
+% \begin{sankeydiagram}
+% \sankeyset{debug=true}
+% \sankeynode{name=a,quantity=1,angle=0,at={0,0}}
+% \end{sankeydiagram}
+% \end{lstlisting}
+%
+% The options can be temporarily modified for a single macro:
+% \begin{lstlisting}[style=LaTeXsmall]
+% \begin{sankeydiagram}
+% \sankeynode[debug=true]{name=a,quantity=1,angle=0,at={0,0}}
+% \end{sankeydiagram}
+% \end{lstlisting}
+%
+% At the begining of each Sankey diagram, all options are initialized
+% with initial values then the \code{every diagram} style is applied.
+%
+% \begin{sankeyoption}{every diagram}{}{}{empty}
+% This style is installed at beginning of each Sankey diagram.
+% \end{sankeyoption}
+%
+% For instance, to use a ratio of 5mm/10 by default (instead of 1cm/10)
+% for all Sankey diagrams, add the following line:
+%
+% \begin{lstlisting}[style=LaTeXsmall]
+% \sankeyset{every diagram/.style={ratio=5mm/10}}
+% \end{lstlisting}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Keys to choose the scale}
+%^^A % ------------------------------------------------------------
+%
+% The scale or ratio of the Sankey diagram is the ratio between the %
+% \code{ratio length} and the \code{ratio quantity}.
+%
+% \begin{sankeyoption}{ratio quantity}{\VAR{number}}{}{10}
+% Quantity (in units of flow) to define ratio. The \VAR{number} can be
+% any math expression.
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}{ratio length}{\VAR{distance}}{}{1cm}
+% Distance (a graphical distance) to define scale.
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}{ratio}{\VAR{distance}/\VAR{number}}{}{1cm/10}
+% Fix the ratio to \VAR{distance}\texttt{/}\VAR{number}.
+% \end{sankeyoption}
+%
+% The initial ratio is 1\,cm/10 units.
+%
+%
+% \textbf{Note:} the \code{sankey} package uses the \code{xfp} package to
+% evaluate all math expressions that use quantities (in units of
+% flow). You can therefore use quantities of a very large or very small
+% order of magnitude. In contrast, for graphic distances, the sankey
+% package uses the \code{pgfmath} package (all calculations must not
+% exceed $\pm 16383.99999$).
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Keys to define rotate offset}
+%^^A % ------------------------------------------------------------
+%
+% \begin{sankeyoption}{rotate}{\VAR{angle}}{}{0}
+%
+% The \code{rotate} key stores an offset angle applied to all Sankey
+% nodes. This is useful when using the \code{rotate} option within a
+% \code{tikzpicture} or a \code{scope}. This TikZ option is only
+% applied to coordinates and not to TikZ nodes (remember that Sankey
+% nodes are TikZ nodes). It's up to the author to keep the
+% \code{rotate} option of the \code{tikzpicture} and that of the
+% \code{sankeydiagram} synchronous.
+%
+% \end{sankeyoption}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Keys to define drawing parameters}
+%^^A % ------------------------------------------------------------
+%
+% \begin{sankeyoption}{minimum radius}{\VAR{distance}}{}{5mm}
+% The minimum radius used by \code{\sankeyturn} and
+% \code{\sankeydubins}.
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}{outin steps}{\VAR{integer}}{}{10}
+% Number of steps used by the \code{\sankeyoutin} macro to simulate flow
+% lanes with constant width.
+% \end{sankeyoption}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Keys to choose drawing styles}
+%^^A % ------------------------------------------------------------
+%
+% \begin{sankeyoption}{fill/.style}{\VAR{style}}{}{{line width=0pt,fill=white}}
+% This TikZ style is used to \emph{fill} all sankey paths.
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}{draw/.style}{\VAR{style}}{}{draw=black,line width=.4pt}
+% This TikZ style is used to \emph{draw} all sankey paths.
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}{start style}{\VAR{style name}}{}{none}
+% There are three predefined \emph{start} styles: \constant{none},
+% \constant{simple}, \constant{arrow}.
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}{end style}{\VAR{style name}}{}{none}
+% There are three predefined \emph{end} styles: \constant{none},
+% \constant{simple}, \constant{arrow}.
+% \end{sankeyoption}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Keys to define new \emph{start} and \emph{end} styles}
+%^^A % ------------------------------------------------------------
+%
+% \begin{sankeyoption}{new start style}{\{\VAR{name}\}\{\VAR{fill
+% path}\}\{\VAR{draw path}\}}{}{}
+% Define the new start style named \VAR{name} with its \VAR{fill
+% path} and its \VAR{draw path}.
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}{new end style}{\{\VAR{name}\}\{\VAR{fill
+% path}\}\{\VAR{draw path}\}}{}{}
+% Define the new end style named \VAR{name} with its \VAR{fill
+% path} and its \VAR{draw path}.
+% \end{sankeyoption}
+%
+% \emph{Fill} and \emph{draw} paths are build in a TikZ scope where the
+% origin is the center of the current Sankey node (its name is accessible
+% via \code{\name}) and the coordinate system is rotated by its
+% orientation.
+%
+%^^A % ------------------------------------------------------------
+% \subsection{The \emph{debug} key}
+%^^A % ------------------------------------------------------------
+%
+% \begin{sankeyoption}{debug}{\VAR{boolean}}{true}{false}
+% To debug a sankey diagram.
+% \end{sankeyoption}
+%
+%^^A % ------------------------------------------------------------
+% \section{Sankey nodes and flows}
+%^^A % ------------------------------------------------------------
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Create Sankey nodes}
+%^^A % ------------------------------------------------------------
+%
+%^^A % ------------------------------------------------------------
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeynode}\OPTARG{\VAR{options}}\ARG{\VAR{node parameters}}
+%
+% \DescribeMacro{\sankeynode} %
+% The \code{\sankeynode} macro defines a Sankey node. The \VAR{options}
+% can be any Sankey diagram keys. To define a Sankey node, you must
+% provide a \emph{name}, a \emph{quantity} and an \emph{angle} as
+% \VAR{node parameters}.
+%
+% \begin{sankeyoption}[/sankey/node parameters]{name}{\VAR{name}}{}{}
+% The \VAR{name} of the new Sankey node (and the associated TikZ node).
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}[/sankey/node parameters]{quantity}{\VAR{quantity}}{}{}
+% The quantity (in flow unit) of the new Sankey node. The \VAR{quantity}
+% can be any math expression.
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}[/sankey/node parameters]{angle}{\VAR{angle}}{}{}
+% The orientation of the flow (0 points to the right) of the new Sankey
+% node.
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}[/sankey/node parameters]{at}{\VAR{at}}{}{0,0}
+% The position of the new Sankey node (a TikZ coordinate \emph{without}
+% round brackets or parentheses).
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}[/sankey/node parameters]{anchor}{\VAR{anchor}}{}{center}
+% Specify the anchor of the Sankey node. Possible values are
+% \constant{center}, \constant{left} or \constant{right}.
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}[/sankey/node parameters]{as}{\VAR{name}}{}{}
+% Copy the \emph{name}, the \emph{quantity}, the \emph{angle} and the
+% \emph{position} of the Sankey node named \VAR{name}.
+% \end{sankeyoption}
+%
+% A Sankey node is also a Tikz node but with only three anchors:
+% \code{left}, \code{center} and \code{right}\footnote{In fact, to be
+% able to use the TikZ \code{fit} library, the %
+% \code{north}, \code{north east} and \code{north west} anchors exist
+% and are equal to \code{left}, %
+% the \code{east} and \code{west} anchors exist and are equal to
+% \code{center} and %
+% the \code{south}, \code{south east} and \code{south west} anchors
+% exist and are equal to \code{right}.}:
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[debug]
+% \sankeynode{name=a,quantity=10}
+% \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+% \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
+%
+% \foreach \nodename/\pos in {a/left,b/below left,c/above}{
+% \foreach \ancname in {left,center,right}{
+% \node[node font=\ttfamily\footnotesize,\pos=1mm of \nodename.\ancname,
+% inner sep=0pt,rotate=\sankeygetnodeorient{\nodename},anchor=east]
+% {\ancname\vphantom{g}};
+% \fill[black] (\nodename.\ancname) circle(1pt);
+% }
+% }
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%^^A % ------------------------------------------------------------
+% \subsubsection{Choose default parameters}
+%^^A % ------------------------------------------------------------
+%
+% \begin{sankeyoption}{every node/.style}{\{\VAR{node parameters}\}}{}{empty}
+% The \VAR{node parameters} defined by the
+% \code{every node} style is installed at the creation of every Sankey node.
+% \end{sankeyoption}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Create starting and ending nodes via macros}
+%^^A % ------------------------------------------------------------
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeynodestart}\OPTARG{\VAR{options}}\ARG{\VAR{node parameters}}
+%
+% \DescribeMacro{\sankeynodestart} %
+% The \code{\sankeynodestart} creates and fills/draws a starting Sankey
+% node:
+%
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}]
+% \sankeynodestart{name=a,quantity=10}
+% \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+% \sankeynodestart{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%^^A % ------------------------------------------------------------
+%
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeynodeend}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% parameters}}
+%
+% \DescribeMacro{\sankeynodeend} %
+% The \code{\sankeynodeend} creates and fills/draws an ending Sankey
+% node:
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[end style=simple,fill/.style={fill=orange!20}]
+% \sankeynodeend{name=a,quantity=10}
+% \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+% \sankeynodeend{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Create starting and ending nodes via options}
+%^^A % ------------------------------------------------------------
+%
+% \begin{miniblock}
+% \begin{sankeyoption}[/sankey/node parameters]{start}{\VAR{boolean}}{true}{false}
+% The \code{\sankeynode} macro acts as the
+% \code{\sankeynodestart} macro if you add the
+% \code{start} option to its options.
+% \end{sankeyoption}
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}]
+% \sankeynode{name=a,quantity=10,start}
+% \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left,start}
+% \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right,start}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+% \begin{miniblock}
+% \begin{sankeyoption}[/sankey/node parameters]{end}{\VAR{boolean}}{true}{false}
+% The \code{\sankeynode} macro acts as the \code{\sankeynodeend}
+% macro if you add the \code{end} option to its options.
+% \end{sankeyoption}
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[end style=simple,fill/.style={fill=orange!20}]
+% \sankeynode{name=a,quantity=10,end}
+% \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left,end}
+% \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right,end}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+%
+% \begin{miniblock}
+% Although rarely necessary, you can mix these two parameters:
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}
+% \sankeyset{
+% end style=arrow,
+% start style=arrow,
+% fill/.style={fill=orange!20}
+% }
+% \sankeynode{name=a,quantity=10,start,end}
+% \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left,start,end}
+% \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right,start,end}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+% \end{miniblock}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Retrieve information from Sankey nodes}
+%^^A % ------------------------------------------------------------
+%
+% \MACRO\code{\sankeygetnodeqty}\ARG{\VAR{node name}}
+%
+% \DescribeMacro{\sankeygetnodeqty} %
+% The expandable command \code{\sankeygetnodeqty} returns the quantity
+% assigned to the Sankey node named \VAR{node name}.
+%
+% \MACRO\code{\sankeyqtytolen}\ARG{\VAR{quantity}}
+%
+% \DescribeMacro{\sankeyqtytolen} %
+% The expandable \code{\sankeyqtytolen} macro converts \VAR{quantity} to
+% graphical length using the current ratio.
+%
+% \MACRO\code{\sankeygetnodeorient}\ARG{\VAR{node name}}
+%
+% \DescribeMacro{\sankeygetnodeorient} %
+% The expandable command \code{\sankeygetnodeorient} returns the angle
+% (orientation) assigned to the Sankey node named \VAR{node name}.
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Move nodes}
+%^^A % ------------------------------------------------------------
+%
+% All the macros of this section move a Sankey node and fill/draw a
+% portion of the Sankey flow. Then the previous position of the Sankey
+% node is accessible via the \code{-old} suffix (i.e. if you move the
+% \code{a} node, its previous position is the \code{a-old} node).
+%
+% The starred version of each of these macros moves in the opposite
+% direction to their non-starred version.
+%
+% Except for the \code{\sankeyturn} macro, a negative value (distance or
+% angle) moves in the opposite direction (the \code{\sankeyturn} macro
+% is an exception: a negative angle turns right while a positive value
+% turns left).
+%
+% {\centering
+% \begin{tikzpicture}
+% \begin{sankeydiagram}
+% \tikzset{com/.style={node font=\ttfamily\scriptsize,
+% fill=bgcode,fill opacity=1,text opacity=1}}
+% \sankeyset{end style=simple,start style=simple}
+% \sankeynode{name=ac,quantity=5}
+% \sankeynode{name=al,quantity=5,at={[yshift=2mm]ac.left},anchor=right}
+% \sankeynode{name=ar,quantity=5,at={[yshift=-2mm]ac.right},anchor=left}
+% \sankeyturnleft{al}{60}
+% \sankeyadvance{ac}{1cm}
+% \sankeyturnright{ar}{60}
+% \sankeyturnleft*{al-old}{60}
+% \sankeyadvance*{ac-old}{1cm}
+% \sankeyturnright*{ar-old}{60}
+% \sankeystart{al-old}
+% \sankeystart{ac-old}
+% \sankeystart{ar-old}
+% \sankeyend{al}
+% \sankeyend{ac}
+% \sankeyend{ar}
+% \draw[red,very thick]
+% (al-old-old.left) -- node[com]{n} (al-old-old.right)
+% (ac-old-old.left) -- node[com]{n} (ac-old-old.right)
+% (ar-old-old.left) -- node[com]{n} (ar-old-old.right);
+% \path
+% (al) ++(2mm,2mm) node[com,anchor=south west,align=left] {
+% \string\sankeyturnleft\{n\}\{angle>0\}\\
+% \string\sankeyturnleftbackward\{n\}\{angle<0\}\\
+% \string\sankeyturnleft*\{n\}\{angle<0\}\\
+% \string\sankeyturnleftbackward*\{n\}\{angle>0\}\\
+% \string\sankeyturn\{n\}\{angle>0\}
+% };
+% \path
+% (al-old) ++(-2mm,2mm) node[com,anchor=south east,align=right] {
+% \string\sankeyturnleftbackward\{n\}\{angle>0\}\\
+% \string\sankeyturnleft\{n\}\{angle<0\}\\
+% \string\sankeyturnleft*\{n\}\{angle>0\}\\
+% \string\sankeyturnleftbackward*\{n\}\{angle<0\}\\
+% \string\sankeyturn*\{n\}\{angle>0\}
+% };
+% \path
+% (ac) ++(2mm,0) node[com,anchor=west,align=left] {
+% \string\sankeyadvance\{n\}\{distance>0\}\\
+% \string\sankeyadvance*\{n\}\{distance<0\}
+% };
+% \path
+% (ac-old) ++(-2mm,0) node[com,anchor=east,align=right] {
+% \string\sankeyadvance\{n\}\{distance<0\}\\
+% \string\sankeyadvance*\{n\}\{distance>0\}
+% };
+% \path
+% (ar) ++(2mm,-2mm) node[com,anchor=north west,align=left] {
+% \string\sankeyturnright\{n\}\{angle>0\}\\
+% \string\sankeyturnrightbackward\{n\}\{angle<0\}\\
+% \string\sankeyturnright*\{n\}\{angle<0\}\\
+% \string\sankeyturnrightbackward*\{n\}\{angle>0\}\\
+% \string\sankeyturn\{n\}\{angle<0\}
+% };
+% \path
+% (ar-old) ++(-2mm,-2mm) node[com,anchor=north east,align=right] {
+% \string\sankeyturnrightbackward\{n\}\{angle>0\}\\
+% \string\sankeyturnright\{n\}\{angle<0\}\\
+% \string\sankeyturnright*\{n\}\{angle>0\}\\
+% \string\sankeyturnrightbackward*\{n\}\{angle<0\}\\
+% \string\sankeyturn*\{n\}\{angle<0\}
+% };
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \par}
+%^^A % ------------------------------------------------------------
+% \subsubsection{Macro to move straight (forward or backward)}
+%^^A % ------------------------------------------------------------
+%
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyadvance}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% name}}\ARG{\VAR{distance}}
+%
+% \DescribeMacro{\sankeyadvance} The \code{\sankeyadvance} moves the
+% sankey node straight ahead and fills/draws this portion of the
+% sankey path. A positive \VAR{distance} moves forward while a
+% negative \VAR{distance} moves backward.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}]
+% \sankeynodestart{name=a,quantity=10}
+% \sankeyadvance{a}{1cm}
+% \sankeynode[debug]{as=a}
+% \sankeynode[debug]{as=a-old}
+% \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+% \sankeyadvance{b}{1cm}
+% \sankeynodestart{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
+% \sankeyadvance{c}{5mm}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyadvance*}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% name}}\ARG{\VAR{distance}}
+%
+% \DescribeMacro{\sankeyadvance*} The \code{\sankeyadvance*} moves
+% the sankey node straight back and fills/draws this portion of the
+% sankey path. A positive \VAR{distance} moves backward while a
+% negative \VAR{distance} moves forward.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[end style=arrow,fill/.style={fill=orange!20}]
+% \sankeynodeend{name=a,quantity=10}
+% \sankeyadvance*{a}{1cm}
+% \sankeynode[debug]{as=a}
+% \sankeynode[debug]{as=a-old}
+% \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+% \sankeyadvance*{b}{1cm}
+% \sankeynodeend{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
+% \sankeyadvance*{c}{5mm}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Macro to turn forward or backward}
+%^^A % ------------------------------------------------------------
+%
+%\begin{miniblock}
+% \MACRO\code{\sankeyturn}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% name}}\ARG{\VAR{angle}}
+%
+% \DescribeMacro{\sankeyturn} The \code{\sankeyturn} macro moves the
+% sankey node by turning to one side or the other and fills/draws
+% this portion of the sankey path. A \emph{positive} \VAR{angle}
+% turns left while a \emph{negative} \VAR{angle} turns right.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}]
+% \sankeynodestart{name=a,quantity=10}
+% \sankeyturn{a}{90}
+% \sankeynode[debug]{as=a}
+% \sankeynode[debug]{as=a-old}
+% \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+% \sankeyturn[minimum radius=1cm]{b}{-45}
+% \sankeynodestart{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
+% \sankeyturn{c}{180}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+%
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyturn*}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% name}}\ARG{\VAR{angle}}
+%
+% \DescribeMacro{\sankeyturn*} The \code{\sankeyturn*} macro moves the
+% sankey node backward by turning right or left and fills/draws this
+% portion of the sankey path. A \emph{positive} \VAR{angle} turns left
+% while a \emph{negative} \VAR{angle} turns right.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[end style=simple,fill/.style={fill=orange!20}]
+% \sankeynodeend{name=a,quantity=10}
+% \sankeyturn*{a}{90}
+% \sankeynode[debug]{as=a}
+% \sankeynode[debug]{as=a-old}
+% \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+% \sankeyturn*[minimum radius=1cm]{b}{-45}
+% \sankeynodeend{name=c,quantity=10,angle=-90,at={3,1},anchor=right}
+% \sankeyturn*{c}{180}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Macros to turn left (forward or backward)}
+%^^A % ------------------------------------------------------------
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyturnleft}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% name}}\ARG{\VAR{angle}}
+%
+% \DescribeMacro{\sankeyturnleft} The
+% \code{\sankeyturnleft} macro moves the sankey node by turning left
+% and fills/draws this portion of the sankey path. A \emph{positive}
+% \VAR{angle} turns forward while a \emph{negative} \VAR{angle} turns backward.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=arrow,end style=arrow]
+% \sankeyset{fill/.style={fill=orange!20}}
+% \sankeynodestart{name=a,quantity=10}
+% \sankeyturnleft{a}{90}
+% \sankeynode[debug]{as=a}
+% \sankeynode[debug]{as=a-old}
+% \sankeyset{fill/.style={fill=lime!20}}
+% \sankeynodeend{name=b,quantity=5,angle=-135,at={1,2},anchor=left}
+% \sankeyturnleft[minimum radius=1cm]{b}{-225}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+%
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyturnleft*}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% name}}\ARG{\VAR{angle}}
+%
+% \DescribeMacro{\sankeyturnleft*} The
+% \code{\sankeyturnleft*} macro moves the sankey node backward
+% by turning left and fills/draws this portion of the sankey path.
+% A \emph{positive} \VAR{angle} turns backward while a
+% \emph{negative} \VAR{angle} turns forward.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=arrow,end style=arrow]
+% \sankeyset{fill/.style={fill=orange!20}}
+% \sankeynodeend{name=a,quantity=10}
+% \sankeyturnleft*{a}{90}
+% \sankeynode[debug]{as=a}
+% \sankeynode[debug]{as=a-old}
+% \sankeyset{fill/.style={fill=lime!20}}
+% \sankeynodestart{name=b,quantity=5,angle=-135,at={1,2},anchor=left}
+% \sankeyturnleft*[minimum radius=.75cm]{b}{-225}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+%
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyturnleftbackward}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% name}}\ARG{\VAR{angle}}
+%
+% \DescribeMacro{\sankeyturnleftbackward} The
+% \code{\sankeyturnleftbackward} macro moves the sankey node backward
+% by turning left and fills/draws this portion of the sankey path.
+% A \emph{positive} \VAR{angle} turns backward while a
+% \emph{negative} \VAR{angle} turns forward.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=arrow,end style=arrow]
+% \sankeyset{fill/.style={fill=orange!20}}
+% \sankeynodeend{name=a,quantity=10}
+% \sankeyturnleftbackward{a}{90}
+% \sankeynode[debug]{as=a}
+% \sankeynode[debug]{as=a-old}
+% \sankeyset{fill/.style={fill=lime!20}}
+% \sankeynodestart{name=b,quantity=5,angle=-135,at={1,2},anchor=left}
+% \sankeyturnleftbackward[minimum radius=.75cm]{b}{-225}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+%
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyturnleftbackward*}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% name}}\ARG{\VAR{angle}}
+%
+% \DescribeMacro{\sankeyturnleftbackward*} The
+% \code{\sankeyturnleftbackward*} macro moves the sankey node by turning left
+% and fills/draws this portion of the sankey path. A \emph{positive}
+% \VAR{angle} turns forward while a \emph{negative} \VAR{angle} turns backward.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=arrow,end style=arrow]
+% \sankeyset{fill/.style={fill=orange!20}}
+% \sankeynodestart{name=a,quantity=10}
+% \sankeyturnleftbackward*{a}{90}
+% \sankeynode[debug]{as=a}
+% \sankeynode[debug]{as=a-old}
+% \sankeyset{fill/.style={fill=lime!20}}
+% \sankeynodeend{name=b,quantity=5,angle=-135,at={1,2},anchor=left}
+% \sankeyturnleftbackward*[minimum radius=1cm]{b}{-225}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+%
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Macros to turn right (forward or backward)}
+%^^A % ------------------------------------------------------------
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyturnright}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% name}}\ARG{\VAR{angle}}
+%
+% \DescribeMacro{\sankeyturnright} The \code{\sankeyturnright} macro
+% moves the sankey node by turning right and fills/draws this portion
+% of the sankey path. A \emph{positive} \VAR{angle} turns forward
+% while a \emph{negative} \VAR{angle} turns backward.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=arrow,end style=arrow]
+% \sankeyset{fill/.style={fill=orange!20}}
+% \sankeynodestart{name=a,quantity=10}
+% \sankeyturnright[fill/.style={fill=orange!20}]{a}{90}
+% \sankeynode[debug]{as=a}
+% \sankeynode[debug]{as=a-old}
+% \sankeyset{fill/.style={fill=lime!20}}
+% \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+% \sankeyturnright[minimum radius=.75cm]{b}{-225}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+%
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyturnright*}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% name}}\ARG{\VAR{angle}}
+%
+% \DescribeMacro{\sankeyturnright*} The \code{\sankeyturnright*} macro
+% moves the sankey node backward by turning right and fills/draws
+% this portion of the sankey path. A \emph{positive} \VAR{angle} turns
+% backward while a \emph{negative} \VAR{angle} turns forward.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=arrow,end style=arrow]
+% \sankeyset{fill/.style={fill=orange!20}}
+% \sankeynodeend{name=a,quantity=10}
+% \sankeyturnright*[fill/.style={fill=orange!20}]{a}{90}
+% \sankeynode[debug]{as=a}
+% \sankeynode[debug]{as=a-old}
+% \sankeyset{fill/.style={fill=lime!20}}
+% \sankeynodestart{name=b,quantity=5,angle=45,at={1,1},anchor=left}
+% \sankeyturnright*[minimum radius=.75cm]{b}{-225}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+%
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyturnrightbackward}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% name}}\ARG{\VAR{angle}}
+%
+% \DescribeMacro{\sankeyturnrightbackward}
+% The \code{\sankeyturnrightbackward} macro
+% moves the sankey node backward by turning right and fills/draws
+% this portion of the sankey path. A \emph{positive} \VAR{angle} turns
+% backward while a \emph{negative} \VAR{angle} turns forward.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=arrow,end style=arrow]
+% \sankeyset{fill/.style={fill=orange!20}}
+% \sankeynodeend{name=a,quantity=10}
+% \sankeyturnrightbackward[fill/.style={fill=orange!20}]{a}{90}
+% \sankeynode[debug]{as=a}
+% \sankeynode[debug]{as=a-old}
+% \sankeyset{fill/.style={fill=lime!20}}
+% \sankeynodestart{name=b,quantity=5,angle=45,at={1,1},anchor=left}
+% \sankeyturnrightbackward[minimum radius=.75cm]{b}{-225}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+%
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyturnrightbackward*}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% name}}\ARG{\VAR{angle}}
+%
+% \DescribeMacro{\sankeyturnrightbackward*} The
+% \code{\sankeyturnrightbackward*} macro moves the sankey
+% node forward by turning right and fills/draws this portion
+% of the sankey path. A \emph{positive} \VAR{angle} turns forward
+% while a \emph{negative} \VAR{angle} turns backward.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=arrow,end style=arrow]
+% \sankeyset{fill/.style={fill=orange!20}}
+% \sankeynodestart{name=a,quantity=10}
+% \sankeyturnrightbackward*[fill/.style={fill=orange!20}]{a}{90}
+% \sankeynode[debug]{as=a}
+% \sankeynode[debug]{as=a-old}
+% \sankeyset{fill/.style={fill=lime!20}}
+% \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+% \sankeyturnrightbackward*[minimum radius=.75cm]{b}{-225}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+%
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Links between nodes}
+%^^A % ------------------------------------------------------------
+%
+% The macros described in this section fill/draw a lane between two
+% Sankey nodes.
+%
+% Note: since Sankey nodes are oriented, linking \code{A} node to
+% \code{B} node does not produce the same result as linking \code{B}
+% node to \code{A} node!
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyoutin}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% A}}\ARG{\VAR{node B}}
+%
+% \DescribeMacro{\sankeyoutin} The \code{\sankeyoutin} macro
+% fills/draws a lane from \VAR{node A} to \VAR{node B} using a
+% Bézier curve with regular steps (10 steps by default) to
+% simulate constant width lane.
+%
+% The constant width and the minimum curvature are \emph{not} guaranteed!
+% \end{miniblock}
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeydubins}\OPTARG{\VAR{options}}\ARG{\VAR{node
+% A}}\ARG{\VAR{node B}}
+%
+% \DescribeMacro{\sankeydubins} %
+% The \code{\sankeydubins} macro fills/draws a lane between
+% \VAR{node A} and \VAR{node B} using a Dubins
+% path\footnote{\url{https://en.wikipedia.org/wiki/Dubins_path}}.
+%
+% The constant width and the minimum curvature are guaranteed.
+% \end{miniblock}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Comparison between \texttt{outin} and \texttt{dubins}
+% paths}
+%^^A % ------------------------------------------------------------
+%
+% The following diagrams compare \texttt{outin} path with
+% 10 steps (orange), \texttt{outin} path with 2 steps (red)
+% and \texttt{dubins} path (lime) in various positions.
+%
+% \begin{miniblock}
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=simple,end style=arrow]
+% \sankeyset{fill/.style={fill=orange!20}}
+% \sankeynodestart{name=a,quantity=5}
+% \sankeynodeend{name=b,at={4,3},quantity=5}
+% \sankeyoutin{a}{b}
+%
+% \sankeyset{fill/.style={fill=red!20}}
+% \sankeynodestart{name=a,at={2,0},quantity=5}
+% \sankeynodeend{name=b,at={6,3},quantity=5}
+% \sankeyoutin[outin steps=2]{a}{b}
+%
+% \sankeyset{fill/.style={fill=lime!40}}
+% \sankeynodestart{name=a,at={4,0},quantity=5}
+% \sankeynodeend{name=b,at={(8,3},quantity=5}
+% \sankeydubins[minimum radius=5mm]{a}{b}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+% \begin{miniblock}
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=simple,end style=arrow]
+% \sankeyset{fill/.style={fill=orange!20}}
+% \sankeynodestart{name=a,quantity=5}
+% \sankeynodeend{name=b,at={2,3},quantity=5}
+% \sankeyoutin{a}{b}
+%
+% \sankeyset{fill/.style={fill=red!20}}
+% \sankeynodestart{name=a,at={2,0},quantity=5}
+% \sankeynodeend{name=b,at={4,3},quantity=5}
+% \sankeyoutin[outin steps=2]{a}{b}
+%
+% \sankeyset{fill/.style={fill=lime!40}}
+% \sankeynodestart{name=a,at={4,0},quantity=5}
+% \sankeynodeend{name=b,at={(6,3},quantity=5}
+% \sankeydubins[minimum radius=5mm]{a}{b}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+% \begin{miniblock}
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=simple,end style=arrow]
+% \sankeyset{fill/.style={fill=orange!20}}
+% \sankeynodestart{name=a,quantity=5}
+% \sankeynodeend{name=b,at={0,3},quantity=5}
+% \sankeyoutin{a}{b}
+%
+% \sankeyset{fill/.style={fill=red!20}}
+% \sankeynodestart{name=a,at={2,0},quantity=5}
+% \sankeynodeend{name=b,at={2,3},quantity=5}
+% \sankeyoutin[outin steps=2]{a}{b}
+%
+% \sankeyset{fill/.style={fill=lime!40}}
+% \sankeynodestart{name=a,at={4,0},quantity=5}
+% \sankeynodeend{name=b,at={(4,3},quantity=5}
+% \sankeydubins[minimum radius=5mm]{a}{b}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Examples of \texttt{dubins} paths}
+%^^A % ------------------------------------------------------------
+%
+% \begin{miniblock}
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}[start style=simple,end style=arrow]
+% \sankeyset{
+% fill/.style={fill=lime!40},
+% draw/.style={draw=green!50!black,line width=2pt},
+% }
+%
+% \sankeynodestart{name=a,quantity=5}
+% \sankeynodeend{name=b,at={0,2},quantity=5}
+% \sankeydubins[minimum radius=2mm]{a}{b}
+%
+% \fill[green!50!black] (2,0) coordinate (c) circle(2pt);
+% \sankeynodestart{name=a,at={[shift={(c)}]90:5mm},quantity=5}
+% \sankeynodeend{name=b,at={[shift={(c)}]150:5mm},angle=60,quantity=5}
+% \sankeydubins[minimum radius=2.5mm]{a}{b}
+%
+% \sankeynodestart{name=a,at={3.5,0},quantity=5}
+% \sankeynodeend{name=b,at={3.5,.75},angle=-180,quantity=5}
+% \sankeydubins[minimum radius=5mm]{a}{b}
+%
+% \sankeynodestart{name=a,at={7,1},quantity=5}
+% \sankeynodeend{name=b,at={7,1.75},quantity=5}
+% \sankeydubins[minimum radius=2.5mm]{a}{b}
+%
+% \sankeynodestart{name=a,at={9,0},quantity=5}
+% \sankeynodeend{name=b,at={9,2},angle=180,quantity=5}
+% \sankeydubins[minimum radius=2.5mm]{a}{b}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Pure filling/drawing macros}
+%^^A % ------------------------------------------------------------
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeystart}\OPTARG{\VAR{options}}\ARG{\VAR{name}}
+%
+% \DescribeMacro{\sankeystart} %
+% The \code{\sankeystart} fills/draws a starting extremity attached to
+% the preexisting Sankey node \VAR{name}:
+%
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}
+% [start style=arrow,fill/.style={fill=cyan!20},draw/.style={draw=blue}]
+% \sankeynode{name=a,quantity=10}
+% \sankeystart{a}
+% \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+% \sankeystart{b}
+% \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
+% \sankeystart{c}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%^^A % ------------------------------------------------------------
+%
+%
+% \begin{miniblock}
+% \MACRO\code{\sankeyend}\OPTARG{\VAR{options}}\ARG{\VAR{name}}
+%
+% \DescribeMacro{\sankeyend} %
+% The \code{\sankeyend} fills/draws an ending extremity attached to
+% the preexisting Sankey node \VAR{name}:
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}
+% [end style=simple,fill/.style={fill=cyan!20},draw/.style={draw=blue}]
+% \sankeynode{name=a,quantity=10}
+% \sankeyend{a}
+% \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+% \sankeyend{b}
+% \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
+% \sankeyend{c}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% %
+% {\centering\input{\samplecodename}\par}
+% \end{miniblock}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Forked node}
+%^^A % ------------------------------------------------------------
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Create and fork a Sankey node}
+%^^A % ------------------------------------------------------------
+%
+% \changes{v3.0}{2021/03/14}{add keys to fork a Sankey node during its
+% creation}
+%
+% \begin{miniblock}
+% When creating a new Sankey node, the \code{forked} and %
+% \code{fork anchor} keys allow to fork the node directly \emph{and} to
+% anchor it on an anchor of a forked subnode.
+%
+% \begin{sankeyoption}[/sankey/node parameters]{forked}{\{\VAR{quantity/name pairs}\}}{}{}
+% The \VAR{quantity/name pairs} is a comma separated list of
+% \emph{quantity/name} pairs (one for each subnode, from left to
+% right). The sum of all quantities \emph{must} be equal to the quantity
+% of the new node to fork.
+% \end{sankeyoption}
+%
+% \begin{sankeyoption}[/sankey/node parameters]{fork anchor}{\VAR{node.anchor}}{}{}
+% An anchor belonging to the new node \emph{or} belonging to a subnode
+% (the anchor name must be prefixed by the name of the
+% node). \emph{Note:} when a \code{fork anchor} key is supplied, the
+% \code{anchor} key is ignored (with a \emph{warning} message).
+% \end{sankeyoption}
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}
+% \sankeyset{
+% start style=arrow,end style=arrow,
+% fill/.style={fill=yellow!10,line width=0pt,draw=yellow!10}
+% }
+%
+% \sankeynode[debug]{
+% name=a,quantity=40,angle=-80,
+% forked={25/b,10/c,5/d},
+% fork anchor=c.right,
+% }
+%
+% \sankeyadvance*{b}{1cm}
+% \sankeyturn*[minimum radius=2cm]{c}{-30}
+% \sankeyturn*[minimum radius=2cm]{c}{30}
+% \sankeyturn*[minimum radius=5mm]{d}{-90}
+% \sankeyadvance{a}{1.5cm}
+% \foreach \nodename in {b,c,d}{ \sankeystart{\nodename} }
+% \sankeyend{a}
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Fork a Sankey node}
+%^^A % ------------------------------------------------------------
+% \begin{miniblock}
+% \MACRO\code{\sankeyfork}\OPTARG{\VAR{options}}\ARG{\VAR{name}}\ARG{\VAR{quantity/name pairs}}
+%
+% \DescribeMacro{\sankeyfork} %
+% The \code{\sankeyfork} macro splits the preexisting Sankey node
+% named \VAR{name} in a list of new Sankey subnodes. The
+% \VAR{quantity/name pairs} is a comma separated list of
+% \emph{quantity/name} pairs, one for each subnode from left to
+% right. The sum of all quantities \emph{must} be equal to the
+% quantity of the node to fork.
+%
+% \begin{VerbatimOut}[gobble=2]{\samplecodename}
+% \begin{tikzpicture}
+% \begin{sankeydiagram}
+% \sankeynode{name=a,quantity=40,angle=-45}
+% \sankeyfork[debug]{a}{25/b,10/c,5/d}
+% \path (a.left) rectangle (a.right); %^^A create a bounding box
+% \end{sankeydiagram}
+% \end{tikzpicture}
+% \end{VerbatimOut}
+% %
+% {\centering\input{\samplecodename}\par}
+% %
+% \lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% \end{miniblock}
+%
+%^^A % ------------------------------------------------------------
+% \section{Miscellaneous}
+%^^A % ------------------------------------------------------------
+%
+%^^A % ------------------------------------------------------------
+% \subsection{The \texttt{debug} layer}
+%^^A % ------------------------------------------------------------
+%
+% The options \code{debug} key uses the \code{sankeydebug} layer to draw
+% above the \code{main} TikZ layer (via \code{\pgfsetlayers}, the
+% \code{sankey} package installs four layers: \code{background},
+% \code{main}, \code{foreground}, \code{sankeydebug}).
+%
+% The four following styles define how to display debug information:
+%
+% \begin{lstlisting}[style=LaTeXsmall]
+% \sankeyset{
+% debug color/.style={/utils/exec={\colorlet{debug color}{#1}}},
+% % debug color used by all debug macros
+% debug color=red!75!black,
+% % debug line between left and right anchors
+% debug line/.style={overlay,draw=debug color,|-|},
+% % debug line between center and label
+% debug normal/.style={overlay,draw=debug color},
+% % debug node label
+% debug label/.style={
+% overlay,
+% draw,
+% font=\ttfamily\tiny,
+% text=debug color,text opacity=1,
+% inner sep=.1em,
+% fill=white,fill opacity=1,
+% rounded corners=.1em,
+% node contents={\name},
+% },
+% }
+% \end{lstlisting}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{The \texttt{dubins} TikZ library}
+% \label{sec:dubins}
+%^^A % ------------------------------------------------------------
+%
+% The \code{sankey} package uses the \code{dubins} TikZ library (the
+% \code{tikzlibrarydubins.code.tex} file) to compute Dubins paths. The
+% documentation for this library does not yet exist.
+%
+%^^A % ------------------------------------------------------------
+% \subsection{How to duplicate a Sankey node}
+%^^A % ------------------------------------------------------------
+%
+% \MACRO\code{\sankeynodealias}\ARG{\VAR{origname}}\ARG{\VAR{clonename}}
+%
+% \DescribeMacro{\sankeynodealias} %
+% The \code{\sankeynodealias} macro clones the Sankey node named
+% \VAR{origname} into the Sankey node named \VAR{clonename}.
+%
+% So, you can clone a Sankey node via two methods:
+%
+% \begin{lstlisting}[style=LaTeXsmall]
+% \sankeynode{name=a,quantity=10}
+% \sankeynode{as=a,name=b}
+% \end{lstlisting}
+%
+% \begin{lstlisting}[style=LaTeXsmall]
+% \sankeynode{name=a,quantity=10}
+% \sankeynodealias{a}{b}
+% \end{lstlisting}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{How to define new start and end styles}
+%^^A % ------------------------------------------------------------
+%
+% Here are the definitions of the \code{arrow} styles:
+%
+% \begin{lstlisting}[style=LaTeXsmall]
+% \sankeyset{
+% %% arrow style
+% new start style={arrow}{
+% (\name.left) -- ++(-10pt,0)
+% -- ([xshift=-10pt/6]\name.center)
+% -- ([xshift=-10pt]\name.right)
+% -- (\name.right) -- cycle
+% }{
+% (\name.left) -- ++(-10pt,0)
+% -- ([xshift=-10pt/6]\name.center)
+% -- ([xshift=-10pt]\name.right)
+% -- (\name.right)
+% },
+% new end style={arrow}{
+% (\name.left) -- ([yshift=1mm]\name.left)
+% -- ([xshift=10pt]\name.center)
+% -- ([yshift=-1mm]\name.right) -- (\name.right) -- cycle
+% }{
+% (\name.left) -- ([yshift=1mm]\name.left)
+% -- ([xshift=10pt]\name.center)
+% -- ([yshift=-1mm]\name.right) -- (\name.right)
+% },
+% }
+% \end{lstlisting}
+%
+%^^A % ------------------------------------------------------------
+% \section{Todo}
+%^^A % ------------------------------------------------------------
+%
+% \begin{itemize}
+% \item Document the \code{dubins} TikZ library.
+% \item Add a tutorial.
+% \item Add examples with cycle(s).
+% \end{itemize}
+%
+% ^^A % ------------------------------------------------------------
+% \clearpage
+%
+% \manualparts
+%
+% \part{Examples}
+% \label{examples}
+%^^A % ------------------------------------------------------------
+% {
+% \setlength{\parskip}{0pt}
+% \localtableofcontents
+% \listoffigures
+% }
+%
+% \tikzset{every picture/.style={}}
+%^^A % ------------------------------------------------------------
+%
+%^^A % ------------------------------------------------------------
+% \clearpage
+% \section{Simple example}
+%^^A % ------------------------------------------------------------
+%
+% \embedfile[mimetype=text/plain]{sankey-example1.tex}
+%
+% \begin{figure}
+% \centering
+% {\MakePercentComment\input{sankey-example1.tex}}
+% \caption{Simple example}
+% \label{fig:simple-example}
+% \end{figure}
+%
+% See figure~\vref{fig:simple-example}. The \code{sankey-example1.tex}
+% file contains the following code and is an attachement of the current
+% PDF document.
+%
+% \lstinputlisting[style=LaTeXsmall]{sankey-example1.tex}
+%
+% \iffalse
+%<*example1>
+\begin{tikzpicture}
+ \begin{sankeydiagram}%[debug]
+ \colorlet{cold}[rgb]{cyan!75!blue!50!white}
+ \colorlet{hot}[rgb]{red!50!orange!75!white}
+ \sankeyset{
+ ratio=90pt/6,minimum radius=15pt,
+ start style=simple,end style=simple,
+ draw/.style={
+ draw=blue!50!cyan,
+ line width=1pt,line cap=round,line join=round,
+ },
+ cold/.style={
+ fill/.style={
+ draw=cold,line width=0pt,fill=cold,
+ },
+ },
+ cold to hot/.style={
+ fill/.style={
+ fill=none,top color=cold,
+ bottom color=hot,middle color=yellow,
+ },
+ },
+ hot/.style={
+ fill/.style={
+ draw=hot,line width=0pt,fill=hot,
+ },
+ },
+ }
+
+ \sankeyset{cold}
+ \sankeynodestart{name=p0,at={100,0},angle=-90,quantity=6}
+ \sankeyadvance{p0}{50pt}
+ \sankeyfork{p0}{3/p1,3/p2}
+ \sankeyturnleft{p1}{90}
+ \sankeyadvance{p1}{20pt}
+ \sankeyadvance{p2}{60pt}
+ \sankeyfork{p2}{2/p3,1/p4}
+ \sankeyturnleft{p3}{90}
+ \sankeyadvance{p3}{50pt}
+ \sankeyfork{p3}{1/p5,1/p6}
+ \sankeyadvance{p5}{70pt}
+ \sankeyfork{p1}{1/p7,1/p8,1/p9}
+ \sankeyadvance{p7}{50pt}
+ \sankeyadvance{p9}{50pt}
+ \sankeyadvance{p4}{40pt}
+ \sankeyturnleft{p4}{90}
+ \sankeyadvance{p4}{65pt}
+ \sankeyadvance{p7}{40pt}
+ \sankeynode{
+ name=p11,at={[shift={(50pt,-15pt)}]p7},quantity=3,
+ forked={1/p7a,1/p9a,1/p5a},
+ }
+ \sankeyoutin{p7}{p7a}
+ \sankeyoutin{p9}{p9a}
+ \sankeyoutin{p5}{p5a}
+ \sankeyadvance{p11}{30pt}
+ \sankeyend{p11}
+ \sankeyturnright{p8}{90}
+ \sankeyturnright{p6}{90}
+ \sankeyturnright{p4}{90}
+ \sankeyset{hot}
+ \sankeyadvance[cold to hot]{p8}{40pt}
+ \sankeynode{
+ name=p10,at={[shift={(-15pt,-60pt)}]p8},angle=-90,quantity=3,
+ forked={1/p8a,1/p6a,1/p4a},
+ }
+ \sankeyoutin[cold to hot]{p4}{p4a}
+ \sankeyoutin[cold to hot]{p6}{p6a}
+ \sankeyoutin{p8}{p8a}
+ \sankeyadvance{p10}{30pt}
+ \sankeyend{p10}
+ \end{sankeydiagram}
+\end{tikzpicture}
+%</example1>
+% \fi
+%
+%^^A % ------------------------------------------------------------
+% \clearpage
+% \section{Energy diagram}
+%^^A % ------------------------------------------------------------
+%
+% \embedfile[mimetype=text/plain]{sankey-example-energy.tex}
+%
+% \begin{figure}
+% \centering
+% {\MakePercentComment\input{sankey-example-energy.tex}}
+% \caption{Energy diagram}
+% \label{fig:very-simple-example}
+% \end{figure}
+%
+% This example comes from
+% \href{https://ibphysicsblog.wordpress.com/2015/10/23/sankey-diagrams/}{IB
+% Pysics Blog} by Kyu Won Shim.
+%
+% See figure~\vref{fig:very-simple-example}. The \code{sankey-example-energy.tex}
+% file contains the following code and is an attachement of the current
+% PDF document.
+%
+% \lstinputlisting[style=LaTeXsmall]{sankey-example-energy.tex}
+%
+% \iffalse
+%<*example-energy>
+\begin{tikzpicture}
+ % font choice
+ \renewcommand\rmdefault{txr}\rmfamily\footnotesize
+ \sisetup{
+ round-mode=places,
+ round-precision=1,
+ add-decimal-zero,
+ round-integer-to-decimal,
+ }
+ \begin{sankeydiagram}
+ \colorlet{energy}{blue!30!cyan!80!black}
+ \colorlet{lost energy}{red!50!orange!90!black}
+ \sankeyset{
+ ratio=13em/100,
+ minimum radius=1em,
+ start style=simple,end style=simple,
+ draw/.style={draw=none,line width=0},
+ energy/.style={
+ fill/.style={
+ draw=energy,
+ line width=0,
+ fill=energy,
+ }
+ },
+ lost energy/.style={
+ fill/.style={
+ draw=lost energy,
+ line width=0,
+ fill=lost energy,
+ }
+ }
+ }
+
+ \newcommand\abovelabel[2]{ % valname, label
+ \node[anchor=south east,align=center,inner xsep=0] at (#1.left) {#2};
+ }
+
+ \newcommand\energylabel[1]{ % valname
+ \node[anchor=north east,text=energy,inner xsep=0] at (#1.right)
+ {\num{\sankeygetnodeqty{#1}}};
+ }
+
+ \newcommand\lostenergylabel[2]{ % valname, label
+ \node[anchor=north,text=lost energy] at ([yshift=-2.5mm]#1.center)
+ (value)
+ {\num{\sankeygetnodeqty{#1}}};
+ \node[anchor=north,inner sep=0,align=center] at (value.south) {#2};
+ }
+
+ \newcommand\lostenergylabelbottom[2]{ % valname, label
+ \draw[draw=lost energy,dashed,thick]
+ ([yshift=-3mm]#1.center) coordinate (#1) -- ([yshift=-3mm]#1.center);
+ \lostenergylabel{#1}{#2}
+ }
+
+ \sankeynode{name=Co,quantity=100.0}
+ \path (Co.right) ++(0,-7mm) coordinate (c);
+
+ \newcommand\turnandstop[2]{ % valname, label
+ \begingroup
+ \sankeyset{lost energy}
+ \sankeyturnright{#1}{90}
+ \sankeynode{as=#1,name=#1-stop,at={#1 |- c}}
+ \sankeyoutin{#1}{#1-stop}
+ \sankeynode{as=#1-stop,name=#1}
+ \sankeyend{#1}
+ \lostenergylabel{#1}{#2}
+ \endgroup
+ }
+
+ \newcommand\turnandstopbottom[2]{ % valname, label
+ \begingroup
+ \sankeyset{lost energy}
+ \sankeyturnright{#1}{90}
+ \sankeynode{as=#1,name=#1-stop,at={#1 |- c}}
+ \sankeyoutin{#1}{#1-stop}
+ \sankeynode{as=#1-stop,name=#1}
+ \sankeyend{#1}
+ \lostenergylabelbottom{#1}{#2}
+ \endgroup
+ }
+
+ \def\hshift{6.25em}
+
+ \sankeyadvance[energy]{Co}{1.2*\hshift}
+ \abovelabel{Co}{\textbf{Coal}\\(Primary energy)}
+ \energylabel{Co}
+ \sankeyfork{Co}{35/El1,65/Pg}
+ \turnandstop{Pg}{Power generation}
+
+ \sankeyadvance[energy]{El1}{1.8*\hshift}
+ \abovelabel{El1}{\textbf{Electricity}\\(Secondary energy)}
+ \energylabel{El1}
+ \sankeyfork{El1}{33.5/El2,1.5/Tr}
+ \turnandstopbottom{Tr}{Transmission}
+
+ \sankeyadvance[energy]{El2}{.65*\hshift}
+ \energylabel{El2}
+ \sankeyfork{El2}{31.5/El3,2.0/Di}
+ \turnandstop{Di}{Distribution}
+
+ \sankeyadvance[energy]{El3}{.65*\hshift}
+ \energylabel{El3}
+ \sankeyfork{El3}{31.0/El4,0.5/Wi}
+ \turnandstopbottom{Wi}{Wiring}
+
+ \sankeyadvance[energy]{El4}{.65*\hshift}
+ \abovelabel{El4}{\textbf{Electricity}\\(Final energy)}
+ \energylabel{El4}
+ \sankeyfork{El4}{3.0/Lr1,28.0/Lb}
+ \turnandstop{Lb}{Lightbulb}
+
+ \sankeyadvance[energy]{Lr1}{1.1*\hshift}
+ \abovelabel{Lr1}{\textbf{Light radiation}\\(Useful energy)}
+ \energylabel{Lr1}
+ \sankeyfork{Lr1}{2.0/Lr2,1.0/Ls}
+ \turnandstopbottom{Ls}{Lampshade}
+
+ \sankeyadvance[energy]{Lr2}{.6*\hshift}
+ \energylabel{Lr2}
+ \sankeyfork{Lr2}{1.0/Il,1.0/Id}
+ \turnandstop{Id}{Idle}
+
+ \sankeyadvance[energy]{Il}{.6*\hshift}
+ \abovelabel{Il}{\textbf{Illumination}\\(Energy services)}
+ \energylabel{Il}
+ \sankeyend[energy]{Il}
+ \end{sankeydiagram}
+\end{tikzpicture}
+%</example-energy>
+% \fi
+%^^A % ------------------------------------------------------------
+% \clearpage
+% \section{Example from question on TeX.se}
+%^^A % ------------------------------------------------------------
+%
+% \changes{v3.0}{2021/03/14}{fix bad names in second example}
+%
+% \embedfile[mimetype=text/plain]{sankey-example2.tex}
+%
+% \begin{figure}
+% \centering
+% {\MakePercentComment\input{sankey-example2}}
+% \caption{Example from TeX.se question}
+% \label{fig:texse-example}
+% \end{figure}
+%
+% This example came from
+% \href{https://tex.stackexchange.com/q/40159/14500}{this question} on
+% \href{https://tex.stackexchange.com/}{TeX.StackExchange}.
+%
+% See figure~\vref{fig:texse-example}. The \code{sankey-example2.tex}
+% file contains the following code and is an attachement of the current
+% PDF document.
+%
+% \lstinputlisting[style=LaTeXsmall]{sankey-example2}
+%
+% \iffalse
+%<*example2>
+\begin{tikzpicture}
+ \renewcommand*\sfdefault{txss}
+
+ \begin{sankeydiagram}%[debug]
+ \sankeyset{
+ ratio=4cm/524.3,
+ minimum radius=3mm,
+ start style=arrow,
+ end style=arrow,
+ fill/.style={
+ line width=0pt,
+ fill=cyan!50!blue!50!black,
+ draw=cyan!50!blue!50!black,
+ },
+ draw/.style={draw=none},
+ every node/.style={angle=-90},
+ }
+
+ \sankeynodestart{name=B,at={-.5,0},quantity=7.2}
+ \coordinate[below=1mm of B.center] (B label);
+ \sankeyadvance{B}{5mm}
+ \sankeynodestart{name=GI,at={1,0},quantity=137.3}
+ \coordinate[below=1mm of GI.center] (GI label);
+ \sankeyadvance{GI}{5mm}
+ \sankeynodestart{name=I,at={4,0},quantity=397.8}
+ \coordinate[below=1mm of I.center] (I label);
+ \sankeynode{
+ name=EI,at={2.86,-3},quantity=542.3,
+ forked={397.8/Ia,137.3/GIa,7.2/Ba}
+ }
+ \sankeydubins[minimum radius=1.2cm]{I}{Ia}
+ \sankeyoutin{GI}{GIa}
+ \sankeyoutin{B}{Ba}
+ \sankeyadvance{EI}{5mm}
+ \coordinate (EI label) at (EI);
+ \sankeyadvance{EI}{5mm}
+ \sankeyfork{EI}{63.1/EB,479.2/P}
+
+ \sankeyturnleft{EB}{90}
+ \sankeyadvance{EB}{4cm}
+ \coordinate (EB label) at ($(EB)!.5!(EB-old)$);
+ \sankeyend{EB}
+
+ \sankeyadvance{P}{10mm}
+ \coordinate (P label) at (P);
+ \sankeyadvance{P}{5mm}
+
+ \sankeyfork{P}{33.5/NV,445.7/P-NV}
+
+ {
+ \colorlet{NV color}{cyan!80!lime!50!gray}
+ \sankeyset{fill/.append style={fill=NV color,draw=NV color}}
+ \sankeyturnleft{NV}{90}
+ \sankeynode{as=NV,name=NV2,at=NV -| EB}
+ \sankeyoutin{NV}{NV2}
+ \coordinate (NV label) at (NV -| EB label);
+ \sankeyend{NV2}
+ }
+
+ \sankeyadvance{P-NV}{10mm}
+ \sankeyfork{P-NV}{118.1/U,327.6/P-NV-U}
+
+ {
+ \sankeyset{
+ fill/.style={fill=orange!70!gray!50,draw=orange!70!gray!50}
+ }
+ \sankeyturnleft{U}{90}
+ \sankeynode{as=U,name=U2,at=U -| EB}
+ \sankeyoutin{U}{U2}
+ \coordinate (U label) at (U -| EB label);
+ \sankeyend{U2}
+ }
+
+ \sankeyadvance{P-NV-U}{10mm}
+ \sankeyfork{P-NV-U}{327.2/P-NV-U-SD,0.4/SD}
+
+ {
+ \sankeyturnright{SD}{90}
+ \sankeyadvance{SD}{15mm}
+ \coordinate (SD label) at (SD);
+ \sankeyadvance{SD}{15mm}
+ \sankeyend{SD}
+ }
+
+ \sankeyadvance{P-NV-U-SD}{8mm}
+ \sankeyfork{P-NV-U-SD}{18.8/VE,308.4/E}
+
+ {
+ \sankeyset{fill/.append style={orange!70!gray!30}}
+ \sankeyturnleft{VE}{90}
+ \sankeynode{as=VE,name=VE2,at=VE -| EB}
+ \sankeyoutin{VE}{VE2}
+ \coordinate (VE label) at (VE -| EB label);
+ \sankeyend{VE2}
+ }
+
+ \sankeyadvance{E}{8mm}
+ \coordinate (E label) at (E);
+ \sankeyadvance{E}{20mm}
+ \sankeyfork{E}{135.1/H+GHD,87.2/V,86.1/In}
+
+ \sankeyturnright{In}{90}
+ \sankeyadvance{In}{10mm}
+ \sankeyturnleft{In}{90}
+ \sankeyadvance{In}{5mm}
+ \coordinate (In label) at (In);
+ \sankeyadvance{In}{10mm}
+ \sankeyend{In}
+
+ \sankeynode{as=V,name=V2,at=V|-In label}
+ \sankeyoutin{V}{V2}
+ \coordinate (V label) at (V2);
+ \sankeyadvance{V2}{10mm}
+ \sankeyend{V2}
+
+ \sankeyturnleft{H+GHD}{90}
+ \sankeyadvance{H+GHD}{5mm}
+ \sankeyfork{H+GHD}{47.0/GHD,88.1/H}
+
+ \sankeyturnright{H}{90}
+ \sankeynode{as=H,name=H2,at=H|-In label}
+ \sankeyoutin{H}{H2}
+ \coordinate (H label) at (H2);
+ \sankeyadvance{H2}{10mm}
+ \sankeyend{H2}
+
+ \sankeyadvance{GHD}{30mm}
+ \sankeyturnright{GHD}{90}
+ \sankeynode{as=GHD,name=GHD2,at=GHD|-In label}
+ \sankeyoutin{GHD}{GHD2}
+ \coordinate (GHD label) at (GHD2);
+ \sankeyadvance{GHD2}{10mm}
+ \sankeyend{GHD2}
+ \end{sankeydiagram}
+
+ % labels
+ \tikzset{
+ label/.style={
+ fill=white,fill opacity=.8,text opacity=1,
+ inner sep=1mm,
+ text=cyan!50!blue!50!black,
+ inner xsep=2mm,
+ font=\sffamily\bfseries\footnotesize,
+ align=center,
+ },
+ }
+ \node[label,anchor=north] (B label) at (B label) {7.2};
+ \node[label,left=1mm of B label] {Bestands-\\entnahme};
+ \node[label,anchor=north] at (GI label) {137.3};
+ \node[label,above=5mm of GI label] {Gewinnung\\im Inland};
+ \node[label,anchor=north] at (I label) {397.8};
+ \node[label,above=5mm of I label] {Import};
+
+ \node[label] at (EI label) {542.3\\Energieaufkommen im Inland};
+
+ \node[label,anchor=center] (EB label) at (EB label) {63.1};
+ \node[label,above=1mm of EB label] {Export und\\Bunkerung};
+
+ \node[label] at (P label) {479.2\\Primärenergieverbrauch};
+
+ \node[label,anchor=center] (NV label) at (NV label) {33.5};
+ \node[label,above=0mm of NV label] {Nichtenergetischer Verbrauch};
+
+ \node[label,anchor=center] (U label) at (U label) {118.1};
+ \node[label,below=3mm of U label] {Umwandlungsverluste};
+
+ \node[label,anchor=center] (SD label) at (SD label) {0.4};
+ \node[label,above=0mm of SD label] {Statistische\\Differenzen};
+
+ \node[label,anchor=center] (VE label) at (VE label) {18.8};
+ \node[label,below=0mm of VE label] {Verbrauch in den\\Energiesktoren};
+
+ \node[label,anchor=north] (E label) at (E label)
+ {308.4\\Endenergieverbrauch};
+
+ \node[label,anchor=north] (In label) at (In label) {86.1};
+ \node[label,anchor=north,below=1cm of In label] {Industrie};
+
+ \node[label,anchor=north] (V label) at (V label) {87.2};
+ \node[label,anchor=north,below=1cm of V label] {Verkehr};
+
+ \node[label,anchor=north] (H label) at (H label) {88.1};
+ \node[label,anchor=north,below=1cm of H label] {Haushalte};
+
+ \node[label,anchor=north] (GHD label) at (GHD label) {47.0};
+ \node[label,anchor=north,below=1cm of GHD label]
+ {Gewerbe, Handel\\Diensleistungen};
+\end{tikzpicture}
+%</example2>
+% \fi
+%
+%^^A % ------------------------------------------------------------
+% \clearpage
+% \section{Reproduction of an example from Google Charts documentation}
+%^^A % ------------------------------------------------------------
+%
+% \changes{v3.0}{2021/03/14}{add the reproduction of an example from
+% Google Charts documentation}
+%
+% \embedfile[mimetype=text/plain]{sankey-example3.tex}
+%
+% This example is a reproduction of an example of Google
+% Charts Documentation\footnote{\url{https://developers.google.com/chart/interactive/docs/gallery/sankey}}.
+%
+% See figure \vref{fig:google-example}. The \code{sankey-example3.tex}
+% file contains the following code and is an attachement of the current
+% PDF document.
+%
+% \begin{figure}
+% \centering
+% {\MakePercentComment\input{sankey-example3}}
+% \caption{Reproduction of an example from Google Charts
+% documentation}
+% \label{fig:google-example}
+% \end{figure}
+%
+% \lstinputlisting[style=LaTeXsmall]{sankey-example3}
+%
+% \iffalse
+%<*example3>
+\begin{tikzpicture}
+ \begin{sankeydiagram}%[debug]
+ \sffamily
+ \sankeyset{
+ ratio=1cm/10,
+ outin steps=2,
+ draw/.style={draw=none,line width=0pt},
+ color/.style={fill/.style={fill=#1,fill opacity=.75}},
+ shade/.style 2 args={fill/.style={left color=#1,
+ right color=#2,fill opacity=.5}},
+ % colors
+ @define HTML color/.code args={#1/#2}{\definecolor{#1}{HTML}{#2}},
+ @define HTML color/.list={
+ cyan/a6cee3,lime/b2df8a,red/fb9a99,orange/fdbf6f,
+ violet/cab2d6,yellow/ffff99,blue/1f78b4,green/33a02c
+ },
+ % colors of countries
+ @let country color/.code args={#1/#2}{\colorlet{#1}[rgb]{#2}},
+ @let country color/.list={
+ CA/red,US/orange,MX/orange,BR/cyan,FR/lime,GB/red,
+ SP/lime,PT/cyan,ML/blue,SN/violet,MA/yellow,
+ AO/violet,ZA/yellow,IN/green,JP/green,CN/blue
+ },
+ }
+ \def\vdist{5mm}
+ \def\hwidth{.5em}
+ \def\hdist{4.1cm}
+
+ \sankeynode{name=CA,quantity=7}
+ \sankeynode{name=US,quantity=8,at={[yshift=\vdist]CA.left},anchor=right}
+ \sankeynode{name=MX,quantity=8,at={[yshift=\vdist]US.left},anchor=right}
+ \sankeynode{name=BR,quantity=8,at={[yshift=\vdist]MX.left},anchor=right}
+
+ \foreach \country in {CA,US,MX,BR}{
+ \sankeyadvance[color=\country]{\country}{\hwidth}
+ }
+
+ \sankeyfork{CA}{1/CA-to-PT,1/CA-to-GB,5/CA-to-FR}
+ \sankeyfork{US}{1/US-to-PT,1/US-to-SP,5/US-to-GB,1/US-to-FR}
+ \sankeyfork{MX}{1/MX-to-PT,5/MX-to-SP,1/MX-to-GB,1/MX-to-FR}
+ \sankeyfork{BR}{5/BR-to-PT,1/BR-to-SP,1/BR-to-GB,1/BR-to-FR}
+
+ \sankeynode{name=FR,quantity=11,
+ at={[xshift=\hdist]CA.right},anchor=right}
+ \sankeynode{name=GB,quantity=11,
+ at={[yshift=\vdist]FR.left},anchor=right}
+ \sankeynode{name=SP,quantity=7,
+ at={[yshift=\vdist]GB.left},anchor=right}
+ \sankeynode{name=PT,quantity=8,
+ at={[yshift=\vdist]SP.left},anchor=right}
+
+ \sankeyfork{FR}
+ {1/FR-from-BR,1/FR-from-MX,1/FR-from-US,5/FR-from-CA,3/FR-from-00}
+ \sankeyfork{GB}
+ {1/GB-from-BR,1/GB-from-MX,5/GB-from-US,1/GB-from-CA,3/GB-from-00}
+ \sankeyfork{SP}{1/SP-from-BR,5/SP-from-MX,1/SP-from-US}
+ \sankeyfork{PT}{5/PT-from-BR,1/PT-from-MX,1/PT-from-US,1/PT-from-CA}
+
+ \foreach \country in {FR,GB,SP,PT}{
+ \sankeyadvance[color=\country]{\country}{\hwidth}
+ }
+
+ \sankeyfork{FR}{1/FR-to-ZA,1/FR-to-AO,3/FR-to-MA,3/FR-to-SN,3/FR-to-ML}
+ \sankeyfork{GB}{7/GB-to-ZA,1/GB-to-AO,2/GB-to-MA,1/GB-to-SN}
+ \sankeyfork{SP}{1/SP-to-ZA,3/SP-to-MA,1/SP-to-SN,2/SP-to-00}
+ \sankeyfork{PT}{3/PT-to-ZA,2/PT-to-AO,1/PT-to-MA,1/PT-to-SN,1/PT-to-00}
+
+ \sankeynode{name=ML,quantity=9,
+ at={[xshift=\hdist]FR.right},anchor=right}
+ \sankeynode{name=SN,quantity=9,
+ at={[yshift=\vdist]ML.left},anchor=right}
+ \sankeynode{name=MA,quantity=9,
+ at={[yshift=\vdist]SN.left},anchor=right}
+ \sankeynode{name=AO,quantity=9,
+ at={[yshift=\vdist]MA.left},anchor=right}
+ \sankeynode{name=ZA,quantity=12,
+ at={[yshift=\vdist]AO.left},anchor=right}
+
+ \sankeyfork{ML}{3/ML-from-FR,6/Mail-from-00}
+ \sankeyfork{SN}
+ {1/SN-from-PT,1/SN-from-SP,1/SN-from-GB,3/SN-from-FR,3/SN-from-00}
+ \sankeyfork{MA}{1/MA-from-PT,3/MA-from-SP,2/MA-from-GB,3/MA-from-FR}
+ \sankeyfork{AO}{2/AO-from-PT,1/AO-from-GB,1/AO-from-FR,5/AO-from-00}
+ \sankeyfork{ZA}{3/ZA-from-PT,1/ZA-from-SP,7/ZA-from-GB,1/ZA-from-FR}
+
+ \foreach \country in {ML,SN,MA,AO,ZA}{
+ \sankeyadvance[color=\country]{\country}{\hwidth}
+ }
+
+ \sankeyfork{ML}{5/ML-to-CN,3/ML-to-JP,1/ML-to-IN}
+ \sankeyfork{SN}{5/SN-to-CN,3/SN-to-JP,1/SN-to-IN}
+ \sankeyfork{MA}{5/MA-to-CN,3/MA-to-JP,1/MA-to-IN}
+ \sankeyfork{AO}{5/AO-to-CN,3/AO-to-JP,1/AO-to-IN}
+ \sankeyfork{ZA}{5/ZA-to-CN,3/ZA-to-JP,1/ZA-to-IN,3/ZA-to-00}
+
+ \sankeynode{name=IN,quantity=5,
+ at={[xshift=\hdist]ML.right},anchor=right}
+ \sankeynode{name=JP,quantity=15,
+ at={[yshift=\vdist]IN.left},anchor=right}
+ \sankeynode{name=CN,quantity=25,
+ at={[yshift=\vdist]JP.left},anchor=right}
+
+ \sankeyfork{IN}
+ {1/IN-from-ZA,1/IN-from-AO,1/IN-from-MA,1/IN-from-SN,1/IN-from-ML}
+ \sankeyfork{JP}
+ {3/JP-from-ZA,3/JP-from-AO,3/JP-from-MA,3/JP-from-SN,3/JP-from-ML}
+ \sankeyfork{CN}
+ {5/CN-from-ZA,5/CN-from-AO,5/CN-from-MA,5/CN-from-SN,5/CN-from-ML}
+
+ \foreach \country in {IN,JP,CN}{
+ \sankeyadvance[color=\country]{\country}{\hwidth}
+ }
+
+ \foreach \startcountry/\countries in {
+ CA/{PT,GB,FR}, US/{PT,SP,GB,FR}, MX/{PT,SP,GB,FR},
+ BR/{PT,SP,GB,FR}, FR/{ML,SN,MA,AO,ZA}, GB/{SN,MA,AO,ZA},
+ SP/{SN,MA,ZA}, PT/{SN,MA,AO,ZA}, ML/{IN,JP,CN},
+ SN/{IN,JP,CN}, MA/{IN,JP,CN}, AO/{IN,JP,CN},
+ ZA/{IN,JP,CN}}
+ {
+ \foreach \endcountry in \countries {
+ \sankeyoutin[shade={\startcountry}{\endcountry}]
+ {\startcountry-to-\endcountry}{\endcountry-from-\startcountry}
+ }
+ }
+
+ \foreach \country/\countryname in {CA/Canada, US/USA, MX/Mexico,
+ BR/Brazil, FR/France, GB/England, SP/Spain, PT/Portugal}
+ {
+ \node[anchor=west,inner sep=.1em,font=\small]
+ at (\country) {\countryname\vphantom{Ag}};
+ }
+
+ \foreach \country/\countryname in {
+ ML/Mali, SN/Senegal, MA/Morocco, AO/Angola,
+ ZA/South Africa, IN/India, JP/Japan, CN/China}
+ {
+ \node[anchor=east,inner sep=.1em,font=\small]
+ at (\country-old) {\countryname\vphantom{Ag}};
+ }
+ \end{sankeydiagram}
+\end{tikzpicture}
+%</example3>
+% \fi
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Variation}
+%^^A % ------------------------------------------------------------
+%
+% Here is a variation of the previous example using the \code{rotate}
+% key.
+%
+% See figure \vref{fig:google-example-variation}. The
+% \code{sankey-example3-variation.tex} file contains the following code
+% and is an attachement of the current PDF document.
+%
+% \begin{figure}
+% \centering
+% {\MakePercentComment\input{sankey-example3-variation}}
+% \caption{Reproduction of an example from Google Charts documentation
+% -- variation using the \protect\texttt{rotate} key.}
+% \label{fig:google-example-variation}
+% \end{figure}
+%
+% \lstinputlisting[style=LaTeXsmall]{sankey-example3-variation}
+%
+% \iffalse
+%<*example3-variation>
+\begin{tikzpicture}[rotate=-90]
+ \begin{sankeydiagram}[rotate=-90]
+ \sffamily
+ \sankeyset{
+ ratio=1.7cm/10,
+ outin steps=2,
+ start style=arrow,
+ end style=simple,
+ draw/.style={draw=white,line width=.4pt},
+ color/.style={fill/.style={fill=#1,fill opacity=.75}},
+ shade/.style 2 args={fill/.style={
+ fill=none,line width=0,
+ top color=#1,bottom color=#2,
+ middle color=#1!50!#2!50!white,
+ fill opacity=.75}},
+ % colors
+ @define HTML color/.code args={#1/#2}{\definecolor{#1}{HTML}{#2}},
+ @define HTML color/.list={
+ cyan/a6cee3,lime/b2df8a,red/fb9a99,orange/fdbf6f,
+ violet/cab2d6,yellow/ffff99,blue/1f78b4,green/33a02c
+ },
+ % colors of countries
+ @let country color/.code args={#1/#2}{\colorlet{#1}[rgb]{#2}},
+ @let country color/.list={
+ CA/red,US/orange,MX/lime,BR/violet,FR/yellow,GB/blue,
+ SP/green,PT/cyan,ML/cyan,SN/red,MA/orange,
+ AO/violet,ZA/lime,IN/blue,JP/yellow,CN/green
+ },
+ }
+ \def\vdist{5mm}
+ \def\hwidth{1em}
+ \def\hdist{6cm}
+
+ \sankeynode{name=CA,quantity=7}
+ \sankeynode{name=US,quantity=8,at={[yshift=\vdist]CA.left},anchor=right}
+ \sankeynode{name=MX,quantity=8,at={[yshift=\vdist]US.left},anchor=right}
+ \sankeynode{name=BR,quantity=8,at={[yshift=\vdist]MX.left},anchor=right}
+
+ \foreach \country in {CA,US,MX,BR}{
+ \sankeystart[color=\country]{\country}
+ \sankeyadvance[color=\country]{\country}{\hwidth}
+ }
+
+ \sankeyfork{CA}{1/CA-to-PT,1/CA-to-GB,5/CA-to-FR}
+ \sankeyfork{US}{1/US-to-PT,1/US-to-SP,5/US-to-GB,1/US-to-FR}
+ \sankeyfork{MX}{1/MX-to-PT,5/MX-to-SP,1/MX-to-GB,1/MX-to-FR}
+ \sankeyfork{BR}{5/BR-to-PT,1/BR-to-SP,1/BR-to-GB,1/BR-to-FR}
+
+ \sankeynode{name=FR,quantity=11,
+ at={[xshift=\hdist]CA.right},anchor=right}
+ \sankeynode{name=GB,quantity=11,
+ at={[yshift=\vdist]FR.left},anchor=right}
+ \sankeynode{name=SP,quantity=7,
+ at={[yshift=\vdist]GB.left},anchor=right}
+ \sankeynode{name=PT,quantity=8,
+ at={[yshift=\vdist]SP.left},anchor=right}
+
+ \sankeyfork{FR}
+ {1/FR-from-BR,1/FR-from-MX,1/FR-from-US,5/FR-from-CA,3/FR-from-00}
+ \sankeyfork{GB}
+ {1/GB-from-BR,1/GB-from-MX,5/GB-from-US,1/GB-from-CA,3/GB-from-00}
+ \sankeyfork{SP}{1/SP-from-BR,5/SP-from-MX,1/SP-from-US}
+ \sankeyfork{PT}{5/PT-from-BR,1/PT-from-MX,1/PT-from-US,1/PT-from-CA}
+
+ \foreach \country in {FR,GB,SP,PT}{
+ \sankeyadvance[color=\country]{\country}{\hwidth}
+ }
+
+ \sankeyfork{FR}{1/FR-to-ZA,1/FR-to-AO,3/FR-to-MA,3/FR-to-SN,3/FR-to-ML}
+ \sankeyfork{GB}{7/GB-to-ZA,1/GB-to-AO,2/GB-to-MA,1/GB-to-SN}
+ \sankeyfork{SP}{1/SP-to-ZA,3/SP-to-MA,1/SP-to-SN,2/SP-to-00}
+ \sankeyfork{PT}{3/PT-to-ZA,2/PT-to-AO,1/PT-to-MA,1/PT-to-SN,1/PT-to-00}
+
+ \sankeynode{name=ML,quantity=9,
+ at={[xshift=\hdist]FR.right},anchor=right}
+ \sankeynode{name=SN,quantity=9,
+ at={[yshift=\vdist]ML.left},anchor=right}
+ \sankeynode{name=MA,quantity=9,
+ at={[yshift=\vdist]SN.left},anchor=right}
+ \sankeynode{name=AO,quantity=9,
+ at={[yshift=\vdist]MA.left},anchor=right}
+ \sankeynode{name=ZA,quantity=12,
+ at={[yshift=\vdist]AO.left},anchor=right}
+
+ \sankeyfork{ML}{3/ML-from-FR,6/Mail-from-00}
+ \sankeyfork{SN}
+ {1/SN-from-PT,1/SN-from-SP,1/SN-from-GB,3/SN-from-FR,3/SN-from-00}
+ \sankeyfork{MA}{1/MA-from-PT,3/MA-from-SP,2/MA-from-GB,3/MA-from-FR}
+ \sankeyfork{AO}{2/AO-from-PT,1/AO-from-GB,1/AO-from-FR,5/AO-from-00}
+ \sankeyfork{ZA}{3/ZA-from-PT,1/ZA-from-SP,7/ZA-from-GB,1/ZA-from-FR}
+
+ \foreach \country in {ML,SN,MA,AO,ZA}{
+ \sankeyadvance[color=\country]{\country}{\hwidth}
+ }
+
+ \sankeyfork{ML}{5/ML-to-CN,3/ML-to-JP,1/ML-to-IN}
+ \sankeyfork{SN}{5/SN-to-CN,3/SN-to-JP,1/SN-to-IN}
+ \sankeyfork{MA}{5/MA-to-CN,3/MA-to-JP,1/MA-to-IN}
+ \sankeyfork{AO}{5/AO-to-CN,3/AO-to-JP,1/AO-to-IN}
+ \sankeyfork{ZA}{5/ZA-to-CN,3/ZA-to-JP,1/ZA-to-IN,3/ZA-to-00}
+
+ \sankeynode{name=IN,quantity=5,
+ at={[xshift=\hdist]ML.right},anchor=right}
+ \sankeynode{name=JP,quantity=15,
+ at={[yshift=\vdist]IN.left},anchor=right}
+ \sankeynode{name=CN,quantity=25,
+ at={[yshift=\vdist]JP.left},anchor=right}
+
+ \sankeyfork{IN}
+ {1/IN-from-ZA,1/IN-from-AO,1/IN-from-MA,1/IN-from-SN,1/IN-from-ML}
+ \sankeyfork{JP}
+ {3/JP-from-ZA,3/JP-from-AO,3/JP-from-MA,3/JP-from-SN,3/JP-from-ML}
+ \sankeyfork{CN}
+ {5/CN-from-ZA,5/CN-from-AO,5/CN-from-MA,5/CN-from-SN,5/CN-from-ML}
+
+ \foreach \country in {IN,JP,CN}{
+ \sankeyadvance[color=\country]{\country}{\hwidth}
+ \sankeyend[color=\country]{\country}
+ }
+
+ \foreach \startcountry/\countries in {
+ CA/{PT,GB,FR}, US/{PT,SP,GB,FR}, MX/{PT,SP,GB,FR},
+ BR/{PT,SP,GB,FR}, FR/{ML,SN,MA,AO,ZA}, GB/{SN,MA,AO,ZA},
+ SP/{SN,MA,ZA}, PT/{SN,MA,AO,ZA}, ML/{IN,JP,CN},
+ SN/{IN,JP,CN}, MA/{IN,JP,CN}, AO/{IN,JP,CN},
+ ZA/{IN,JP,CN}}
+ {
+ \foreach \endcountry in \countries {
+ \sankeyoutin[shade={\startcountry}{\endcountry}]
+ {\startcountry-to-\endcountry}{\endcountry-from-\startcountry}
+ }
+ }
+
+
+ \foreach \country/\countryname in {CA/Canada, US/USA, MX/Mexico,
+ BR/Brazil, FR/France, GB/England, SP/Spain, PT/Portugal}
+ {
+ \node[anchor=south,inner sep=.1em,font=\small]
+ at (\country) {\countryname\vphantom{Ag}};
+ }
+
+ \foreach \country/\countryname in {
+ ML/Mali, SN/Senegal, MA/Morocco, AO/Angola,
+ ZA/South Africa, IN/India, JP/Japan, CN/China}
+ {
+ \node[anchor=south,inner sep=.1em,font=\small]
+ at (\country) {\countryname\vphantom{Ag}};
+ }
+ \end{sankeydiagram}
+\end{tikzpicture}
+%</example3-variation>
+% \fi
+%
+%^^A % ------------------------------------------------------------
+% \clearpage
+% \section{Very nice example -- Nadieh Bremer creation}
+%^^A % ------------------------------------------------------------
+%
+% \embedfile[mimetype=text/plain]{sankey-example4.tex}
+%
+% \begin{figure}
+% \centering
+% {\MakePercentComment\input{sankey-example4}}
+% \caption{Very nice example -- Nadieh Bremer's creation}
+% (from
+% \href{https://www.visualcinnamon.com/portfolio/adyen-report-2019/}{Adyen's
+% Shareholder Report})
+% \label{fig:nice-example}
+% \end{figure}
+%
+% Graphic designer Nadieh Bremer created this very nice Sankey
+% diagram\footnote{\url{https://www.visualcinnamon.com/portfolio/adyen-report-2019/}}
+% for Adyen's second half 2018 report to shareholders. It is coded here
+% with her kind permission.
+%
+% You can change the data values between lines 28 and 53.
+%
+% See figure~\vref{fig:nice-example}. The \code{sankey-example4.tex}
+% file contains the following code and is an attachement of the current
+% PDF document.
+%
+% \lstinputlisting[numbers=left,style=LaTeXsmall]{sankey-example4}
+%
+% \iffalse
+%<*example4>
+\begin{tikzpicture}
+ \renewcommand*\sfdefault{txss}
+ \sffamily
+ \sisetup{
+ detect-all=true,
+ group-separator={,},
+ group-minimum-digits=4,
+ }
+ % storage of labels
+ \newcommand\LabSet[2]{% node name, label
+ \expandafter\edef\csname#1@Lab\endcsname{#2}}
+ \newcommand\Lab[1]{% node name
+ \csname#1@Lab\endcsname}
+ % storage of quantities
+ \newcommand\QtySet[2]{% node name, quantity
+ \expandafter\edef\csname#1@Qty\endcsname{\fpeval{#2}}}
+ \newcommand\Qty[1]{% node name
+ \csname#1@Qty\endcsname}
+ % all nodes with their name, label and quantity
+ \sankeyset{
+ def data/.code args={#1/#2/#3}{% node name/label/values
+ \LabSet{#1}{#2}
+ \QtySet{#1}{#3}
+ \typeout{#1: \Qty{#1}€ (\Lab{#1})}
+ },
+ def data/.list={
+ {Pf/Processing\\fees/71713},
+ {Sog/Sales of\\good/4547},
+ {Sf/Settlement\\fees/842075},
+ {Os/Other\\services/37532},
+ {R/Revenues/\Qty{Pf}+\Qty{Sog}+\Qty{Sf}+\Qty{Os}},
+ {Coi/Cost of Inventory/5151},
+ {Ciffi/Cost insecure from financial institutions/758234},
+ {Nr/Net revenue/\Qty{R}-\Qty{Coi}-\Qty{Ciffi}},
+ {Aadotaifa/Amortization and\\depreciation of tangible and\\
+ intangible fixed assets/4688},
+ {Ssapc/Social securities and\\pension costs/7860},
+ {Was/Wages and salaries/35627},
+ {Ooe/Other operating expenses/37346},
+ {Nr2/-/\Qty{Nr}-\Qty{Aadotaifa}-\Qty{Ssapc}-\Qty{Was}-\Qty{Ooe}},
+ {Oi/Other income/47},
+ {Ibiiieait/Income before interest income,\\interest expense and
+ income taxes/\Qty{Nr2}+\Qty{Oi}},
+ {Fe/Finance expense/561},
+ {Ofr/Other financial results/2533},
+ {Ibiiieait2/-/\Qty{Ibiiieait}-\Qty{Fe}-\Qty{Ofr}},
+ {Fi/Finance income/204},
+ {Ibit/Income before income taxes/\Qty{Ibiiieait2}+\Qty{Fi}},
+ {It/Income taxes/21134},
+ {Niftp/Net income for the period/\Qty{Ibit}-\Qty{It}},
+ {Octa/Other currency\\translation adjustments/785},
+ {Tci/Total comprehensive income/\Qty{Niftp}+\Qty{Octa}}
+ },
+ }
+
+ \definecolor{mygreen}{RGB}{9,192,82}
+ \tikzset{
+ cost node/.style={
+ overlay,
+ align=flush center,
+ node font=\footnotesize\sffamily\bfseries,
+ inner sep=0,
+ node contents={%
+ {\mdseries€\,\num{\Qty{#1}}}\\
+ \Lab{#1}\vphantom{g}%
+ },
+ },
+ white hash/.style={
+ draw=none,fill=none,
+ pattern={Lines[angle=60,line width=2pt,distance=4pt]},
+ pattern color=white,
+ },
+ line sep/.style={draw=white,line width=1pt},
+ left label/.style={left=#1,align=flush right,anchor=north east},
+ right label/.style={right=#1,align=flush left},
+ right label hashed/.style={
+ right=1mm of $(#1.left)!.5!(#1-old.left)$,align=flush left,
+ },
+ left label hashed/.style={
+ left=1mm of $(#1.right)!.5!(#1-old.right)$,align=flush right,
+ },
+ }
+
+ \newcommand\turnandstop[1]{
+ \sankeyturn[green to greenwhite]{#1}{-90}
+ \sankeynode{as=#1,name=#1-e,at={#1 -| Coi}}
+ \sankeyoutin[greenwhite to white]{#1}{#1-e}
+ \node[cost node=#1,left label={1mm of #1-e.right}];
+ }
+
+ \begin{sankeydiagram}%[debug]
+ \sankeyset{
+ ratio=28em/1000000,
+ minimum radius=2cm,
+ start style=none,
+ every node/.style={angle=-90},
+ % default fill and draw styles
+ fill/.style={
+ line width=0pt,
+ fill=mygreen,
+ },
+ draw/.style={draw=none},
+ % specific fill and draw styles
+ green to greenwhite/.style={
+ fill/.style={
+ line width=0pt,
+ right color=mygreen,
+ left color=mygreen!20!white,
+ }
+ },
+ greenwhite to white/.style={
+ fill/.style={
+ line width=0pt,
+ right color=mygreen!20!white,
+ left color=mygreen!5!white,
+ }
+ },
+ dashed/.style={draw/.style={draw=mygreen,dashed}},
+ }
+
+ \coordinate (top) at (0,2em);
+
+ \sankeynodestart{name=Pf,quantity=\Qty{Pf}}
+ \node[cost node=Pf,above=.5em of Pf.center];
+
+ \sankeynodestart{name=Sog,quantity=\Qty{Sog},
+ at={[xshift=4em]Pf.left},anchor=right}
+ \node[cost node=Sog,above=.5em of Sog.center];
+
+ \sankeynodestart{name=Sf,quantity=\Qty{Sf},
+ at={[xshift=2em]Sog.left},anchor=right}
+ \node[cost node=Sf,above=.5em of Sf.center];
+
+ \sankeynodestart{name=Os,quantity=\Qty{Os},
+ at={[xshift=2em]Sf.left},anchor=right}
+ \node[cost node=Os,above=.5em of Os.center];
+
+ \sankeynode{
+ name=R,quantity=\Qty{R},at={[yshift=-10em]Sf.center},
+ forked={\Qty{Os}/Os-a,\Qty{Sf}/Sf-a,\Qty{Sog}/Sog-a,\Qty{Pf}/Pf-a},
+ }
+
+ \foreach \nodename in {Pf,Sog,Sf,Os}{
+ \sankeyoutin[fill/.style={top color=white,bottom color=mygreen}]
+ {\nodename}{\nodename-a}
+ }
+
+ \sankeyadvance{R}{1em}
+ \node[cost node=R,right label hashed=R];
+
+ \sankeyfork{R}{\Qty{Ciffi}/Ciffi,\Qty{Nr}/Nr,\Qty{Coi}/Coi}
+
+ \sankeyturnleft[minimum radius=1.cm]{Ciffi}{90}
+ \node[cost node=Ciffi,at={([shift={(1mm,0)}]Ciffi.center)},rotate=-90,
+ anchor=south,align=flush left,node font=\scriptsize\sffamily\bfseries];
+
+ \sankeyturnright[green to greenwhite]{Coi}{90}
+ \sankeyadvance[greenwhite to white]{Coi}{1em}
+ \node[cost node=Coi,left={1mm of [yshift=.75ex]Coi.left},
+ align=flush right,anchor=north east,overlay];
+
+ \sankeyadvance{Nr}{9em}
+ \sankeyadvance{Nr}{1em}
+ \node[cost node=Nr,left label hashed=Nr,
+ node font=\large\sffamily\bfseries];
+
+ \sankeyfork{Nr}{\Qty{Nr2}/Nr2,\Qty{Ooe}/Ooe,
+ \Qty{Was}/Was,\Qty{Ssapc}/Ssapc,\Qty{Aadotaifa}/Aadotaifa}
+
+ \turnandstop{Aadotaifa}
+
+ \sankeyadvance{Ssapc}{5em}
+ \turnandstop{Ssapc}
+
+ \sankeyadvance{Was}{9em}
+ \turnandstop{Was}
+
+ \sankeyadvance{Ooe}{12em}
+ \turnandstop{Ooe}
+
+ \sankeyadvance{Nr2}{15em}
+ \sankeynode{name=Ibiiieait,quantity=\Qty{Ibiiieait},
+ anchor=right,at={Nr2.right},
+ forked={\Qty{Oi}/Oi,\Qty{Nr2}/Nr2-e}}
+
+ \sankeyturnleftbackward[minimum radius=1cm,dashed]{Oi}{90}
+ \node[cost node=Oi,right label=1mm of Oi.left];
+
+ \sankeyadvance{Ibiiieait}{1em}
+ \node[cost node=Ibiiieait,right label hashed=Ibiiieait];
+
+ \sankeyfork{Ibiiieait}
+ {\Qty{Ibiiieait2}/Ibiiieait2,\Qty{Ofr}/Ofr,\Qty{Fe}/Fe}
+
+ \turnandstop{Fe}
+
+ \sankeyadvance{Ofr}{3em}
+ \turnandstop{Ofr}
+
+ \sankeyadvance{Ibiiieait2}{6em}
+ \sankeynode{name=Ibit,quantity={\Qty{Ibiiieait2}+\Qty{Fi}},
+ anchor=right,at={Ibiiieait2.right},
+ forked={\Qty{Fi}/Fi,\Qty{Ibiiieait2}/Ibiiieait2-e}}
+
+ \sankeyturnleftbackward[minimum radius=1cm,dashed]{Fi}{90}
+ \node[cost node=Fi,right label=1mm of Fi.left];
+
+ \sankeyadvance{Ibit}{1em}
+ \node[cost node=Ibit,right label hashed=Ibit];
+
+ \sankeyfork{Ibit}{\Qty{Niftp}/Niftp,\Qty{It}/It}
+
+ \turnandstop{It}
+
+ \sankeyadvance{Niftp}{6em}
+
+ \sankeyadvance{Niftp}{1em}
+ \node[cost node=Niftp,right label hashed=Niftp];
+
+ \sankeynode{name=Tci,quantity=\Qty{Niftp}+\Qty{Octa},
+ anchor=right,at={[yshift=-6em]Niftp.right},
+ forked={\Qty{Octa}/Octa,\Qty{Niftp}/Niftp-e}}
+ \sankeyoutin{Niftp}{Niftp-e}
+
+ \sankeyturnleftbackward[minimum radius=1cm]{Octa}{90}
+ \node[cost node=Octa,right label=1mm of Octa.left];
+
+ \sankeyadvance{Tci}{1em}
+ \node[cost node=Tci,right label hashed=Tci];
+
+ \newcommand\hashband[1]{
+ \draw[line sep] (#1-old.right) -- (#1-old.left);
+ \draw[line sep] (#1.right) -- (#1.left);
+ \path[white hash] (#1-old.right) rectangle (#1.left);
+ }
+
+ \foreach \nodename in {R,Nr,Nr,Ibiiieait,Ibit,Niftp,Tci}{
+ \hashband{\nodename}
+ }
+
+ \end{sankeydiagram}
+\end{tikzpicture}
+%</example4>
+% \fi
+%
+% \clearpage
+%
+% \StopEventually{}
+%^^A % ------------------------------------------------------------
+%
+% \manualparts
+%
+% \part{Implementation}
+% \label{implementation}
+%^^A % ------------------------------------------------------------
+%
+% {
+% \setlength{\parskip}{0pt}
+% \localtableofcontents
+% }
+%
+%^^A % ------------------------------------------------------------
+% \section{The \texttt{sankey.sty} file}
+%^^A % ------------------------------------------------------------
+%
+% Poorly commented source code...
+%
+% \changes{v1.0}{2016/03/06}{first version}
+% \changes{v2.0}{2021/01/27}{first public version (on CTAN)}
+% \changes{v3.0}{2021/03/14}{better naming rule}
+% \changes{v3.0}{2021/03/14}{use .ins and .dtx files}
+%
+% \iffalse
+%<*sankey>
+% \fi
+%
+% Version information:
+%
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}[2015/10/01]
+\ProvidesPackage{sankey}[2021/03/14 v3.0 to draw Sankey diagrams]
+% \end{macrocode}
+%
+% All required packages and TikZ libraries:
+% \begin{macrocode}
+\RequirePackage{xparse}
+\RequirePackage{etoolbox}
+\RequirePackage{xfp}
+\RequirePackage{tikz}
+\usetikzlibrary{
+ calc,
+ decorations.markings,
+ dubins
+}
+% \end{macrocode}
+%
+% Declarations of PGF layers (to debug Sankey diagrams):
+%
+% \begin{macrocode}
+%% add a new layer to debug sankey diagrams
+\pgfdeclarelayer{background}
+\pgfdeclarelayer{foreground}
+\pgfdeclarelayer{sankeydebug}
+\pgfsetlayers{background,main,foreground,sankeydebug}
+% \end{macrocode}
+%
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Fields}
+%^^A % ------------------------------------------------------------
+%
+% \begin{macro}{\snk@newfield}
+%
+% The \code{sankeynewfield} macro defines
+% setter and getter macros for \emph{key}/\emph{value} pairs.
+% It requires five parameters: the \emph{def} macro used to
+% store a new value, the \emph{setter} macro name, the \emph{getter} macro name,
+% the \emph{cs name} used by the new field (including a \texttt{\#1}
+% parameter -- the \emph{key}) and the \emph{error message} (used by the getter
+% macro if the key is not defined).
+%
+% The \emph{setter} macro requires
+% two parameters: the key and the value.
+% The \emph{getter} macro requires
+% one parameter: the key.
+%
+% \begin{macrocode}
+\def\snk@newfield#1#2#3#4#5{
+ % setter
+ \def#2##1##2{\expandafter#1\csname #4\endcsname{##2}}
+ % getter
+ \def#3##1{%
+ \ifcsdef{#4}{%
+ \csname#4\endcsname%
+ }{%
+ \PackageError{sankey}{#5}{unknown key with \string#3}%
+ }%
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Definition of \emph{global} and \emph{expanded} fields (using
+% \texttt{\protect\string\xdef})}
+%^^A % ------------------------------------------------------------
+%
+% \begin{macro}{\snk@setnodeqty}
+% \begin{macro}{\sankeygetnodeqty}
+% The setter and getter macros to store and retrieve
+% the \emph{quantity} field associated with
+% each Sankey node (the key is the name of the Sankey node).
+% \begin{macrocode}
+\snk@newfield\xdef\snk@setnodeqty\sankeygetnodeqty%
+{@snk@node@qty@#1}{Unknown sankey node '#1'}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\snk@setnodeorient}
+% \begin{macro}{\sankeygetnodeorient}
+% The setter and getter macros to store and retrieve
+% the \emph{angle} (or orientation) field
+% associated with each Sankey node (the key is the name of the Sankey node).
+% \begin{macrocode}
+\snk@newfield\xdef\snk@setnodeorient\sankeygetnodeorient%
+{@snk@node@orient@#1}{Unknown sankey node '#1'}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Definitions of \emph{local} fields (using \texttt{\protect\string\def})}
+%^^A % ------------------------------------------------------------
+%
+% \begin{macro}{\snk@setstartfill}
+% \begin{macro}{\snk@getstartfill}
+% \begin{macro}{\snk@setstartdraw}
+% \begin{macro}{\snk@getstartdraw}
+% The setter and getter macros to store and retrieve the starting fill/draw
+% paths (the key is the style name).
+% \begin{macrocode}
+\snk@newfield\def\snk@setstartfill\snk@getstartfill%
+{@snk@start@fill@#1}{Unknown sankey start fill path #1}
+
+\snk@newfield\def\snk@setstartdraw\snk@getstartdraw%
+{@snk@start@draw@#1}{Unknown sankey start draw path #1}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\snk@setendfill}
+% \begin{macro}{\snk@getendfill}
+% \begin{macro}{\snk@setenddraw}
+% \begin{macro}{\snk@getenddraw}
+% The setter and getter macros to store and retrieve the ending fill/draw
+% paths (the key is the style name).
+% \begin{macrocode}
+\snk@newfield\def\snk@setendfill\snk@getendfill%
+{@snk@end@fill@#1}{Unknown sankey end fill path #1}
+
+\snk@newfield\def\snk@setenddraw\snk@getenddraw%
+{@snk@end@draw@#1}{Unknown sankey end draw path #1}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Check if a sankey node is defined}
+%^^A % ------------------------------------------------------------
+%
+% \begin{macro}{\snk@ifnodedefined}
+
+% The \code{\snk@ifnodedefined} macro checks if a Sankey
+% node is defined by checking if its name is associated to
+% a \emph{quantity}.
+% \begin{macrocode}
+\newcommand\snk@ifnodedefined[3]{%
+ \ifcsdef{@snk@node@qty@#1}{#2}{#3}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\snk@errorifnotdefined}
+% The \code{\snk@errorifnotdefined} macro generares
+% an error message if the Sankye node is not defined.
+% \begin{macrocode}
+\newcommand\snk@errorifnotdefined[1]{%
+ \snk@ifnodedefined{#1}{}%
+ {\PackageError{sankey}{Unknown sankey node '#1'}{}}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{The \texttt{sankey node} shape}
+%^^A % ------------------------------------------------------------
+%
+%
+% A \code{sankey node} is defined as a TikZ node
+% with a particular \emph{shape}: its width is null and its
+% height matches the associated \emph{quantity}.
+% This shape requires only three anchors: \code{center}, \code{left}
+% and \code{right}.
+% These threee anchors are sufficient to use the
+% \code{sankey} package. But the \code{fit} library needs
+% anchors defined by rectangular node.
+%
+% \begin{macrocode}
+\pgfdeclareshape{sankey node}{
+ \inheritsavedanchors[from=rectangle]
+ \inheritanchor[from=rectangle]{center}
+ \inheritanchorborder[from=rectangle]
+ \anchor{left}{\pgf@process{\northeast}}
+ \anchor{right}{\pgf@process{\southwest}}
+ % compatibility with 'fit' library
+ \inheritanchor[from=rectangle]{west}
+ \inheritanchor[from=rectangle]{east}
+ \inheritanchor[from=rectangle]{north}
+ \inheritanchor[from=rectangle]{south}
+ \inheritanchor[from=rectangle]{north west}
+ \inheritanchor[from=rectangle]{south east}
+ \inheritanchor[from=rectangle]{north east}
+ \inheritanchor[from=rectangle]{south west}
+}
+% \end{macrocode}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Keys}
+%^^A % ------------------------------------------------------------
+%
+% \begin{macro}{\sankeyset}
+% The \code{sankey} package uses \code{pgfkeys} to set options via
+% \emph{key=value} pairs using the \texttt{/sankey} path
+% (for Sankey diagram options) and using the
+% \texttt{/sankey/node parameters} path (for Sankey node parameters).
+%
+% The \code{\sankeyset} macro processes
+% its parameter as a list of comma separated pairs of the form
+% \emph{key=value} with the default path set to \texttt{/sankey}.
+%
+% \begin{macrocode}
+\pgfkeys{/sankey/.is family}
+\NewDocumentCommand\sankeyset{m}{\pgfkeys{sankey,#1}}
+% \end{macrocode}
+% \end{macro}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Keys to define the scale}
+%^^A % ------------------------------------------------------------
+% \begin{macro}{\snk@totalqty}
+% \begin{macro}{\snk@totallen}
+%
+% The \code{ratio quantity}, \code{ratio length} and
+% \code{ratio} keys define the ratio between
+% \emph{flow quantity} and \emph{graphic length} (the scale).
+% The \code{\snk@totalqty} and \code{\snk@totallen} macros store the values.
+% All \emph{quantities} are processed by \code{\fpeval} and
+% all \emph{lengths} are processed by \code{pgfmath}.
+% \begin{macrocode}
+\sankeyset{
+ ratio quantity/.code={\edef\snk@totalqty{\fpeval{#1}}},
+ ratio quantity/.value required,
+ ratio length/.code={
+ \pgfmathsetmacro\snk@totallen{#1}
+ \edef\snk@totallen{\snk@totallen pt}
+ },
+ ratio length/.value required,
+ ratio/.style args={#1/#2}{
+ ratio length=#1,
+ ratio quantity=#2,
+ },
+ ratio/.value required,
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Rotate offset}
+%^^A % ------------------------------------------------------------
+%
+% \begin{macro}{\snk@rotate}
+%
+% The \code{rotate} key stores an offset angle applied to all Sankey
+% nodes. This is useful when using the \code{rotate} option within a
+% \code{tikzpicture} or a \code{scope}. This TikZ option is only
+% applied to coordinates and not to TikZ nodes (remember that Sankey
+% nodes are TikZ nodes). It's up to the author to keep the
+% \code{rotate} option of the \code{tikzpicture} and that of the
+% \code{sankeydiagram} synchronous.
+%
+% \begin{macrocode}
+\sankeyset{
+ rotate/.code={\edef\snk@rotate{\fpeval{#1}}},
+ rotate/.value required,
+}
+% \end{macrocode}
+% \end{macro}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Minimum radius}
+%^^A % ------------------------------------------------------------
+%
+% \begin{macro}{\snk@minradius}
+%
+% The \code{minimum radius} key processes the minimum radius
+% of curvature by \code{pgfmath} then stores it in
+% the \code{\snk@minradius} macro.
+% \begin{macrocode}
+\sankeyset{
+ minimum radius/.code={
+ \pgfmathsetmacro\snk@minradius{#1}
+ \edef\snk@minradius{\snk@minradius pt}
+ },
+ minimum radius/.value required,
+}
+% \end{macrocode}
+% \end{macro}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Outin step}
+%^^A % ------------------------------------------------------------
+%
+% \begin{macro}{\snk@stepoutin}
+% The \code{outin} key stores its value in
+% the \code{\snk@stepoutin} macro.
+%
+% \begin{macrocode}
+\sankeyset{
+ outin steps/.estore in=\snk@stepoutin,
+ outon steps/.value required,
+}
+% \end{macrocode}
+% \end{macro}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Sankey debug}
+%^^A % ------------------------------------------------------------
+%
+%
+% The \code{debug} key drives the \code{sankey debug} toggle.
+%
+% \begin{macrocode}
+\newtoggle{sankey debug}
+\sankeyset{
+ debug/.is choice,
+ debug/true/.code={\toggletrue{sankey debug}},
+ debug/false/.code={\togglefalse{sankey debug}},
+ debug/.default=true,
+}
+% \end{macrocode}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Start and end styles}
+%^^A % ------------------------------------------------------------
+%
+% \begin{macro}{\snk@startstyle}
+% \begin{macro}{\snk@endstyle}
+% The \code{start style} and \code{end style} keys are choices.
+%
+% The \code{new start style} and \code{new end style} keys
+% add new option to these choices.
+% They use the \code{startfill}, \code{startdraw} fields
+% or the \code{endfill} and \code{enddraw}
+% fields (using the style \emph{name} as key) to store the fill and draw
+% paths then create a new option to install the new
+% start (\code{\snk@startstyle}) or end (\code{\snk@endstyle}) style.
+%
+% \begin{macrocode}
+\sankeyset{
+ start style/.is choice,
+ end style/.is choice,
+ % to define new start and end styles
+ new start style/.code n args={3}{% name, fill path, draw path
+ \snk@setstartfill{#1}{#2}
+ \snk@setstartdraw{#1}{#3}
+ \sankeyset{start style/#1/.code={\def\snk@startstyle{#1}}}
+ },
+ new end style/.code n args={3}{% name, fill path, draw path
+ \snk@setendfill{#1}{#2}
+ \snk@setenddraw{#1}{#3}
+ \sankeyset{end style/#1/.code={\def\snk@endstyle{#1}}}
+ },
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Initial parameters}
+%^^A % ------------------------------------------------------------
+%
+% The \code{@initial options} style defines default values for
+% options of Sankey diagram. The \code{every diagram} style (initially
+% empty) allows the user to choose its own default values.
+%
+% The \code{@initial options} and the \code{every diagram} styles are
+% applied (in this order) at the beginning of each Sankey diagram.
+%
+% \begin{macrocode}
+\sankeyset{
+ debug color/.style={/utils/exec={\colorlet{debug color}{#1}}},
+ @initial options/.style={
+ ratio=1cm/10,
+ minimum radius=5mm,%
+ outin steps=10,
+ debug=false,
+ start style=none,
+ end style=none,
+ rotate=0,
+ % default fill/draw styles,
+ fill/.style={line width=0pt,fill=white},
+ draw/.style={draw=black,line width=.4pt},
+ % debug color used by all debug macros
+ debug color=red!75!black,
+ % debug line between left and right anchors
+ debug line/.style={overlay,draw=debug color,|-|},
+ % debug line between center and label
+ debug normal/.style={overlay,draw=debug color},
+ % debug node label
+ debug label/.style={
+ overlay,
+ draw,
+ font=\ttfamily\tiny,
+ text=debug color,text opacity=1,
+ inner sep=.1em,
+ fill=white,fill opacity=1,
+ rounded corners=.1em,
+ node contents={\name},
+ },
+ every node/.style={},
+ },
+ every diagram/.style={},
+}
+
+% \end{macrocode}
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Sankey node parameters}
+%^^A % ------------------------------------------------------------
+%
+% The \code{/sankey/node parameters} family defines all parameters during
+% creation of Sankey node.
+%
+% \begin{macrocode}
+\sankeyset{node parameters/.is family}
+% \end{macrocode}
+% \begin{macro}{\name}
+% \begin{macro}{\qty}
+% \begin{macro}{\orient}
+% \begin{macro}{\pos}
+%
+% The \code{name}, \code{quantity}, \code{angle} and \code{at} keys use the
+% \code{\name}, \code{\qty}, \code{\orient} and \code{\pos} macros
+% to store the \emph{name}, the \emph{quantity}, the \emph{orientation} (or
+% \emph{angle}) and the \emph{position} of a Sankey node during its
+% creation.
+%
+% The \emph{quantity} is processed via \code{\fpeval}. The
+% \emph{orientation} is normalized.
+%
+% \begin{macrocode}
+\sankeyset{node parameters,
+ name/.estore in=\name,
+ name/.value required,
+ quantity/.code={\edef\qty{\fpeval{#1}}},
+ quantity/.value required,
+ angle/.code={\edef\orient{\snk@normalize@angle{#1}}},
+ angle/.value required,
+ at/.code={\snk@getpos\pos{#1}},
+ at/.value required,
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% The \code{as} key is just a shortcut to define the four current node
+% parameters by copying them from an existing Sankey node.
+%
+% \begin{macrocode}
+\sankeyset{node parameters,
+ as/.style={
+ name=#1,
+ quantity=\sankeygetnodeqty{#1},
+ angle=\sankeygetnodeorient{#1},
+ at={#1.center},
+ },
+ as/.value required,
+}
+% \end{macrocode}
+%
+% \begin{macro}{\snk@anchor}
+%
+% The \code{anchor} key stores in the \code{\snk@anchor} macro
+% the anchor name to use to create the new current Sankey node
+%
+% \begin{macrocode}
+\sankeyset{node parameters,
+ anchor/.is choice,
+ anchor/left/.code={\def\snk@anchor{left}},
+ anchor/right/.code={\def\snk@anchor{right}},
+ anchor/center/.code={\def\snk@anchor{center}},
+ anchor/.value required,
+}
+% \end{macrocode}
+% \end{macro}
+%
+% The \code{start} and \code{end} keys drive the
+% \code{sankey node start} and \code{sankey node end}
+% toggles.
+%
+% \begin{macrocode}
+\newtoggle{sankey node start}
+\newtoggle{sankey node end}
+\sankeyset{node parameters,
+ start/.is choice,
+ start/true/.code={\toggletrue{sankey node start}},
+ start/false/.code={\togglefalse{sankey node start}},
+ start/.default=true,
+ %
+ end/.is choice,
+ end/true/.code={\toggletrue{sankey node end}},
+ end/false/.code={\togglefalse{sankey node end}},
+ end/.default=true,
+}
+% \end{macrocode}
+% \begin{macro}{\snk@listofforks}
+% \begin{macro}{\snk@forkanchor}
+%
+% The \code{forked} and \code{fork anchor} keys store their value in the
+% \code{\snk@listofforks} and \code{\snk@forkanchor} macros.
+%
+% \begin{macrocode}
+\sankeyset{node parameters,
+ forked/.estore in=\snk@listofforks,
+ forked/.value required,
+ fork anchor/.estore in=\snk@forkanchor,
+ fork anchor/.value required,
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% The \code{@initial parameters} style initialises all Sankey node
+% parameters at the start of the creation of a new Sankey node.
+%
+% \begin{macrocode}
+\sankeyset{node parameters,
+ @initial parameters/.style={
+ start=false,
+ end=false,
+ forked=,
+ fork anchor=,
+ anchor=center,
+ at={0,0},
+ angle=0,
+ },
+}
+% \end{macrocode}
+%
+%
+%^^A % ------------------------------------------------------------
+% \subsubsection{Internal Tikz style}
+%^^A % ------------------------------------------------------------
+%
+% To apply this style with Tikz, use absolute key name
+% (\texttt{/sankey/@sankey node}). This style is used to create the Tikz
+% node assoicated to a Sankey node.
+%
+% \begin{macrocode}
+\sankeyset{
+ % sankey node TikZ style
+ @sankey node/.style n args={3}{% name, pos, anchor
+ shape=sankey node,
+ inner sep=0,
+ minimum height={\sankeyqtytolen{\sankeygetnodeqty{#1}}},
+ minimum width=0,
+ draw=none,
+ line width=0pt,
+ fill=none,
+ node contents={},
+ rotate=\sankeygetnodeorient{#1}+\snk@rotate,
+ at={(#2)},
+ name=#1,
+ anchor=#3,
+ },
+}
+% \end{macrocode}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{The \texttt{sankeydiagram} environment}
+% ^^A % ------------------------------------------------------------
+%
+% \begin{environment}{sankeydiagram}
+%
+% The \code{sankeydiagram} environment defines locally all the macros
+% used by a Sankey diagram. Then it applies the %
+% \code{@initial options} and \code{every diagram} styles (in this
+% order) and applies all the keys provided in its optional argument.
+%
+% \begin{macrocode}
+\NewDocumentEnvironment{sankeydiagram}{O{}}{
+% \end{macrocode}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Internal macros}
+%^^A % ------------------------------------------------------------
+%
+% \begin{macro}{\snk@getpos}
+%
+% The \code{\snk@getpos} macro extracts the position of a TikZ
+% node\footnote{Thanks to Andrew Stacey \url{https://tex.stackexchange.com/a/33765/14500}}.
+%
+% \begin{macrocode}
+ \def\snk@getpos##1##2{%
+ \tikz@scan@one@point\pgfutil@firstofone(##2)\relax%
+ \edef##1{\the\pgf@x,\the\pgf@y}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\snk@modulo}
+%
+% The \code{\snk@modulo} macro evaluates \#1 modulo \#2 using \code{\fpeval}.
+%
+% \begin{macrocode}
+ \def\snk@modulo##1##2{\fpeval{##1-(floor((##1)/(##2),0)*##2)}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\snk@normalize@angle}
+%
+% The \code{\snk@normalize@angle} macro normalizes \#1 (an angle) between
+% $-180$ and $180$ (using \code{\fpeval}).
+%
+% \begin{macrocode}
+ \def\snk@normalize@angle##1{%
+ \fpeval{\snk@modulo{(##1)+180}{360}-180}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\snk@show@debug}
+%
+% The \code{snk@show@debug} macro draws debug information
+% of the Sankey node named \#1 but only if the \code{sankey debug}
+% toogle is true. Everything is drawn on the \code{sankeydebug}
+% layer. It uses the \code{/sankey/debug line},
+% \code{/sankey/debug normal} and \code{/sankey/debug label} Tikz styles.
+%
+% \begin{macrocode}
+ \def\snk@show@debug##1{% node name
+ \iftoggle{sankey debug}{
+ \begingroup
+ \edef\name{##1}
+ \edef\qty{\sankeygetnodeqty{\name}}
+ \edef\orient{\sankeygetnodeorient{\name}}
+ \begin{pgfonlayer}{sankeydebug}
+ \path[/sankey/debug line] (\name.left) -- (\name.right);
+ \pgfmathsetmacro{\snk@len}{\sankeyqtytolen{\qty}/3}
+ \path[/sankey/debug normal] (\name.center)
+ -- ($(\name.center)!\snk@len pt!90:(\name.right)$)
+ node[/sankey/debug label,rotate=\orient+90+\snk@rotate,anchor=north];
+ \end{pgfonlayer}
+ \endgroup
+ }{}
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\snk@makeforkednode}
+% \begin{macro}{\snk@tot}
+% \begin{macro}{\snk@subnodeqty}
+% \begin{macro}{\snk@subnodename}
+% \begin{macro}{\snk@added@values}
+%
+% The \code{\snk@makeforkednode} forks a Sankey node.
+%
+% \begin{macrocode}
+ \def\snk@makeforkednode{
+ \begingroup
+ \ifdefempty{\snk@listofforks}{
+ \ifdefempty{\snk@forkanchor}{}{
+ \PackageWarning{sankey}%
+ {Can't use 'fork anchor' key without 'forked' key}
+ }
+ }{
+ \def\snk@tot{0}
+ \def\snk@added@values{}
+ \sankeyset{
+ @add forked node/.code args={####1/####2}{
+ \coordinate (####2) at ($(\name.left)%
+ !\fpeval{(\snk@tot+.5*(####1))/\qty}%
+ !(\name.right)$);
+ \edef\snk@orient{\orient}
+ \sankeynode[debug=false]
+ {name=####2,quantity=####1,at=####2,angle=\snk@orient}
+ \edef\snk@tot{\fpeval{\snk@tot+####1}}
+ \edef\snk@added@values{\snk@added@values+####1}
+ },
+ @add forked node/.list/.expand once=\snk@listofforks,
+ }
+ \edef\snk@diff{\fpeval{abs(\qty-\snk@tot)}}
+ \ifnumequal{\snk@diff}{0}{}{
+ \PackageWarning{sankey}%
+ {^^J*** Warning: bad sankey fork: %
+ \qty\space!=\space\snk@added@values(=\snk@tot)%
+ ^^J\snk@listofforks}
+ }
+ \ifdefempty{\snk@forkanchor}{
+ \edef\snk@forkanchor{\name.\snk@anchor}
+ }{}
+ \snk@getpos\snk@c{$(\snk@forkanchor) - (\pos)$}
+ \sankeynode{as=\name,at={$(\name) - (\snk@c)$}}
+ \foreach \snk@subnodeqty/\snk@subnodename in \snk@listofforks {
+ \sankeynode{as=\snk@subnodename,at={$(\snk@subnodename) - (\snk@c)$}}
+ }
+ }
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\snk@makenode}
+%
+% The \code{\snk@makenode} macro creates a new Sankey node named
+% \code{\name} with \code{\qty} quantity, oriented at
+% \code{\orient} degrees (but modified by the \code{\snk@rotate}
+% angle offset), anchored by its \code{\anchor} (or its \emph{center}
+% by default) at \code{\pos} position.
+%
+% \begin{macrocode}
+ \def\snk@makenode{
+ \begingroup
+ \snk@setnodeqty{\name}{\qty}
+ \edef\orient{\snk@normalize@angle{\orient}}
+ \snk@setnodeorient{\name}{\orient}
+ \ifundef{\snk@anchor}{\def\snk@anchor{center}}{}
+ \node[/sankey/@sankey node={\name}{\pos}{\snk@anchor}];
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\snk@filldrawstart}
+%
+% The \code{\snk@filldrawstart} macro fills
+% (with the \code{/sankey/fill} TikZ style) then draws
+% (with the \code{/sankey/draw} TikZ style)
+% a start of flow using paths from style \code{\snk@startstyle} on
+% the Sankey node named \code{\name}.
+%
+% \begin{macrocode}
+ \def\snk@filldrawstart{
+ \begin{scope}[shift={(\name)},rotate=\orient]
+ \path[/sankey/fill] \snk@getstartfill{\snk@startstyle};
+ \path[/sankey/draw] \snk@getstartdraw{\snk@startstyle};
+ \end{scope}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\snk@filldrawend}
+%
+% The \code{\snk@filldrawend} macro fills
+% (with the \code{/sankey/fill} TikZ style) then draws
+% (with the \code{/sankey/draw} TikZ style)
+% a end of flow using paths from style \code{\snk@endstyle} on
+% the Sankey node named \code{\name}.
+%
+% \begin{macrocode}
+ \def\snk@filldrawend{
+ \begin{scope}[shift={(\name)},rotate=\sankeygetnodeorient{\name}]
+ \path[/sankey/fill] \snk@getendfill{\snk@endstyle};
+ \path[/sankey/draw] \snk@getenddraw{\snk@endstyle};
+ \end{scope}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\snk@checkquantities}
+% \begin{macro}{\snk@qtyi}
+% \begin{macro}{\snk@qtyii}
+% The \code{\snk@checkquantities} compares quantities
+% from Sankey nodes \code{#1} and \code{#2} and emits
+% an error message if they differ (\code{#3} is the name
+% of the macro which requested the verification).
+%
+% \begin{macrocode}
+ \def\snk@checkquantities##1##2##3{
+ \begingroup
+ \edef\snk@qtyi{\sankeygetnodeqty{##1}}
+ \edef\snk@qtyii{\sankeygetnodeqty{##2}}
+ \ifdefstrequal{\snk@qtyi}{\snk@qtyii}{}{
+ \PackageError{sankey}%
+ {^^J*** \string##3: quantities differ between %
+ ##1 (\snk@qtyi) and ##2 (\snk@qtyii)%
+ ^^J}%
+ {The quantities of the two Sankey nodes must be equal.}
+ }
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{User macros}
+%^^A % ------------------------------------------------------------
+%
+% \begin{macro}{\sankeydubins}
+%
+% The \code{\sankeydubins} macro links two Sankey nodes via
+% a Dubins path. First, it computes the Dubins path between
+% centers (left and right radii are the same) and stores the
+% result in \code{sankey}. Then it uses the stored result
+% to fill and draw the lane (left border and right borders
+% use Dubins paths with asymmetric radii).
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeydubins{O{}mm}{% options, sn, en
+ \snk@errorifnotdefined{##2}
+ \snk@errorifnotdefined{##3}
+ \snk@checkquantities{##2}{##3}{\sankeydubins}
+ \begingroup
+ \sankeyset{##1}
+ \pgfmathsetmacro\qty{\sankeygetnodeqty{##2}}
+ \dubinspathset{
+ sankey/.style={
+ start point=##2.center,start angle=\sankeygetnodeorient{##2},
+ end point=##3.center,end angle=\sankeygetnodeorient{##3},
+ minimum radius=\snk@minradius + .5 * \sankeyqtytolen{\qty} pt,
+ },
+ }
+ \dubinspathcalc{sankey,store=sankey}
+ \dubinspathset{
+ left border/.style={
+ sankey, use store=sankey,
+ left and right minimum radii={\snk@minradius}
+ and {\snk@minradius + \sankeyqtytolen{\qty} pt},
+ },
+ right border/.style={
+ sankey, use store=sankey,
+ left and right minimum radii=
+ {\snk@minradius + \sankeyqtytolen{\qty} pt}
+ and {\snk@minradius},
+ },
+ }
+ % fill the region
+ \path[/sankey/fill] (##2.left) \dubinspath{left border}
+ -- (##3.left) -- (##3.right) \dubinspath{right border,reverse}
+ -- (##2.right) -- cycle;
+ % draw left and right borders
+ \path[/sankey/draw] (##2.left) \dubinspath{left border}
+ (##2.right) \dubinspath{right border};
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sankeyoutin}
+%
+% The \code{\sankeyoutin} macro links two Sankey nodes via a Bézier curve.
+% First, to simulate constant width, it creates \code{\snk@stepoutin}
+% intermediate Sankey nodes along the Bézier curve. Then, the lane is
+% filled and drawn linking all the intermediate Sankey node via smaller
+% Bézier curves.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeyoutin{O{}mm}{% options, sn, en
+ \snk@errorifnotdefined{##2}
+ \snk@errorifnotdefined{##3}
+ \snk@checkquantities{##2}{##3}{\sankeyoutin}
+ \begingroup
+ \sankeyset{##1}
+ \edef\qty{\sankeygetnodeqty{##2}}
+ \pgfmathsetmacro\snk@len{\sankeyqtytolen{\qty}/2}
+ \edef\snk@step{\fpeval{1/\snk@stepoutin}}
+ \edef\snk@laststep{\inteval{\snk@stepoutin-1}}
+ \path[overlay,decorate,decoration={
+ markings,
+ mark=between positions \snk@step and {\fpeval{1-.5*\snk@step}}
+ step \snk@step with {
+ \edef\snk@outinmidptname{%
+ snk@outinmidpt-%
+ \pgfkeysvalueof{/pgf/decoration/mark info/sequence number}%
+ }
+ \path
+ (0,0) coordinate(\snk@outinmidptname)
+ (0,-\snk@len pt) coordinate (\snk@outinmidptname-r)
+ (0,\snk@len pt) coordinate (\snk@outinmidptname-l)
+ ;
+ }
+ }]
+ (##2.center)
+ to[out=\sankeygetnodeorient{##2},in=\sankeygetnodeorient{##3}+180]
+ (##3.center);
+ \foreach \snk@ptnum in {1,...,\snk@laststep}{
+ \edef\snk@outinmidptname{snk@outinmidpt-\snk@ptnum}
+ \dbp@anglebetween\snk@outinmidptangle%
+ {\snk@outinmidptname-r}{\snk@outinmidptname-l}
+ \sankeynode[debug=false]{%
+ name=\snk@outinmidptname,
+ quantity=\qty,
+ angle=\snk@outinmidptangle-90,%
+ at=\snk@outinmidptname%
+ }
+ }
+ \sankeynode[debug=false]{%
+ name={snk@outinmidpt-0},
+ quantity=\sankeygetnodeqty{##2},
+ angle=\sankeygetnodeorient{##2},%
+ at={##2}%
+ }
+ \sankeynode[debug=false]{%
+ name={snk@outinmidpt-\snk@stepoutin},
+ quantity={\sankeygetnodeqty{##3}},
+ angle={\sankeygetnodeorient{##3}},%
+ at={##3}%
+ }
+ \path[/sankey/fill,looseness=1]
+ (snk@outinmidpt-0.left)
+ \foreach \snk@curpt
+ [remember=\snk@curpt as \snk@prevpt (initially 0)]
+ in {1,...,\snk@stepoutin}{
+ to[out=\sankeygetnodeorient{snk@outinmidpt-\snk@prevpt},
+ in=\sankeygetnodeorient{snk@outinmidpt-\snk@curpt}+180]
+ (snk@outinmidpt-\snk@curpt.left)
+ }
+ --
+ (snk@outinmidpt-\snk@stepoutin.right)
+ \foreach \snk@curpt
+ [remember=\snk@curpt as \snk@prevpt (initially \snk@stepoutin)]
+ in {\snk@laststep,...,0}{
+ to[out=\sankeygetnodeorient{snk@outinmidpt-\snk@prevpt}+180,
+ in=\sankeygetnodeorient{snk@outinmidpt-\snk@curpt}]
+ (snk@outinmidpt-\snk@curpt.right)
+ }
+ -- cycle;
+ \path[/sankey/draw,looseness=1]
+ (snk@outinmidpt-0.left)
+ \foreach \snk@curpt
+ [remember=\snk@curpt as \snk@prevpt (initially 0)]
+ in {1,...,\snk@stepoutin}{
+ to[out=\sankeygetnodeorient{snk@outinmidpt-\snk@prevpt},
+ in=\sankeygetnodeorient{snk@outinmidpt-\snk@curpt}+180]
+ (snk@outinmidpt-\snk@curpt.left)
+ }
+ (snk@outinmidpt-\snk@stepoutin.right)
+ \foreach \snk@curpt
+ [remember=\snk@curpt as \snk@prevpt (initially \snk@stepoutin)]
+ in {\snk@laststep,...,0}{
+ to[out=\sankeygetnodeorient{snk@outinmidpt-\snk@prevpt}+180,
+ in=\sankeygetnodeorient{snk@outinmidpt-\snk@curpt}]
+ (snk@outinmidpt-\snk@curpt.right)
+ };
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\sankeynodealias}
+%
+% The \code{\sankeynodealias} macro clones the Sankey node
+% named \code{#1} into a Sankey node named \code{#2}.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeynodealias{mm}{%name, alias
+ \snk@errorifnotdefined{##1}
+ \path[late options={name=##1,alias=##2}];
+ \snk@setnodeqty{##2}{\sankeygetnodeqty{##1}}
+ \snk@setnodeorient{##2}{\sankeygetnodeorient{##1}}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sankeynode}
+%
+% The \code{\sankeynode} macro creates the new Sankey
+% node named \code{#2}.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeynode{O{}m}{% options, node parameters
+ \begingroup
+ \sankeyset{##1}
+ \sankeyset{node parameters,@initial parameters,/sankey/every node,##2}
+ \snk@makenode{}
+ \snk@makeforkednode{}
+ \iftoggle{sankey node start}{\snk@filldrawstart}{}
+ \iftoggle{sankey node end}{\snk@filldrawend}{}
+ \snk@show@debug{\name}
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sankeystart}
+%
+% The \code{\sankeystart} macro fills and draws a starting lane
+% attached to the Sankey node named \code{#2}.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeystart{O{}m}{% options, name
+ \snk@errorifnotdefined{##2}
+ \begingroup
+ \sankeyset{##1}
+ \edef\name{##2}
+ \edef\orient{\sankeygetnodeorient{##2}}
+ \edef\qty{\sankeygetnodeqty{##2}}
+ \snk@filldrawstart
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sankeynodestart}
+%
+% The \code{\sankeynodestart} macro creates the new Sankey
+% node named \code{#2} then fills and draws a starting lane
+% attached to this new Sankey node.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeynodestart{O{}m}{% option, node parameters
+ \sankeynode[##1]{start,##2}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sankeyend}
+%
+% The \code{\sankeyend} macro fills and draws an ending lane
+% attached to the Sankey node named \code{#2}.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeyend{O{}m}{%options, name
+ \snk@errorifnotdefined{##2}
+ \begingroup
+ \sankeyset{##1}
+ \edef\name{##2}
+ \edef\orient{\sankeygetnodeorient{##2}}
+ \edef\qty{\sankeygetnodeqty{##2}}
+ \snk@filldrawend
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sankeynodeend}
+%
+% The \code{\sankeynodeend} macro creates the new Sankey
+% node named \code{#2} then fills and draws an ending lane
+% attached to this new Sankey node.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeynodeend{O{}m}{% options, node parameters
+ \sankeynode[##1]{end,##2}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sankeyadvance}
+% \begin{macro}{\sankeyadvance*}
+%
+% The \code{\sankeyadvance} macro moves toward (or backward if
+% \emph{starred} calls -- \code{#1}) the Sankey node named \code{#3}.
+% \code{#4} is a distance. The previous position is keeped
+% by a Sankey node named \code{#3-old}.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeyadvance{sO{}mm}{%
+ %params: *(reverse), options, name, distance
+ \snk@errorifnotdefined{##3}
+ \begingroup
+ \sankeyset{##2}
+ \edef\name{##3}
+ \edef\snk@oldname{##3-old}
+ \sankeynodealias{\name}{\snk@oldname}
+ \IfBooleanTF{##1}{
+ % move backward
+ \sankeynode{
+ at={$(\snk@oldname.center)!##4!90:(\snk@oldname.left)$},
+ angle=\sankeygetnodeorient{\snk@oldname},
+ quantity=\sankeygetnodeqty{\snk@oldname},
+ name=\name,
+ }
+ \path[/sankey/fill]
+ (\name.left) -- (\snk@oldname.left)
+ -- (\snk@oldname.right) -- (\name.right) -- cycle;
+ \path[/sankey/draw]
+ (\name.left) -- (\snk@oldname.left)
+ (\snk@oldname.right) -- (\name.right);
+ }{
+ % move forward
+ \sankeynode{
+ at={$(\snk@oldname.center)!##4!-90:(\snk@oldname.left)$},
+ angle=\sankeygetnodeorient{\snk@oldname},
+ quantity=\sankeygetnodeqty{\snk@oldname},
+ name=\name,
+ }
+ \path[/sankey/fill]
+ (\snk@oldname.left) -- (\name.left)
+ -- (\name.right) -- (\snk@oldname.right) -- cycle;
+ \path[/sankey/draw]
+ (\snk@oldname.left) -- (\name.left)
+ (\name.right) -- (\snk@oldname.right);
+ }
+ \snk@show@debug{\name}
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\sankeyturnright}
+% \begin{macro}{\sankeyturnright*}
+%
+% \changes{v3.0}{2021/03/14}{new macro}
+%
+% The \code{sankeyturnright} macro moves forward the Sankey node
+% named \code{#3} by turning right. The angle is \code{#4} (the starred
+% version uses the opposite of \code{#4}). If the angle is \emph{negative}, the
+% macro calls the \code{\sankeyturnrightbackward} macro to move backward else
+% the macro fills/draws the lane between the previous position and the new
+% position. The previous position is keeped by a Sankey
+% node named \code{#3-old}.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeyturnright{sO{}mm}{
+ % *(reverse), options, name, angle
+ \snk@errorifnotdefined{##3}
+ \begingroup
+ \IfBooleanTF{##1}
+ {\edef\snk@angle{\fpeval{-1*##4}}}
+ {\edef\snk@angle{\fpeval{1*##4}}}
+ \edef\snk@anglesign{\fpeval{sign(\snk@angle)}}
+ \ifnumgreater{\snk@anglesign}{-1}{
+ \sankeyset{##2}
+ \edef\name{##3}
+ \edef\snk@oldname{##3-old}
+ \sankeynodealias{\name}{\snk@oldname}
+ \edef\qty{\sankeygetnodeqty{\name}}
+ \edef\orient{\snk@normalize@angle{\sankeygetnodeorient{\name}-\snk@angle}}
+ \snk@getpos\snk@c{$(\name.right)!-\snk@minradius!(\name.left)$}
+ \snk@getpos\pos{$(\snk@c)!1!-\snk@angle:(\name.center)$}
+ \snk@makenode{}
+ % fill the region
+ \path[/sankey/fill] let
+ \p1=(\snk@oldname.left),\p2=(\snk@oldname.right),
+ \p3=(\name.left),\p4=(\name.right),
+ \n1={\sankeyqtytolen{\qty}},
+ \n{maxr}={\snk@minradius+\n1},
+ \n{minr}={\snk@minradius}
+ in
+ (\p1) arc(\orient+\snk@angle+90:\orient+90:\n{maxr}) -- (\p3) --
+ (\p4) arc(\orient+90:\orient+\snk@angle+90:\n{minr}) -- (\p2) -- cycle;
+ % draw left and right borders
+ \path[/sankey/draw] let
+ \p1=(\snk@oldname.left),\p2=(\snk@oldname.right),
+ \p3=(\name.left),\p4=(\name.right),
+ \n1={\sankeyqtytolen{\qty}},
+ \n{maxr}={\snk@minradius+\n1},
+ \n{minr}={\snk@minradius}
+ in
+ (\p1) arc(\orient+\snk@angle+90:\orient+90:\n{maxr})
+ (\p4) arc(\orient+90:\orient+\snk@angle+90:\n{minr});
+ \snk@show@debug{\name}
+ }{
+ \sankeyturnrightbackward[##2]{##3}{-1*\snk@angle}
+ }
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\sankeyturnrightbackward}
+% \begin{macro}{\sankeyturnrightbackward*}
+%
+% \changes{v3.0}{2021/03/14}{new macro}
+%
+% The \code{sankeyturnrightbackward} macro moves backward the Sankey node
+% named \code{#3} by turning right. The angle is \code{#4} (the starred
+% version uses the opposite of \code{#4}). If the angle is \emph{negative}, the
+% macro calls the \code{\sankeyturnright} macro to move forward else
+% the macro fills/draws the lane between the previous position and the new
+% position. The previous position is keeped by a Sankey
+% node named \code{#3-old}.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeyturnrightbackward{sO{}mm}{
+ % *(reverse), options, name, angle
+ \snk@errorifnotdefined{##3}
+ \begingroup
+ \IfBooleanTF{##1}
+ {\edef\snk@angle{\fpeval{-1*##4}}}
+ {\edef\snk@angle{\fpeval{1*##4}}}
+ \edef\snk@anglesign{\fpeval{sign(\snk@angle)}}
+ \ifnumgreater{\snk@anglesign}{-1}{
+ \sankeyset{##2}
+ \edef\name{##3}
+ \edef\snk@oldname{##3-old}
+ \sankeynodealias{\name}{\snk@oldname}
+ \edef\qty{\sankeygetnodeqty{\name}}
+ \edef\orient{\snk@normalize@angle{\sankeygetnodeorient{\name}+\snk@angle}}
+ \snk@getpos\snk@c{$(\name.right)!-\snk@minradius!(\name.left)$}
+ \snk@getpos\pos{$(\snk@c)!1!\snk@angle:(\name.center)$}
+ \snk@makenode{}
+ % fill the region
+ \path[/sankey/fill] let
+ \p1=(\name.left),\p2=(\name.right),
+ \p3=(\snk@oldname.left),\p4=(\snk@oldname.right),
+ \n1={\sankeyqtytolen{\qty}},
+ \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius}
+ in
+ (\p1) arc(\orient+90:\orient-\snk@angle+90:\n{maxr}) -- (\p3) --
+ (\p4) arc(\orient-\snk@angle+90:\orient+90:\n{minr}) -- (\p2) -- cycle;
+ % draw left and right borders
+ \path[/sankey/draw] let
+ \p1=(\name.left),\p2=(\name.right),
+ \p3=(\snk@oldname.left),\p4=(\snk@oldname.right),
+ \n1={\sankeyqtytolen{\qty}},
+ \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius}
+ in
+ (\p1) arc(\orient+90:\orient-\snk@angle+90:\n{maxr})
+ (\p4) arc(\orient-\snk@angle+90:\orient+90:\n{minr});
+ \snk@show@debug{\name}
+ }{
+ \sankeyturnright[##2]{##3}{-1*\snk@angle}
+ }
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\sankeyturnleft}
+% \begin{macro}{\sankeyturnleft*}
+%
+% \changes{v3.0}{2021/03/14}{new macro}
+%
+% The \code{sankeyturnleft} macro moves forward the Sankey node
+% named \code{#3} by turning left. The angle is \code{#4} (the starred
+% version uses the opposite of \code{#4}). If the angle is \emph{negative}, the
+% macro calls the \code{\sankeyturnleftbackward} macro to move backward else
+% the macro fills/draws the lane between the previous position and the new
+% position. The previous position is keeped by a Sankey
+% node named \code{#3-old}.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeyturnleft{sO{}mm}{
+ % *(reverse), options, name, angle
+ \snk@errorifnotdefined{##3}
+ \begingroup
+ \IfBooleanTF{##1}
+ {\edef\snk@angle{\fpeval{-1*##4}}}
+ {\edef\snk@angle{\fpeval{1*##4}}}
+ \edef\snk@anglesign{\fpeval{sign(\snk@angle)}}
+ \ifnumgreater{\snk@anglesign}{-1}{
+ \sankeyset{##2}
+ \edef\name{##3}
+ \edef\snk@oldname{##3-old}
+ \sankeynodealias{\name}{\snk@oldname}
+ \edef\qty{\sankeygetnodeqty{\name}}
+ \edef\orient{\snk@normalize@angle{\sankeygetnodeorient{\name}+\snk@angle}}
+ \snk@getpos\snk@c{$(\name.left)!-\snk@minradius!(\name.right)$}
+ \snk@getpos\pos{$(\snk@c)!1!\snk@angle:(\name.center)$}
+ \snk@makenode{}
+ % fill the region
+ \path[/sankey/fill] let
+ \p1=(\snk@oldname.left),\p2=(\snk@oldname.right),
+ \p3=(\name.left),\p4=(\name.right),
+ \n1={\sankeyqtytolen{\qty}},
+ \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius}
+ in
+ (\p1) arc(\orient-\snk@angle-90:\orient-90:\n{minr}) -- (\p3) --
+ (\p4) arc(\orient-90:\orient-\snk@angle-90:\n{maxr}) -- (\p2) -- cycle;
+ % draw left and right borders
+ \path[/sankey/draw] let
+ \p1=(\snk@oldname.left),\p2=(\snk@oldname.right),
+ \p3=(\name.left),\p4=(\name.right),
+ \n1={\sankeyqtytolen{\qty}},
+ \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius}
+ in
+ (\p1) arc(\orient-\snk@angle-90:\orient-90:\n{minr})
+ (\p4) arc(\orient-90:\orient-\snk@angle-90:\n{maxr});
+ \snk@show@debug{\name}
+ }{
+ \sankeyturnleftbackward[##2]{##3}{-1*\snk@angle}
+ }
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\sankeyturnleftbackward}
+% \begin{macro}{\sankeyturnleftbackward*}
+%
+% \changes{v3.0}{2021/03/14}{new macro}
+%
+% The \code{sankeyturnleftbackward} macro moves backward the Sankey node
+% named \code{#3} by turning left. The angle is \code{#4} (the starred
+% version uses the opposite of \code{#4}). If the angle is \emph{negative}, the
+% macro calls the \code{\sankeyturnleft} macro to move forward else
+% the macro fills/draws the lane between the previous position and the new
+% position. The previous position is keeped by a Sankey
+% node named \code{#3-old}.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeyturnleftbackward{sO{}mm}{
+ % *(reverse), options, name, angle
+ \snk@errorifnotdefined{##3}
+ \begingroup
+ \IfBooleanTF{##1}
+ {\edef\snk@angle{\fpeval{-1*##4}}}
+ {\edef\snk@angle{\fpeval{1*##4}}}
+ \edef\snk@anglesign{\fpeval{sign(\snk@angle)}}
+ \ifnumgreater{\snk@anglesign}{-1}{
+ \sankeyset{##2}
+ \edef\name{##3}
+ \edef\snk@oldname{##3-old}
+ \sankeynodealias{\name}{\snk@oldname}
+ \edef\qty{\sankeygetnodeqty{\name}}
+ \edef\orient{\snk@normalize@angle{\sankeygetnodeorient{\name}-\snk@angle}}
+ \snk@getpos\snk@c{$(\name.left)!-\snk@minradius!(\name.right)$}
+ \snk@getpos\pos{$(\snk@c)!1!-\snk@angle:(\name.center)$}
+ \snk@makenode{}
+ % fill the region
+ \path[/sankey/fill] let
+ \p1=(\name.left),\p2=(\name.right),
+ \p3=(\snk@oldname.left),\p4=(\snk@oldname.right),
+ \n1={\sankeyqtytolen{\qty}},
+ \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius}
+ in
+ (\p1) arc(\orient-90:\orient+\snk@angle-90:\n{minr}) -- (\p3) --
+ (\p4) arc(\orient+\snk@angle-90:\orient-90:\n{maxr}) -- (\p2) -- cycle;
+ % draw left and right borders
+ \path[/sankey/draw] let
+ \p1=(\name.left),\p2=(\name.right),
+ \p3=(\snk@oldname.left),\p4=(\snk@oldname.right),
+ \n1={\sankeyqtytolen{\qty}},
+ \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius}
+ in
+ (\p1) arc(\orient-90:\orient+\snk@angle-90:\n{minr})
+ (\p4) arc(\orient+\snk@angle-90:\orient-90:\n{maxr});
+ \snk@show@debug{\name}
+ }{
+ \sankeyturnleft[##2]{##3}{-1*\snk@angle}
+ }
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\sankeyturn}
+% \begin{macro}{\sankeyturn*}
+%
+% \changes{v3.0}{2021/03/14}{simplification by using new \emph{turn} macros}
+%
+% The \code{\sankeyturn} macro moves toward (or backward if
+% \emph{starred} calls -- \code{#1}) the Sankey node named
+% \code{#3} by turning left (angle \code{#4} is positive)
+% or right (angle \code{#4} is negative).
+% The previous position is keeped by a Sankey node named
+% \code{#3-old}.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeyturn{sO{}mm}{%
+ % *(reverse), options, name, angle
+ \snk@errorifnotdefined{##3}
+ \begingroup
+ \edef\snk@anglesign{\fpeval{sign(##4)}}
+ \IfBooleanTF{##1}{
+ \ifnumgreater{\snk@anglesign}{-1}
+ {\sankeyturnleftbackward[##2]{##3}{##4}}
+ {\sankeyturnrightbackward[##2]{##3}{-1*##4}}
+ }{
+ \ifnumgreater{\snk@anglesign}{-1}
+ {\sankeyturnleft[##2]{##3}{##4}}
+ {\sankeyturnright[##2]{##3}{-1*##4}}
+ }
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\sankeyfork}
+%
+% The \code{\sankeyfork} macro forks the Sankey node named
+% \code{#2} to the list of subnodes given by \code{#3}.
+% The subnodes are cloned to take into account
+% the \code{debug} option.
+%
+% \begin{macrocode}
+ \NewDocumentCommand\sankeyfork{O{}mm}{%options, name, list of forks
+ \snk@errorifnotdefined{##2}
+ \begingroup
+ \sankeyset{##1}
+ \sankeynode[debug=false]{as={##2},forked={##3}}
+ \foreach \qty/\snk@subnodename in {##3}{\sankeynode{as={\snk@subnodename}}}
+ \endgroup
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\sankeyqtytolen}
+%
+% The \code{\sankeyqtytolen} macro converts quantity
+% to length using \code{\fpeval} and the ratio determined
+% by \code{\snk@totalqty} and \code{sankeytotallen}.
+%
+% \begin{macrocode}
+ \def\sankeyqtytolen##1{\fpeval{(##1)/\snk@totalqty*\snk@totallen}}
+% \end{macrocode}
+% \end{macro}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{The \protect\texttt{sankeydiagram} environment (the end)}
+%^^A % ------------------------------------------------------------
+%
+% Here is the end of the definition of the \code{sankeydiagram}
+% environment. The \code{@initial options} style and the %
+% \code{every diagram} style are applied before options provided by
+% user.
+%
+% \begin{macrocode}
+ \sankeyset{
+ @initial options,
+ every diagram,
+ % user values
+ #1}
+}
+{} % empty but mandatory ! :-)
+% \end{macrocode}
+% \end{environment}
+%
+%^^A % ------------------------------------------------------------
+% \subsection{Predefined start and end styles}
+%^^A % ------------------------------------------------------------
+%
+% The \code{none} style.
+%
+% \begin{macrocode}
+\sankeyset{
+ new start style={none}{}{},
+ new end style={none}{}{},
+}
+% \end{macrocode}
+%
+% The \code{simple} style.
+%
+% \begin{macrocode}
+\sankeyset{
+ new start style={simple}{
+ (\name.left) -- ([xshift=-.5\pgflinewidth]\name.left)
+ -- ([xshift=-.5\pgflinewidth]\name.right) -- (\name.right) -- cycle
+ }{
+ (\name.left) -- ([xshift=-.5\pgflinewidth]\name.left)
+ -- ([xshift=-.5\pgflinewidth]\name.right) -- (\name.right)
+ },
+ new end style={simple}{
+ (\name.left) -- ([xshift=2mm]\name.center)
+ -- (\name.right) -- cycle
+ }{
+ (\name.left) -- ([xshift=2mm]\name.center) -- (\name.right)
+ },
+}
+% \end{macrocode}
+%
+% The \code{arrow} style.
+%
+% \begin{macrocode}
+\sankeyset{
+ new start style={arrow}{
+ (\name.left) -- ++(-10pt,0) -- ([xshift=-10pt/6]\name.center)
+ -- ([xshift=-10pt]\name.right) -- (\name.right) -- cycle
+ }{
+ (\name.left) -- ++(-10pt,0) -- ([xshift=-10pt/6]\name.center)
+ -- ([xshift=-10pt]\name.right) -- (\name.right)
+ },
+ new end style={arrow}{
+ (\name.left) -- ([yshift=1mm]\name.left)
+ -- ([xshift=10pt]\name.center) -- ([yshift=-1mm]\name.right)
+ -- (\name.right) -- cycle
+ }{
+ (\name.left) -- ([yshift=1mm]\name.left)
+ -- ([xshift=10pt]\name.center) -- ([yshift=-1mm]\name.right)
+ -- (\name.right)
+ },
+}
+% \end{macrocode}
+% \iffalse
+%</sankey>
+% \fi
+%
+%^^A % ------------------------------------------------------------
+% \section{\texttt{tikzlibrarydubins.code.tex}}
+%^^A % ------------------------------------------------------------
+%
+% Not yet documented nor commented...
+%
+% \iffalse
+%<*tikzlibrarydubins.code.tex>
+% \fi
+% \begin{macrocode}
+\def\tikzlibrarydubins@version{v3.0}
+\def\tikzlibrarydubins@date{2021/03/14}
+
+\usetikzlibrary{calc}
+\RequirePackage{etoolbox}
+\RequirePackage{xfp}
+
+\newbool{dubinspathreverse}
+
+\def\ifpgfmathcond#1{%
+ \pgfmathparse{(#1)?1:0}%
+ \ifnumequal{\pgfmathresult}{1}%
+}
+
+
+\def\dbp@getxy#1#2#3{%
+ \tikz@scan@one@point\pgfutil@firstofone(#3)\relax%
+ \edef#1{\the\pgf@x}%
+ \edef#2{\the\pgf@y}%
+}
+
+\def\dbp@anglebetween#1#2#3{%macro, s, t
+ \dbp@getxy\dbp@ax\dbp@ay{#2}
+ \dbp@getxy\dbp@bx\dbp@by{#3}
+ \pgfmathsetmacro#1{atan2(\dbp@by-\dbp@ay,\dbp@bx-\dbp@ax)}
+}
+
+\def\dbp@distancebetween#1#2#3{%macro, s, t
+ \dbp@getxy\dbp@ax\dbp@ay{#2}
+ \dbp@getxy\dbp@bx\dbp@by{#3}
+ \edef#1{\fpeval{sqrt(%
+ (\dbp@bx-\dbp@ax)*(\dbp@bx-\dbp@ax)%
+ +(\dbp@by-\dbp@ay)*(\dbp@by-\dbp@ay)%
+ )}}%
+}
+
+\newcommand\dbp@rsr{% s, sa, t, ta, as, len, at, r
+ let
+ \p{tr}=([shift={(\dbp@angb-90:\dbp@radius pt)}]\dbp@b),
+ \n1={\dbp@anga+90},
+ \n2={\dbp@angb+90},
+ \n3={\n2+\dbp@lastangle}
+ in
+ arc(\n1:\n1-\dbp@firstangle:\dbp@rradius pt)
+ -- ([shift={(\p{tr})}]\n3:\dbp@rradius pt)
+ arc(\n3:\n2:\dbp@rradius pt)
+}
+
+\newcommand\dbp@lsl{% s, sa, t, ta, as, len, at, r
+ let
+ \p{tl}=([shift={(\dbp@angb+90:\dbp@radius pt)}]\dbp@b),
+ \n1={\dbp@anga-90},\n2={\n1+\dbp@firstangle},
+ \n3={\dbp@angb-90},\n4={\n3-\dbp@lastangle}
+ in
+ arc(\n1:\n2:\dbp@lradius pt)
+ -- ([shift={(\p{tl})}]\n4:\dbp@lradius pt)
+ arc(\n4:\n3:\dbp@lradius pt)
+}
+
+\newcommand\dbp@rsl{% s, sa, t, ta, as, len, at, r
+ let
+ \p{tl}=([shift={(\dbp@angb+90:\dbp@radius pt)}]\dbp@b),
+ \n1={\dbp@anga+90},\n2={\n1-\dbp@firstangle},
+ \n3={\dbp@angb-90},\n4={\n3-\dbp@lastangle}
+ in
+ arc(\n1:\n2:\dbp@rradius pt)
+ -- ([shift={(\p{tl})}]\n4:\dbp@lradius pt)
+ arc(\n4:\n3:\dbp@lradius pt)
+}
+
+\newcommand\dbp@lsr{% s, sa, t, ta, as, len, at, r
+ let
+ \p{tr}=([shift={(\dbp@angb-90:\dbp@radius pt)}]\dbp@b),
+ \n1={\dbp@anga-90},\n2={\n1+\dbp@firstangle},
+ \n3={\dbp@angb+90},\n4={\n3+\dbp@lastangle}
+ in
+ arc(\n1:\n2:\dbp@lradius pt)
+ -- ([shift={(\p{tr})}]\n4:\dbp@rradius pt)
+ arc(\n4:\n3:\dbp@rradius pt)
+}
+
+\newcommand\dbp@lrl{% s, sa, t, ta, as, ai, at, r
+ let
+ \n1={\dbp@anga-90},\n2={\n1+\dbp@firstangle},
+ \n3={\dbp@angb-90},\n4={\n3-\dbp@lastangle}
+ in
+ arc(\n1:\n2:\dbp@lradius pt)
+ arc(\n2+180:\n2+180-\dbp@midparam:\dbp@rradius pt)
+ arc(\n4:\n3:\dbp@lradius pt)
+}
+
+\newcommand\dbp@rlr{% s, sa, t, ta, as, ai, at, r
+ let
+ \n1={\dbp@anga+90},\n2={\n1-\dbp@firstangle},
+ \n3={\dbp@angb+90},\n4={\n3+\dbp@lastangle}
+ in
+ arc(\n1:\n2:\dbp@rradius pt)
+ arc(\n2+180:\n2+180+\dbp@midparam:\dbp@lradius pt)
+ arc(\n4:\n3:\dbp@rradius pt)
+}
+\newcommand\dbp@rev@lsl{\dbp@rsr}
+\newcommand\dbp@rev@rsr{\dbp@lsl}
+\newcommand\dbp@rev@lsr{\dbp@lsr}
+\newcommand\dbp@rev@rsl{\dbp@rsl}
+\newcommand\dbp@rev@lrl{\dbp@rlr}
+\newcommand\dbp@rev@rlr{\dbp@lrl}
+
+
+\newcommand\dubinspath[1]{%
+ \pgfextra{
+ \dubinspathset{#1}
+ \ifbool{dubinspathreverse}{
+ \edef\dbp@newa{\dbp@b}
+ \edef\dbp@newb{\dbp@a}
+ \pgfmathsetmacro\dbp@newanga{180+\dbp@angb}
+ \pgfmathsetmacro\dbp@newangb{180+\dbp@anga}
+ \edef\dbp@newfirstangle{\dbp@lastangle}
+ \edef\dbp@newlastangle{\dbp@firstangle}
+ \edef\dbp@newmethod{rev@\dbp@method}
+ \edef\dbp@newlradius{\dbp@rradius}
+ \edef\dbp@newrradius{\dbp@lradius}
+ \dubinspathset{
+ start point=\dbp@newa,
+ end point=\dbp@newb,
+ start angle=\dbp@newanga,
+ end angle=\dbp@newangb,
+ first angle=\dbp@newfirstangle,
+ last angle=\dbp@newlastangle,
+ left and right minimum radii=\dbp@newlradius pt and \dbp@newrradius pt,
+ method=\dbp@newmethod,
+ }
+ }{}
+ }
+ \csname dbp@\dbp@method\endcsname%
+}
+
+
+%% solution
+
+\def\dbp@store#1#2{%
+ \expandafter\xdef\csname dbp@store@#1@#2\endcsname%
+ {\csname dbp@#2\endcsname}%
+}
+\def\dbp@get#1#2{%
+ \csname dbp@store@#1@#2\endcsname%
+}
+
+\def\dbp@setparams#1#2#3#4#5{%
+ % method, length, fisrt angle, middle param, last angle
+ \edef\dbp@method{#1}
+ \edef\dbp@length{#2}
+ \edef\dbp@firstangle{#3}
+ \edef\dbp@middleparam{#4}
+ \edef\dbp@lastangle{#5}
+ \ifdef{\dbp@storename}{
+ \foreach \p in {method,length,firstangle,middleparam,lastangle}{
+ \dbp@store{\dbp@storename}{\p}
+ }
+ }{}
+}
+
+\def\dbp@updateparams#1#2#3#4#5{
+ \ifpgfmathcond{#2<\dbp@length}{
+ \dbp@setparams{#1}{#2}{#3}{#4}{#5}
+ }{}
+}
+
+\tikzset{
+ dubins path/.is family,
+ dubins path,
+ start point/.store in=\dbp@a,
+ start angle/.store in=\dbp@anga,
+ end point/.store in=\dbp@b,
+ end angle/.store in=\dbp@angb,
+ store/.store in=\dbp@storename,
+ use store/.style={
+ method=\dbp@get{#1}{method},
+ first angle=\dbp@get{#1}{firstangle},
+ last angle=\dbp@get{#1}{lastangle},
+ middle param=\dbp@get{#1}{middleparam},
+ },
+ minimum radius/.code={
+ \pgfmathsetmacro\dbp@radius{#1}
+ \pgfmathsetmacro\dbp@rradius{#1}
+ \pgfmathsetmacro\dbp@lradius{#1}
+ },
+ left and right minimum radii/.code args={#1 and #2}{
+ \pgfmathsetmacro\dbp@lradius{#1}
+ \pgfmathsetmacro\dbp@rradius{#2}
+ \pgfmathsetmacro\dbp@radius{(\dbp@lradius + \dbp@rradius)/2}
+ },
+ method/.store in=\dbp@method,
+ first angle/.store in=\dbp@firstangle,
+ last angle/.store in=\dbp@lastangle,
+ middle param/.store in=\dbp@midparam,
+ reverse/.is if=dubinspathreverse,
+}
+
+\newcommand\dubinspathset[1]{\tikzset{dubins path,#1}}
+
+\newcommand\dubinspathcalc[1]{%
+ \begingroup
+ \dubinspathset{#1}
+ \tikzset{
+ declare function={
+ angtodist(\dbp@a,\dbp@r)={abs(\dbp@a)*.01745329*\dbp@r};
+ modangr(\dbp@a,\dbp@b)={
+ (
+ Mod(\dbp@a,360)<Mod(\dbp@b,360)
+ ?
+ Mod(\dbp@a,360)
+ :
+ Mod(\dbp@a,360)-360)+\dbp@b-Mod(\dbp@b,360
+ )
+ };
+ modangl(\dbp@a,\dbp@b)={
+ (
+ Mod(\dbp@a,360)<Mod(\dbp@b,360)
+ ?
+ Mod(\dbp@a,360)+360
+ :
+ Mod(\dbp@a,360))+(\dbp@b)-Mod(\dbp@b,360)
+ };
+ },
+ }
+
+ \pgfmathsetmacro\dbp@radius{\dbp@rradius}
+ \pgfmathsetmacro\dbp@anga{mod((\dbp@anga)+180,360)-180}
+ \pgfmathsetmacro\dbp@angb{mod((\dbp@angb)+180,360)-180}
+ \path
+ let
+ \p{a}=(\dbp@a),
+ \p{b}=(\dbp@b),
+ \p{ar}=($(\p{a}) + (\dbp@anga-90:\dbp@radius pt)$),
+ \p{al}=($(\p{a}) + (\dbp@anga+90:\dbp@radius pt)$),
+ \p{br}=($(\p{b}) + (\dbp@angb-90:\dbp@radius pt)$),
+ \p{bl}=($(\p{b}) + (\dbp@angb+90:\dbp@radius pt)$)
+ in \pgfextra{
+ \pgfinterruptpath
+
+ % RSR (ar and br)
+ \dbp@anglebetween\dbp@rsrarbr{\p{ar}}{\p{br}}
+ \dbp@distancebetween\dbp@rsrdarbr{\p{ar}}{\p{br}}
+ \pgfmathsetmacro\dbp@rsrangone{Mod(\dbp@anga-\dbp@rsrarbr,360)}
+ \pgfmathsetmacro\dbp@rsrangtwo{Mod(\dbp@rsrarbr-\dbp@angb,360)}
+ \pgfmathsetmacro\dbp@rsrlen{\dbp@rsrdarbr}
+ \pgfmathsetmacro\dbp@rsrdist{
+ angtodist(\dbp@rsrangone,\dbp@radius)
+ +\dbp@rsrlen
+ +angtodist(\dbp@rsrangtwo,\dbp@radius)
+ }
+ \dbp@setparams{rsr}{\dbp@rsrdist}{\dbp@rsrangone}{\dbp@rsrlen}{\dbp@rsrangtwo}
+
+ % LSL (al and bl)
+ \dbp@anglebetween\dbp@lslalbl{\p{al}}{\p{bl}}
+ \dbp@distancebetween\dbp@lsldalbl{\p{al}}{\p{bl}}
+ \pgfmathsetmacro{\dbp@lslangone}{mod(\dbp@lslalbl-\dbp@anga+720,360)}
+ \pgfmathsetmacro{\dbp@lslangtwo}{mod(\dbp@angb-\dbp@lslalbl+720,360)}
+ \pgfmathsetmacro\dbp@lsllen{\dbp@lsldalbl}
+ \pgfmathsetmacro\dbp@lsldist{
+ angtodist(\dbp@lslangone,\dbp@radius)
+ +\dbp@lsllen
+ +angtodist(\dbp@lslangtwo,\dbp@radius)
+ }
+ \dbp@updateparams%
+ {lsl}{\dbp@lsldist}{\dbp@lslangone}{\dbp@lsllen}{\dbp@lslangtwo}
+
+ % RSL (ar and bl)
+ \dbp@distancebetween\dbp@rsldarbl{\p{ar}}{\p{bl}}
+ \pgfmathtruncatemacro\dbp@rslok{(\dbp@rsldarbl>=2*\dbp@radius)?1:0}
+ \ifnumequal{\dbp@rslok}{1}{
+ \dbp@anglebetween\dbp@rslarbl{\p{ar}}{\p{bl}}
+ \pgfmathsetmacro\dbp@rslanglesup{
+ asin(\dbp@radius/\dbp@rsldarbl*2)}
+ \pgfmathsetmacro\dbp@rslangone
+ {Mod(\dbp@anga-\dbp@rslarbl+\dbp@rslanglesup,360)}
+ \pgfmathsetmacro\dbp@rslangtwo
+ {Mod(\dbp@angb-\dbp@rslarbl+\dbp@rslanglesup,360)}
+ \pgfmathsetmacro\dbp@rsllen{veclen(\dbp@rsldarbl,\dbp@radius)}
+ \pgfmathsetmacro\dbp@rsldist{
+ angtodist(\dbp@rslangone,\dbp@radius)
+ +\dbp@rsllen
+ +angtodist(\dbp@rslangtwo,\dbp@radius)
+ }
+
+ \dbp@updateparams%
+ {rsl}{\dbp@rsldist}{\dbp@rslangone}{\dbp@rsllen}{\dbp@rslangtwo}
+ }{}
+
+ % LSR (al and br)
+ \dbp@distancebetween\dbp@lsrdalbr{\p{al}}{\p{br}}
+ \pgfmathtruncatemacro\dbp@lsrok{(\dbp@lsrdalbr>=2*\dbp@radius)?1:0}
+ \ifnumequal{\dbp@lsrok}{1}{
+ \dbp@anglebetween\dbp@lsralbr{\p{al}}{\p{br}}
+ \pgfmathsetmacro\dbp@lsranglesup{
+ asin(\dbp@radius/\dbp@lsrdalbr*2)}
+ \pgfmathsetmacro\dbp@lsrangone
+ {Mod(\dbp@lsralbr+\dbp@lsranglesup-\dbp@anga,360)}
+ \pgfmathsetmacro\dbp@lsrangtwo
+ {Mod(\dbp@lsralbr+\dbp@lsranglesup-\dbp@angb,360)}
+ \pgfmathsetmacro\dbp@lsrlen{veclen(\dbp@lsrdalbr,\dbp@radius)}
+ \pgfmathsetmacro\dbp@lsrdist{
+ angtodist(\dbp@lsrangone,\dbp@radius)
+ +\dbp@lsrlen
+ +angtodist(\dbp@lsrangtwo,\dbp@radius)
+ }
+ \dbp@updateparams%
+ {lsr}{\dbp@lsrdist}{\dbp@lsrangone}{\dbp@lsrlen}{\dbp@lsrangtwo}
+ }{}
+
+ % LRL (al and bl)
+ \dbp@distancebetween\dbp@lrldalbl{\p{al}}{\p{bl}}
+ \pgfmathtruncatemacro\dbp@lrlok{(\dbp@lrldalbl<=4*\dbp@radius)?1:0}
+ \ifnumequal{\dbp@lrlok}{1}{
+ \dbp@anglebetween\dbp@lrlalbl{\p{al}}{\p{bl}}
+ \pgfmathsetmacro\dbp@lrlangsup{acos(\dbp@lrldalbl/\dbp@radius/4)}
+ \pgfmathsetmacro\dbp@lrlangone{
+ modangl(\dbp@lrlalbl+\dbp@lrlangsup,\dbp@anga-90)-(\dbp@anga-90)}
+ \pgfmathsetmacro\dbp@lrlangtwo{%
+ (\dbp@angb-90)-modangr(\dbp@lrlalbl+180-\dbp@lrlangsup,\dbp@angb-90)}
+ \pgfmathsetmacro\dbp@lrlangthree{360-2*(90-\dbp@lrlangsup)}
+ \pgfmathsetmacro\dbp@lrldist{
+ angtodist(\dbp@lrlangone,\dbp@radius)
+ +angtodist(\dbp@lrlangthree,\dbp@radius)
+ +angtodist(\dbp@lrlangtwo,\dbp@radius)
+ }
+ \dbp@updateparams%
+ {lrl}{\dbp@lrldist}{\dbp@lrlangone}{\dbp@lrlangthree}{\dbp@lrlangtwo}
+ }{}
+
+ % RLR (ar and br)
+ \dbp@distancebetween\dbp@rlrdarbr{\p{ar}}{\p{br}}
+ \pgfmathtruncatemacro\dbp@rlrok{(\dbp@rlrdarbr<=4*\dbp@radius)?1:0}
+ \ifnumequal{\dbp@rlrok}{1}{
+ \dbp@anglebetween\dbp@rlrarbr{\p{ar}}{\p{br}}
+ \pgfmathsetmacro\dbp@rlrangsup{acos(\dbp@rlrdarbr/\dbp@radius/4)}
+ \pgfmathsetmacro\dbp@rlrangone{
+ (\dbp@anga+90)-modangr(\dbp@rlrarbr-\dbp@rlrangsup,\dbp@anga+90)}
+ \pgfmathsetmacro\dbp@rlrangtwo{%
+ modangl(\dbp@rlrarbr+180+\dbp@rlrangsup,\dbp@angb+90)-(\dbp@angb+90)}
+ \pgfmathsetmacro\dbp@rlrangthree{360-2*(90-\dbp@rlrangsup)}
+ \pgfmathsetmacro\dbp@rlrdist{
+ angtodist(\dbp@rlrangone,\dbp@radius)
+ +angtodist(\dbp@rlrangthree,\dbp@radius)
+ +angtodist(\dbp@rlrangtwo,\dbp@radius)
+ }
+ \dbp@updateparams%
+ {rlr}{\dbp@rlrdist}{\dbp@rlrangone}{\dbp@rlrangthree}{\dbp@rlrangtwo}
+ }{}
+
+ \endpgfinterruptpath
+ };
+ \endgroup
+}
+% \end{macrocode}
+% \iffalse
+%</tikzlibrarydubins.code.tex>
+% \fi
+%
+% \PrintChanges
+%
+% \setcounter{IndexColumns}{2}
+% \PrintIndex
+%
+% \Finale
+%
+% \iffalse
+%<*sankeydocpreamble>
+\usepackage[paper=a4paper,vmargin=1.5cm,left=4.5cm,right=3.5cm]{geometry}
+\usepackage[utf8]{inputenc}
+\usepackage{cmap}
+\usepackage[T1]{fontenc}
+\usepackage{lmodern}
+\usepackage[final,protrusion=true,expansion=true]{microtype}
+\usepackage{xcolor}
+\PassOptionsToPackage{final,colorlinks,linkcolor=red!60!orange!85!black}{hyperref}
+\usepackage[numbered]{hypdoc}
+\usepackage{fancyvrb}
+\usepackage[final]{listings}
+\usepackage{enumitem}
+\usepackage{bookmark}
+\usepackage{siunitx}
+\usepackage{footnote}
+\usepackage{etoc}
+\usepackage{accsupp}
+\usepackage{tikz}
+\usetikzlibrary{positioning,patterns.meta,fit}
+\usepackage[british]{babel}
+\usepackage{varioref}
+\usepackage{embedfile}
+\usepackage{dtx-attach}
+\embedfile[mimetype=text/plain]{sankey.ins}
+\usepackage{sankey}
+
+\colorlet{bgcode}{yellow!50!gray!5}
+\colorlet{keyword}{blue!50!cyan!50!black}
+\colorlet{comment}{red!75!black}
+
+\newcommand\emptyaccsupp[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}}
+
+\lstset{
+ literate=
+ {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ú}{{\'u}}1
+ {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1
+ {à}{{\`a}}1 {è}{{\`e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1
+ {À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1
+ {ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1
+ {Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1
+ {â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1
+ {Â}{{\^A}}1 {Ê}{{\^E}}1 {Î}{{\^I}}1 {Ô}{{\^O}}1 {Û}{{\^U}}1
+ {œ}{{\oe}}1 {Œ}{{\OE}}1 {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1
+ {ç}{{\c c}}1 {Ç}{{\c C}}1 {ø}{{\o}}1 {å}{{\r a}}1 {Å}{{\r A}}1
+ {€}{{\texteuro}}1 {£}{{\pounds}}1 {°}{{\degres}}1
+ {’}{{\textquoteright}}1 {‘}{{\textquoteleft}}1
+ {«}{{<<}}1 {»}{{>>}}1
+ {—}{{---}}1 {−}{{$-$}}1
+ {\^\^A}{{}}0 % verbatim in .dtx file
+}
+
+\lstset{
+ fancyvrb=true,
+ escapechar=`,
+ extendedchars=true,
+ fontadjust=true,
+ columns=fullflexible,
+ flexiblecolumns=true,
+ inputencoding=utf8,
+ keepspaces=true,
+ backgroundcolor=\color{bgcode},
+ basicstyle=\mdseries\ttfamily,
+ keywordstyle=\color{keyword},
+ stringstyle=\ttfamily\color{green!50!black},
+ commentstyle=\color{comment}\itshape,
+ emphstyle=\bfseries\color{red},
+ numbersep=5pt,
+ %numbers=left,
+ numberstyle=\tiny\emptyaccsupp,
+ showstringspaces=false,
+ upquote=true,
+ aboveskip=.5\parskip,
+ belowskip=.5\parskip,
+ framexleftmargin=1pt,
+ framexrightmargin=1pt,
+ gobble=2, % \lstlisting code in .dtx
+}
+
+\lstdefinestyle{textsmall}{basicstyle=\color{black}\small\mdseries\ttfamily}
+\lstdefinestyle{textfootnotesize}{basicstyle=\color{black}\footnotesize\mdseries\ttfamily}
+\lstdefinestyle{textscriptsize}{basicstyle=\color{black}\scriptsize\mdseries\ttfamily}
+\lstdefinestyle{texttiny}{basicstyle=\color{black}\tiny\mdseries\ttfamily}
+
+\lstdefinestyle{LaTeX}{
+ language=[LaTeX]TeX,
+ moretexcs={
+ Lab,
+ LabSet,
+ Qty,
+ QtySet,
+ colorlet,
+ coordinate,
+ countries,
+ country,
+ countryname,
+ definecolor,
+ draw,
+ endcountry,
+ fill,
+ foreach,
+ hashband,
+ hdist,
+ hwidth,
+ node,
+ nodename,
+ path,
+ sankeyadvance,
+ sankeydubins,
+ sankeyend,
+ sankeyend,
+ sankeyfork,
+ sankeynode,
+ sankeynodealias,
+ sankeynodeend,
+ sankeynodestart,
+ sankeyoutin,
+ sankeyset,
+ sankeystart,
+ sankeyturn,
+ sankeyturnleft,
+ sankeyturnleftbackward,
+ sankeyturnright,
+ sankeyturnrightbackward,
+ sisetup,
+ startcountry,
+ tikzset,
+ turnandstop,
+ usepackage,
+ vdist,
+ }
+}
+\lstdefinestyle{LaTeXsmall}{style=LaTeX,style=textsmall}
+\lstdefinestyle{LaTeXfootnotesize}{style=LaTeX,style=textfootnotesize}
+\lstdefinestyle{LaTeXscriptsize}{style=LaTeX,style=textscriptsize}
+\lstdefinestyle{LaTeXtiny}{style=LaTeX,style=texttiny}
+
+\def\code{\lstinline[basicstyle=\mdseries\ttfamily\color{red!50!black}]}
+
+\edef\samplecodename{\jobname-code.vrb}
+
+\newcommand\constant[1]{\textcolor{violet}{\texttt{#1}}}
+\newcommand\ARG[1]{\texttt{\{#1\}}}
+\newcommand\OPTARG[1]{\textcolor{green!50!black}{\texttt{[#1]}}}
+\newcommand\VAR[1]{\textit{\texttt{\ensuremath{\langle}#1\ensuremath{\rangle}}}}
+\newcommand\NOTE[1]{\leavevmode\marginpar{#1}}
+
+\def\mynobreakpar{\par\nobreak\@afterheading}
+\def\docprefix#1{\texttt{\textcolor{gray}{#1}}}
+\def\sankeykeysprefix{/sankey}
+
+\newenvironment{sankeyoption}[5][]{% [prefix] key, val, default, initially
+ \begingroup
+ %
+ \def\keypath{#1}%
+ \def\key{#2}%
+ \def\val{#3}%
+ \def\default{#4}%
+ \def\initially{#5}%
+ %\setlength\parindent{\dimexpr.5\parindent\relax}%
+ % \vspace{.25\baselineskip plus .25\baselineskip minus 0mm}
+ \parfillskip 0pt plus 1fil%
+ \leavevmode%
+ \ttfamily%
+ \hspace*{-1cm}%
+ \textcolor{red!75!black}{\texttt{\docprefix{\ifdefempty{\keypath}{\sankeykeysprefix/}{\keypath/}}\key}}%
+ \ifdefempty{\val}{}{=\val}%
+ \hfill%
+ \ifdefempty{\default}{\null}{(default:\,\constant{\default})}%
+ \ifdefempty{\initially}{\null}{(initially:\,\constant{\initially})}%
+ \mynobreakpar%
+ \endgroup%
+ \parskip=.5\baselineskip plus .25\baselineskip minus .25\baselineskip
+ \parfillskip=30pt plus 1fil
+ \itemize[topsep=0pt,partopsep=0pt,itemsep=0pt]\item[]
+}{%
+ \enditemize%
+}
+
+\newcommand\MACRO{\hspace*{-1cm}}
+
+\newlist{sankeyconstantsdesc}{description}{1}
+\setlist[sankeyconstantsdesc]{align=right,labelindent=1.5em,labelsep=.5em,leftmargin=!,font=\normalfont}
+
+\newlength{\myparskip}
+\setlength{\myparskip}{.75\baselineskip plus 8\baselineskip minus .25\baselineskip}
+\usepackage[skip=\myparskip]{parskip}
+\newenvironment{miniblock}{%
+ \vspace{.5\parskip}%
+}{%
+}
+
+\tikzset{
+ every picture/.style={
+ execute at end picture={
+ \begin{pgfonlayer}{background}
+ \node[fit=(current bounding box),inner sep=0](bb){};
+ \def\rs{5mm}
+ \draw[gray!25] let
+ \p{sw}=(bb.south west), \p{ne}=(bb.north east),
+ \n{maxx}={ceil(\x{ne}/\rs)*\rs}, \n{minx}={floor(\x{sw}/\rs)*\rs},
+ \n{maxy}={ceil(\y{ne}/\rs)*\rs}, \n{miny}={floor(\y{sw}/\rs)*\rs}
+ in (\n{minx},\n{miny}) grid (\n{maxx},\n{maxy});
+ \begin{scope}[overlay]
+ \draw[gray!50,-latex] let
+ \p{sw}=(bb.south west), \p{ne}=(bb.north east),
+ \n{maxx}={ceil(\x{ne}/\rs)*\rs}, \n{minx}={floor(\x{sw}/\rs)*\rs},
+ \n{maxy}={ceil(\y{ne}/\rs)*\rs}, \n{miny}={floor(\y{sw}/\rs)*\rs}
+ in (\n{minx},0) -- (\n{maxx}+1mm,0);
+ \draw[gray!50,-latex] let
+ \p{sw}=(bb.south west), \p{ne}=(bb.north east),
+ \n{maxx}={ceil(\x{ne}/\rs)*\rs}, \n{minx}={floor(\x{sw}/\rs)*\rs},
+ \n{maxy}={ceil(\y{ne}/\rs)*\rs}, \n{miny}={floor(\y{sw}/\rs)*\rs}
+ in (0,\n{miny}) -- (0,\n{maxy}+1mm);
+ \end{scope}
+ \end{pgfonlayer}
+ }
+ }
+}
+
+\def\MacroFont{
+ \fontencoding\encodingdefault
+ \fontfamily\ttdefault
+ \fontseries\mddefault
+ \fontshape\shapedefault
+ \footnotesize%
+}
+%</sankeydocpreamble>
+% \fi
+\endinput
+
+% Local Variables:
+% mode: doctex
+% LaTeX-verbatim-macros-with-braces-local: ("code")
+% TeX-master: t
+% End:
diff --git a/graphics/pgf/contrib/sankey/sankey.ins b/graphics/pgf/contrib/sankey/sankey.ins
new file mode 100644
index 0000000000..ab11ca1dc1
--- /dev/null
+++ b/graphics/pgf/contrib/sankey/sankey.ins
@@ -0,0 +1,85 @@
+%%
+%% Copyright (C) 2016, 2021 by Paul Gaborit
+%%
+%% 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 Paul Gaborit.
+%%
+%% This work consists of the files sankey.dtx, sankey.ins and the derived
+%% files sankey.sty, tikzlibrarydubins.code.tex, sankey-doc-preamble.sty,
+%% sankey-example1.tex, sankey-example2.tex, sankey-example3.tex,
+%% sankey-example3-variation.tex, sankey-example4.tex,
+%% sankey-example-energy.tex
+%%
+
+\input docstrip.tex
+\keepsilent
+
+\usedir{tex/latex/sankey}
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2016, 2021 by Paul Gaborit
+
+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 Paul Gaborit.
+
+This work consists of the files sankey.dtx, sankey.ins and the derived
+files sankey.sty, tikzlibrarydubins.code.tex, sankey-doc-preamble.sty,
+sankey-example1.tex, sankey-example2.tex, sankey-example3.tex,
+sankey-example3-variation.tex, sankey-example4.tex,
+sankey-example-energy.tex
+
+\endpreamble
+
+\generate{%
+ \askforoverwritefalse
+ \file{sankey.sty}{\from{sankey.dtx}{sankey}}%
+ \file{tikzlibrarydubins.code.tex}{\from{sankey.dtx}{tikzlibrarydubins.code.tex}}%
+ \file{sankey-example-energy.tex}{\nopreamble\nopostamble\from{sankey.dtx}{example-energy}}%
+ \file{sankey-example1.tex}{\nopreamble\nopostamble\from{sankey.dtx}{example1}}%
+ \file{sankey-example2.tex}{\nopreamble\nopostamble\from{sankey.dtx}{example2}}%
+ \file{sankey-example3.tex}{\nopreamble\nopostamble\from{sankey.dtx}{example3}}%
+ \file{sankey-example3-variation.tex}{\nopreamble\nopostamble\from{sankey.dtx}{example3-variation}}%
+ \file{sankey-example4.tex}{\nopreamble\nopostamble\from{sankey.dtx}{example4}}%
+ \file{sankey-doc-preamble.sty}{\from{sankey.dtx}{sankeydocpreamble}}%
+}
+
+\Msg{*********************************************************}
+\Msg{*}
+\Msg{* To finish the installation you have to move the}
+\Msg{* following file into a directory searched by TeX:}
+\Msg{*}
+\Msg{* \space\space sankey.sty}
+\Msg{* \space\space tikzlibrarydubins.code.tex}
+\Msg{*}
+\Msg{* To produce the documentation run the file sankey.dtx}
+\Msg{* through (pdf)LaTeX.}
+\Msg{*}
+\Msg{* Happy TeXing!}
+\Msg{*********************************************************}
+
+\endbatchfile \ No newline at end of file
diff --git a/graphics/pgf/contrib/sankey/sankey.pdf b/graphics/pgf/contrib/sankey/sankey.pdf
new file mode 100644
index 0000000000..f1b0fbf2df
--- /dev/null
+++ b/graphics/pgf/contrib/sankey/sankey.pdf
Binary files differ
diff --git a/graphics/pgf/contrib/sankey/sankey.sty b/graphics/pgf/contrib/sankey/sankey.sty
deleted file mode 100644
index 4c28a1fe0d..0000000000
--- a/graphics/pgf/contrib/sankey/sankey.sty
+++ /dev/null
@@ -1,722 +0,0 @@
-% Copyright (C) 2016-2021 by Paul Gaborit
-%
-% This file may be distributed and/or modified
-%
-% 1. under the LaTeX Project Public License and/or
-%
-% 2. under the GNU Public License.
-
-\def\sankey@version{2.0}
-\def\sankey@date{2021/01/27}
-\ProvidesPackage{sankey}[\sankey@date\space\sankey@version\space sankey package]
-
-\RequirePackage{xparse}
-\RequirePackage{xfp}
-\RequirePackage{tikz}
-\usetikzlibrary{calc,decorations.markings,dubins}
-\usepackage{etoolbox}
-
-% add a new layer to debug sankey diagrams
-\pgfdeclarelayer{background}
-\pgfdeclarelayer{foreground}
-\pgfdeclarelayer{sankeydebug}
-\pgfsetlayers{background,main,foreground,sankeydebug}
-
-% flag to debug sankey diagrams
-\newtoggle{sankey debug}
-\newtoggle{sankey node start}
-\newtoggle{sankey node end}
-
-% macros to store and to retrieve the orientation and the quantity
-% associated with each sankey node
-
-\def\sankeysetnodeqty#1#2{\expandafter\xdef\csname sankey@node@#1@qty\endcsname{#2}}
-
-\def\sankeygetnodeqty#1{%
- \ifcsmacro{sankey@node@#1@qty}{%
- \csname sankey@node@#1@qty\endcsname%
- }{%
- \PackageWarning{sankey}{Unknown sankey node '#1'}%
- }%
-}
-
-\def\sankeysetnodeorient#1#2{\expandafter\xdef\csname sankey@node@#1@orient\endcsname{#2}}
-
-\def\sankeygetnodeorient#1{%
- \ifcsmacro{sankey@node@#1@orient}{%
- \csname sankey@node@#1@orient\endcsname%
- }{%
- \PackageWarning{sankey}{Unknown sankey node '#1'}%
- }%
-}
-
-\def\sankeysetstartfill#1#2{\expandafter\gdef\csname sankey@start@fill@#1\endcsname{#2}}
-\def\sankeysetstartdraw#1#2{\expandafter\gdef\csname sankey@start@draw@#1\endcsname{#2}}
-\def\sankeysetendfill#1#2{\expandafter\gdef\csname sankey@end@fill@#1\endcsname{#2}}
-\def\sankeysetenddraw#1#2{\expandafter\gdef\csname sankey@end@draw@#1\endcsname{#2}}
-%
-\def\sankeygetstartfill#1{\csname sankey@start@fill@#1\endcsname}
-\def\sankeygetstartdraw#1{\csname sankey@start@draw@#1\endcsname}
-\def\sankeygetendfill#1{\csname sankey@end@fill@#1\endcsname}
-\def\sankeygetenddraw#1{\csname sankey@end@draw@#1\endcsname}
-
-% new shape
-\pgfdeclareshape{sankey node}{
- \inheritsavedanchors[from=rectangle]
- \inheritanchor[from=rectangle]{center}
- %\inheritanchorborder[from=rectangle]
- \anchor{left}{\pgf@process{\northeast}}
- \anchor{right}{\pgf@process{\southwest}}
-}
-
-% pgfkeys family 'sankey'
-\pgfkeys{/sankey/.is family}
-
-\NewDocumentCommand\sankeyset{m}{\pgfkeys{sankey,#1}}
-
-\sankeyset{
- ratio length/.code={
- \pgfmathsetmacro\sankeytotallen{#1}
- \edef\sankeytotallen{\sankeytotallen pt}
- },
- ratio length/.value required,
- ratio quantity/.code={\edef\sankeytotalqty{\fpeval{#1}}},
- ratio quantity/.value required,
- ratio/.style args={#1/#2}{
- ratio length=#1,
- ratio quantity=#2,
- },
- ratio/.value required,
- minimum radius/.estore in=\sankeyminradius,
- minimum radius/.value required,
- outin steps/.estore in=\sankeystepoutin,
- outon steps/.value required,
- %
- debug/.is choice,
- debug/true/.code={\toggletrue{sankey debug}},
- debug/false/.code={\togglefalse{sankey debug}},
- debug/.default=true,
- %
- start style/.is choice,
- %
- end style/.is choice,
- % default values
- default parameters/.style={
- % default values
- ratio=1cm/10,
- minimum radius=5mm,%
- outin steps=10,
- debug=false,
- start style=none,
- end style=none,
- },
- % to make node
- node parameters/.style={
- quantity/.code={%
- %\typeout{quantity=##1}%
- \edef\qty{\fpeval{##1}}%
- %\typeout{qty=\qty}%
- },
- quantity/.value required,
- angle/.code={%
- %\typeout{angle:##1}%
- \pgfmathsetmacro\orient{##1}%
- },
- angle/.value required,
- name/.store in=\name,
- name/.value required,
- at/.store in=\pos,
- at/.value required,
- as/.style={
- name=##1,
- quantity=\sankeygetnodeqty{##1},
- angle=\sankeygetnodeorient{##1},
- at={##1.center},
- },
- as/.value required,
- %
- anchor/.is choice,
- anchor/left/.code={\def\sankeyanchor{left}},
- anchor/right/.code={\def\sankeyanchor{right}},
- anchor/center/.code={\def\sankeyanchor{center}},
- anchor=center,
- %
- start/.is choice,
- start/true/.code={\toggletrue{sankey node start}},
- start/false/.code={\togglefalse{sankey node start}},
- start/.default=true,
- start=false,
- %
- end/.is choice,
- end/true/.code={\toggletrue{sankey node end}},
- end/false/.code={\togglefalse{sankey node end}},
- end/.default=true,
- end=false,
- },
-}
-
-% some styles
-\sankeyset{
- node/.style={
- shape=sankey node,
- inner sep=0,minimum height={\sankeyqtytolen{#1}},
- minimum width=0,draw=none,line width=0pt,
- node contents={},
- },
- fill/.style={line width=0pt,fill=white},
- draw/.style={draw=black,line width=.4pt},
- % debug color used by all debug macros
- debug color/.style={/utils/exec={\colorlet{debug color}{#1}}},
- debug color=red!75!black,
- % debug line between left and right anchors
- debug line/.style={draw=debug color,|-|},
- % debug line between center and label
- debug normal/.style={draw=debug color},
- % debug node label
- debug label/.style={
- draw,
- font=\ttfamily\tiny,
- text=debug color,text opacity=1,
- inner sep=.1em,
- fill=white,fill opacity=1,
- rounded corners=.1em,
- },
-}
-
-\sankeyset{
- new start style/.code n args={3}{% name, fill path, draw path
- \sankeysetstartfill{#1}{#2}
- \sankeysetstartdraw{#1}{#3}
- \sankeyset{start style/#1/.code={\def\sankeystartstyle{#1}}}
- },
- new end style/.code n args={3}{% name, fill path, draw path
- \sankeysetendfill{#1}{#2}
- \sankeysetenddraw{#1}{#3}
- \sankeyset{end style/#1/.code={\def\sankeyendstyle{#1}}}
- },
-}
-
-% the new 'sankeydiagram' environment
-\NewDocumentEnvironment{sankeydiagram}{O{}+b}{
-
- \newcommand\sankeyarc[2]{% sn, en
- \begingroup
- \pgfmathsetmacro\startangle{\sankeygetnodeorient{##1}}
- \pgfmathsetmacro\endangle{\sankeygetnodeorient{##2}}
- \pgfmathsetmacro\rotateangle{\endangle-\startangle}
- \pgfmathtruncatemacro\acwrotate{\rotateangle>0?1:0}
- \path let
- \p1=(##1.left),\p2=(##1.right),
- \p3=(##2.left),\p4=(##2.right),
- \n1={\sankeyqtytolen{\sankeygetnodeqty{##1}}},
- \n{maxr}={\sankeyminradius+\n1},
- \n{minr}={\sankeyminradius}
- in \pgfextra{
- \ifnumequal{\acwrotate}{1}{
- \begin{pgfinterruptpath}
- % fill the region
- \path[/sankey/fill]
- (\p1) arc(\startangle-90:\endangle-90:\n{minr}) -- (\p3) --
- (\p4) arc(\endangle-90:\startangle-90:\n{maxr}) -- (\p2) -- cycle;
- % draw left and right borders
- \path[/sankey/draw]
- (\p1) arc(\startangle-90:\endangle-90:\n{minr})
- (\p4) arc(\endangle-90:\startangle-90:\n{maxr});
- \end{pgfinterruptpath}
- }{
- \begin{pgfinterruptpath}
- % fill the region
- \path[/sankey/fill]
- (\p1) arc(\startangle+90:\endangle+90:\n{maxr}) -- (\p3) --
- (\p4) arc(\endangle+90:\startangle+90:\n{minr}) -- (\p2) -- cycle;
- % draw left and right borders
- \path[/sankey/draw]
- (\p1) arc(\startangle+90:\endangle+90:\n{maxr})
- (\p4) arc(\endangle+90:\startangle+90:\n{minr});
- \end{pgfinterruptpath}
- }
- };
- \endgroup
- }
-
- \newcommand\sankeymakenodenodebug{
- \begingroup
- \sankeysetnodeqty{\name}{\qty}
- \sankeysetnodeorient{\name}{\orient}
- % \typeout{\qty,\orient}
- \ifundef{\sankeyanchor}{\def\sankeyanchor{center}}{}
- \node[/sankey/node=\qty,rotate=\orient,at/.expanded={(\pos)},name=\name,anchor=\sankeyanchor];
- \endgroup
- }
-
- \newcommand\sankeymakenode{
- \begingroup
- \sankeymakenodenodebug{}
- \iftoggle{sankey debug}{
- \begin{pgfonlayer}{sankeydebug}
- \pgfset{
- number format/relative*=-1,
- number format/precision=1,
- number format/fixed,
- }
- \path[/sankey/debug line] (\name.left) -- (\name.right);
- \pgfmathsetmacro{\len}{\sankeyqtytolen{\qty}/3}
- \path[/sankey/debug normal] (\name.center)
- -- ($(\name.center)!\len pt!90:(\name.right)$)
- node[/sankey/debug label,rotate=\orient+90,anchor=north] {\name:\pgfmathprintnumber{\qty}};
- \end{pgfonlayer}
- }{}
- \endgroup
- }
-
- \newcommand\sankeynodenodebug[1]{
- \begingroup
- \sankeyset{node parameters,##1}
- %\typeout{sankeynodenodebug: '\name' at(\pos) angle(\orient) qty(\qty)}
- \sankeymakenodenodebug{}
- \endgroup
- }
-
- % ============================================================
- % user commands
- % ============================================================
-
- \NewDocumentCommand\sankeydubins{O{}mm}{% options, sn, en
- \begingroup
- \sankeyset{##1}
- \pgfmathsetmacro\startangle{\sankeygetnodeorient{##2}}
- \pgfmathsetmacro\endangle{\sankeygetnodeorient{##3}}
- \edef\sqty{\sankeygetnodeqty{##2}}
- \edef\eqty{\sankeygetnodeqty{##3}}
- \ifdefstrequal{\sqty}{\eqty}{}{
- \PackageError{sankey}%
- {^^J*** \string\sankeyoutin: quantities differ between ##2 (\sqty) and ##3 (\eqty)^^J}%
- {The quantities of the two Sankey nodes must be equal.}
- }
- \pgfmathsetmacro\qty{\sankeygetnodeqty{##2}}
- \pgfmathsetmacro\width{\sankeyqtytolen{\qty}}
- %\typeout{startangle:\startangle,endangle:\endangle,qty:\qty,width:\width}
- \dubinspathset{
- sankey/.style={
- start point=##2.center,start angle=\startangle,
- end point=##3.center,end angle=\endangle,
- minimum radius=\sankeyminradius + .5 * \width pt,
- },
- }
- \dubinspathcalc{sankey,store=sankey}
-
- \dubinspathset{
- left border/.style={
- sankey, use store=sankey,
- left and right minimum radii=
- {\sankeyminradius} and {\sankeyminradius + \width pt},
- },
- right border/.style={
- sankey, use store=sankey,
- left and right minimum radii=
- {\sankeyminradius + \width pt} and {\sankeyminradius},
- },
- }
-
- \path let
- \p1=(##2.left),\p2=(##2.right),
- \p3=(##3.left),\p4=(##3.right)
- in \pgfextra{
- \begin{pgfinterruptpath}
- % fill the region
- \path[/sankey/fill]
- (\p1)
- \dubinspath{left border}
- -- (\p3) --
- (\p4) \dubinspath{right border,reverse}
- -- (\p2) -- cycle;
-
- % draw left and right borders
- \path[/sankey/draw]
- (\p1)
- \dubinspath{left border}
- (\p2)
- \dubinspath{right border}
- ;
- \end{pgfinterruptpath}
- };
- \endgroup
- }
-
-
- \NewDocumentCommand\sankeyoutin{O{}mm}{% options, sn, en
- \begingroup
- \sankeyset{##1}
- \edef\sn{##2}
- \edef\en{##3}
- \edef\sqty{\sankeygetnodeqty{\sn}}
- \edef\eqty{\sankeygetnodeqty{\en}}
- \ifdefstrequal{\sqty}{\eqty}{}{
- \PackageError{sankey}%
- {^^J*** \string\sankeyoutin: quantities differ between \sn (\sqty) and \en (\eqty)^^J}%
- {The quantities of the two Sankey nodes must be equal.}
- }
- %\typeout{*** sankeyoutin: \sn\space to \en\space (\sankeystepoutin)}
- \pgfmathsetmacro\qty{\sankeygetnodeqty{\sn}}
- \pgfmathsetmacro\mylength{\sankeyqtytolen{\qty}/2}
- \pgfmathsetmacro\mystep{1/\sankeystepoutin}
- %\typeout{*** a}
- \pgfmathsetmacro\mybound{1-.5*\mystep}
- %\typeout{*** b}
- \pgfmathsetmacro\laststep{int(\sankeystepoutin-1)}
- %\typeout{sankeystepoutin(\sankeystepoutin) mystep(\mystep) mybound(\mybound) laststep(\laststep)}
- %\typeout{*** sankeyoutin: \startangle to \endangle}
- \path[decorate,overlay,decoration={
- markings,
- mark=between positions \mystep and \mybound step \mystep with {
- \def\sankeyoutinmidptname{sankeyoutinmidpt \pgfkeysvalueof{/pgf/decoration/mark info/sequence number}}
- \path
- (0,0) coordinate(\sankeyoutinmidptname)
- (0,-\mylength pt) coordinate (\sankeyoutinmidptname\space r)
- (0,\mylength pt) coordinate (\sankeyoutinmidptname\space l)
- ;
- }
- }](\sn.center) to[out=\sankeygetnodeorient{\sn},in=\sankeygetnodeorient{\en}+180] (\en.center);
- \foreach \myptnum in {1,...,\laststep}{
- \def\sankeyoutinmidptname{sankeyoutinmidpt \myptnum}
- \anglebetween\sankeyoutinmidptangle{\sankeyoutinmidptname\space r}{\sankeyoutinmidptname\space l}
- \sankeynodenodebug{quantity=\qty,angle=\sankeyoutinmidptangle-90,name=\sankeyoutinmidptname,at=\sankeyoutinmidptname}
- }
- \sankeynodenodebug{quantity=\sankeygetnodeqty{\sn},angle=\sankeygetnodeorient{\sn},name={sankeyoutinmidpt 0},at={\sn}}
- \sankeynodenodebug{quantity={\sankeygetnodeqty{\en}},angle={\sankeygetnodeorient{\en}},name={sankeyoutinmidpt \sankeystepoutin},at={\en}}
-
- %\typeout{*********************}
- \path[/sankey/fill,looseness=1]
- (sankeyoutinmidpt 0.left)
- \foreach \curpt[remember=\curpt as \prevpt (initially 0)] in {1,...,\sankeystepoutin}{
- to[out=\sankeygetnodeorient{sankeyoutinmidpt \prevpt},in=\sankeygetnodeorient{sankeyoutinmidpt \curpt}+180]
- (sankeyoutinmidpt \curpt.left)
- }
- --
- (sankeyoutinmidpt \sankeystepoutin.right)
- \foreach \curpt[remember=\curpt as \prevpt (initially \sankeystepoutin)] in {\laststep,...,0}{
- to[out=\sankeygetnodeorient{sankeyoutinmidpt \prevpt}+180,in=\sankeygetnodeorient{sankeyoutinmidpt \curpt}]
- (sankeyoutinmidpt \curpt.right)
- }
- -- cycle;
-
- \path[/sankey/draw,looseness=1]
- (sankeyoutinmidpt 0.left)
- \foreach \curpt[remember=\curpt as \prevpt (initially 0)] in {1,...,\sankeystepoutin}{
- to[out=\sankeygetnodeorient{sankeyoutinmidpt \prevpt},in=\sankeygetnodeorient{sankeyoutinmidpt \curpt}+180]
- (sankeyoutinmidpt \curpt.left)
- }
- %
- (sankeyoutinmidpt \sankeystepoutin.right)
- \foreach \curpt[remember=\curpt as \prevpt (initially \sankeystepoutin)] in {\laststep,...,0}{
- to[out=\sankeygetnodeorient{sankeyoutinmidpt \prevpt}+180,in=\sankeygetnodeorient{sankeyoutinmidpt \curpt}]
- (sankeyoutinmidpt \curpt.right)
- }
- ;
-
- \endgroup
- }
-
- \NewDocumentCommand\sankeynodealias{mm}{%name, alias
- \path [late options={name=##1,alias=##2}];
- \sankeysetnodeqty{##2}{\sankeygetnodeqty{##1}}
- \sankeysetnodeorient{##2}{\sankeygetnodeorient{##1}}
- }
-
- \newcommand\sankeynode[2][]{
- \begingroup
- \sankeyset{##1}
- \sankeyset{node parameters,##2}
- %\typeout{sankeynode: '\name' at(\pos) angle(\orient) qty(\qty)}
- \sankeymakenode{}
- \endgroup
- }
-
- \def\sankeyfilldrawstart{
- \begin{scope}[shift={(\name)},rotate=\orient]
- \path[/sankey/fill] \sankeygetstartfill{\sankeystartstyle};
- \path[/sankey/draw] \sankeygetstartdraw{\sankeystartstyle};
- \end{scope}
- }
-
- \NewDocumentCommand\sankeystart{O{}m}{
- \begingroup
- \sankeyset{##1}
- \edef\name{##2}
- \edef\orient{\sankeygetnodeorient{##2}}
- \edef\qty{\sankeygetnodeqty{##2}}
- \sankeyfilldrawstart
- \endgroup
- }
-
- \NewDocumentCommand\sankeynodestart{O{}m}{
- \begingroup
- %\typeout{sankeynodestart: ##2}
- \sankeyset{##1}
- \sankeyset{node parameters,##2}
- %\typeout{sankeynodestart: '\name' at(\pos) angle(\orient) qty(\qty)}
- \sankeymakenode{}
- %\typeout{sankeynodestart: sankeynode ok}
- %\typeout{sankeynodestart: '\name' at(\pos) angle(\orient) qty(\qty)}
- \sankeyfilldrawstart
- \endgroup
- }
-
- \def\sankeyfilldrawend{
- \begin{scope}[shift={(\name)},rotate=\sankeygetnodeorient{\name}]
- \path[/sankey/fill] \sankeygetendfill{\sankeyendstyle};
- \path[/sankey/draw] \sankeygetenddraw{\sankeyendstyle};
- \end{scope}
- }
-
- \NewDocumentCommand\sankeyend{O{}m}{%name
- \begingroup
- \sankeyset{##1}
- \edef\name{##2}
- \edef\orient{\sankeygetnodeorient{##2}}
- \edef\qty{\sankeygetnodeqty{##2}}
- \sankeyfilldrawend
- \endgroup
- }
-
- \NewDocumentCommand\sankeynodeend{O{}m}{
- \begingroup
- %\typeout{sankeynodestart: ##2}
- \sankeyset{##1}
- \sankeyset{node parameters,##2}
- %\typeout{sankeynodestart: '\name' at(\pos) angle(\orient) qty(\qty)}
- \sankeymakenode{}
- %\typeout{sankeynodestart: sankeynode ok}
- %\typeout{sankeynodestart: '\name' at(\pos) angle(\orient) qty(\qty)}
- \sankeyfilldrawend
- \endgroup
- }
-
-
-
- \NewDocumentCommand\sankeyadvance{sO{}mm}{% *(reverse), options, name, distance
- \begingroup
- \sankeyset{##2}
- \def\newname{##3}
- \def\oldname{##3-old}
- \sankeynodealias{\newname}{\oldname}
- % \typeout{*** sankeyadvance: ok (\oldname => \newname)}
- \IfBooleanTF{##1}{
- % reverse advance
- \sankeynode{
- at={$(\oldname.center)!##4!90:(\oldname.left)$},
- angle=\sankeygetnodeorient{\oldname},
- quantity=\sankeygetnodeqty{\oldname},
- name=\newname,
- }
- \path[/sankey/fill]
- (\newname.left) -- (\oldname.left)
- --
- (\oldname.right) -- (\newname.right)
- -- cycle;
- \path[/sankey/draw]
- (\newname.left) -- (\oldname.left)
- (\oldname.right) -- (\newname.right);
- \endgroup
- }{
- % advance
- \sankeynode{
- at={$(\oldname.center)!##4!-90:(\oldname.left)$},
- angle=\sankeygetnodeorient{\oldname},
- quantity=\sankeygetnodeqty{\oldname},
- name=\newname,
- }
- \path[/sankey/fill]
- (\oldname.left) -- (\newname.left)
- --
- (\newname.right) -- (\oldname.right)
- -- cycle;
- \path[/sankey/draw]
- (\oldname.left) -- (\newname.left)
- (\newname.right) -- (\oldname.right);
- \endgroup
- }
- }
-
- \NewDocumentCommand\sankeyturn{sO{}mm}{% *(reverse), options, name, angle
- \begingroup
- \sankeyset{##2}
- \def\name{##3}
- \def\oldname{##3-old}
- \sankeynodealias{\name}{\oldname}
- \pgfmathsetmacro\qty{\sankeygetnodeqty{\oldname}}
- \pgfmathsetmacro\oldangle{\sankeygetnodeorient{\oldname}}
- \IfBooleanTF{##1}{
- % turn in reverse
- \pgfmathsetmacro\orient{\oldangle-##4}
- % \typeout{TURN: \oldangle=>\orient}
- \ifnumgreater{##4}{0}{% anti-clockwise turn
- \path let
- \p1=(##3.left), \p2=(##3.right),
- % center of rotation
- \p{c}=($(\p1)!-\sankeyminradius!(\p2)$),
- % starting position
- \p{s}=(##3.center),
- % ending position
- \p{e}=($(\p{c})!1!-##4:(\p{s})$)
- in \pgfextra{
- \begin{pgfinterruptpath}
- % \typeout{acw turn:\qty:\orient}
- \def\pos{\p{e}}
- \sankeymakenode{}
- \sankeyarc{\name}{\oldname}
- \end{pgfinterruptpath}
- };
- }{ % clockwise turn
- \path let
- \p1=(##3.right), \p2=(##3.left),
- % center of rotation
- \p{c}=($(\p1)!-\sankeyminradius!(\p2)$),
- % starting position
- \p{s}=(##3.center),
- % ending position
- \p{e}=($(\p{c})!1!-##4:(\p{s})$)
- in \pgfextra{
- % \typeout{cw turn:\qty:\orient}
- \begin{pgfinterruptpath}
- \def\pos{\p{e}}
- \sankeymakenode{}
- \sankeyarc{\name}{\oldname}
- \end{pgfinterruptpath}
- };
- }
- }{
- % turn
- \pgfmathsetmacro\orient{\oldangle+##4}
- % \typeout{TURN: \oldangle=>\orient}
- \ifnumgreater{##4}{0}{% anti-clockwise turn
- \path let
- \p1=(##3.left), \p2=(##3.right),
- % center of rotation
- \p{c}=($(\p1)!-\sankeyminradius!(\p2)$),
- % starting position
- \p{s}=(##3.center),
- % ending position
- \p{e}=($(\p{c})!1!##4:(\p{s})$)
- in \pgfextra{
- \begin{pgfinterruptpath}
- % \typeout{acw turn:\qty:\orient}
- \def\pos{\p{e}}
- \sankeymakenode{}
- \sankeyarc{\oldname}{\name}
- \end{pgfinterruptpath}
- };
- }{ % clockwise turn
- \path let
- \p1=(##3.right), \p2=(##3.left),
- % center of rotation
- \p{c}=($(\p1)!-\sankeyminradius!(\p2)$),
- % starting position
- \p{s}=(##3.center),
- % ending position
- \p{e}=($(\p{c})!1!##4:(\p{s})$)
- in \pgfextra{
- % \typeout{cw turn:\qty:\orient}
- \begin{pgfinterruptpath}
- \def\pos{\p{e}}
- \sankeymakenode{}
- \sankeyarc{\oldname}{\name}
- \end{pgfinterruptpath}
- };
- }
- }
- \endgroup
- }
-
- \NewDocumentCommand\sankeyfork{mm}{%name,list of forks
- \def\listofforks{##2}
- \xdef\sankeytot{0}
- \xdef\sankeycalculus{0}
- \pgfmathsetmacro\iqty{\sankeygetnodeqty{##1}}
- \pgfmathsetmacro\iorient{\sankeygetnodeorient{##1}}
- \pgfmathsetmacro\orient{\iorient}
- %\typeout{iname:##1, iqty:\iqty,iorient:\iorient}
- \foreach \qty/\name[count=\c] in \listofforks {
- %\typeout{sankeyfork foreach: qty(\qty) name(\name) count(\c)}
- \path
- let
- \p1=(##1.left),\p2=(##1.right),
- \p{start}=($(\p1)!\fpeval{\sankeytot/\iqty}!(\p2)$),
- \n{nexttot}={\fpeval{\sankeytot+\qty}},
- \p{end}=($(\p1)!\fpeval{\n{nexttot}/\iqty}!(\p2)$),
- \p{mid}=($(\p{start})!.5!(\p{end})$)
- in \pgfextra{
- %\typeout{new fork:\name}
- %\typeout{qty:\qty,name:\name,count:\c,pos=\p{mid}}
- \xdef\sankeytot{\n{nexttot}}
- \xdef\sankeycalculus{\fpeval{\sankeycalculus+\qty}}
- \begin{pgfinterruptpath}
- \def\pos{\p{mid}}
- \sankeymakenode{}
- \end{pgfinterruptpath}
- };
- }
- \edef\diff{\fpeval{abs(\iqty-\sankeytot)}}
- %\typeout{sankeyfork diff: \diff}
- %\pgfmathsetmacro{\diff}{abs(\iqty-\sankeytot)}
- %\pgfmathtruncatemacro{\finish}{\diff<0.01?1:0}
- \ifnumequal{\diff}{0}{}{
- \PackageWarning{sankey}{^^J*** Warning: bad sankey fork: \iqty\space!=\space\sankeycalculus(=\sankeytot)^^J##2}
- }
- }
-
- \def\sankeyqtytolen##1{\fpeval{(##1)/\sankeytotalqty*\sankeytotallen}}
-
- \sankeyset{
- % % default values,
- % /tikz/declare function={
- % % sankeyqtytolen(\qty)=\qty/\sankeytotalqty*\sankeytotallen;
- % % sankeylentoqty(\len)=\len/\sankeytotallen*\sankeytotalqty;
- % },%
- default parameters,%
- % user values
- #1}
-
- %\typeout{sankeytotallen: \sankeytotallen}
-
- #2 % body of sankeydiagram environment
-}
-
-
-\sankeyset{
- % none style
- new start style={none}{}{},
- new end style={none}{}{},
- % simple style
- new start style={simple}{
- (\name.left) -- ([xshift=-.5\pgflinewidth]\name.left) -- ([xshift=-.5\pgflinewidth]\name.right) -- (\name.right) -- cycle
- }{
- (\name.left) -- ([xshift=-.5\pgflinewidth]\name.left) -- ([xshift=-.5\pgflinewidth]\name.right) -- (\name.right)
- },
- new end style={simple}{
- (\name.left) -- ([xshift=2mm]\name.center) -- (\name.right) -- cycle
- }{
- (\name.left) -- ([xshift=2mm]\name.center) -- (\name.right)
- },
- % arrow style
- new start style={arrow}{
- (\name.left) -- ++(-10pt,0)
- -- ([xshift=-10pt/6]\name.center)
- -- ([xshift=-10pt]\name.right)
- -- (\name.right) -- cycle
- }{
- (\name.left) -- ++(-10pt,0)
- -- ([xshift=-10pt/6]\name.center)
- -- ([xshift=-10pt]\name.right)
- -- (\name.right)
- },
- new end style={arrow}{
- (\name.left) -- ([yshift=1mm]\name.left)
- -- ([xshift=10pt]\name.center)
- -- ([yshift=-1mm]\name.right) -- (\name.right) -- cycle
- }{
- (\name.left) -- ([yshift=1mm]\name.left)
- -- ([xshift=10pt]\name.center)
- -- ([yshift=-1mm]\name.right) -- (\name.right)
- },
-} \ No newline at end of file
diff --git a/graphics/pgf/contrib/sankey/tikzlibrarydubins.code.tex b/graphics/pgf/contrib/sankey/tikzlibrarydubins.code.tex
deleted file mode 100644
index da1dc120dc..0000000000
--- a/graphics/pgf/contrib/sankey/tikzlibrarydubins.code.tex
+++ /dev/null
@@ -1,361 +0,0 @@
-% Copyright (C) 2016-2021 by Paul Gaborit
-%
-% This file may be distributed and/or modified
-%
-% 1. under the LaTeX Project Public License and/or
-%
-% 2. under the GNU Public License.
-
-\usetikzlibrary{calc}
-
-\RequirePackage{etoolbox}
-\RequirePackage{etextools}
-\RequirePackage{xfp}
-
-\newbool{dubinspathreverse}
-
-\def\ifpgfmathcond#1{%
- \pgfmathparse{(#1)?1:0}%
- \ifnumequal{\pgfmathresult}{1}%
-}
-
-\def\anglebetween#1#2#3{%macro, s, t
- \path let
- \p{s}=(#2), \p{t}=(#3),
- \n{angle}={atan2(\y{t}-\y{s},\x{t}-\x{s})}
- in \pgfextra {
- \pgfmathsetmacro#1{\n{angle}}
- \aftergroup@def#1
- };
-}
-
-\def\distancebetween#1#2#3{%macro, s, t
- \path let
- \p{s}=(#2), \p{t}=(#3),
- %\n{dist}={veclen(\x{t}-\x{s},\y{t}-\y{s}))}
- \n{dist}={\fpeval{sqrt((\x{t}-\x{s})*(\x{t}-\x{s})+(\y{t}-\y{s})*(\y{t}-\y{s}))}}
- in \pgfextra {
- %\typeout{n{dist}:\n{dist}}
- \pgfmathsetmacro#1{\n{dist}}
- \aftergroup@def#1
- };
-}
-
-\newcommand\dubinspath@rsr{% s, sa, t, ta, as, len, at, r
- let
- \p{tr}=([shift={(\dbp@angb-90:\dbp@radius pt)}]\dbp@b),
- \n1={\dbp@anga+90},
- \n2={\dbp@angb+90},
- \n3={\n2+\dbp@lastangle}
- in
- arc(\n1:\n1-\dbp@firstangle:\dbp@rradius pt)
- -- ([shift={(\p{tr})}]\n3:\dbp@rradius pt)
- arc(\n3:\n2:\dbp@rradius pt)
-}
-
-\newcommand\dubinspath@lsl{% s, sa, t, ta, as, len, at, r
- let
- \p{tl}=([shift={(\dbp@angb+90:\dbp@radius pt)}]\dbp@b),
- \n1={\dbp@anga-90},\n2={\n1+\dbp@firstangle},
- \n3={\dbp@angb-90},\n4={\n3-\dbp@lastangle}
- in
- arc(\n1:\n2:\dbp@lradius pt)
- -- ([shift={(\p{tl})}]\n4:\dbp@lradius pt)
- arc(\n4:\n3:\dbp@lradius pt)
-}
-
-\newcommand\dubinspath@rsl{% s, sa, t, ta, as, len, at, r
- let
- \p{tl}=([shift={(\dbp@angb+90:\dbp@radius pt)}]\dbp@b),
- \n1={\dbp@anga+90},\n2={\n1-\dbp@firstangle},
- \n3={\dbp@angb-90},\n4={\n3-\dbp@lastangle}
- in
- arc(\n1:\n2:\dbp@rradius pt)
- -- ([shift={(\p{tl})}]\n4:\dbp@lradius pt)
- arc(\n4:\n3:\dbp@lradius pt)
-}
-
-\newcommand\dubinspath@lsr{% s, sa, t, ta, as, len, at, r
- let
- \p{tr}=([shift={(\dbp@angb-90:\dbp@radius pt)}]\dbp@b),
- \n1={\dbp@anga-90},\n2={\n1+\dbp@firstangle},
- \n3={\dbp@angb+90},\n4={\n3+\dbp@lastangle}
- in
- arc(\n1:\n2:\dbp@lradius pt)
- -- ([shift={(\p{tr})}]\n4:\dbp@rradius pt)
- arc(\n4:\n3:\dbp@rradius pt)
-}
-
-\newcommand\dubinspath@lrl{% s, sa, t, ta, as, ai, at, r
- let
- \n1={\dbp@anga-90},\n2={\n1+\dbp@firstangle},
- \n3={\dbp@angb-90},\n4={\n3-\dbp@lastangle}
- in
- arc(\n1:\n2:\dbp@lradius pt)
- arc(\n2+180:\n2+180-\dbp@midparam:\dbp@rradius pt)
- arc(\n4:\n3:\dbp@lradius pt)
-}
-
-\newcommand\dubinspath@rlr{% s, sa, t, ta, as, ai, at, r
- let
- \n1={\dbp@anga+90},\n2={\n1-\dbp@firstangle},
- \n3={\dbp@angb+90},\n4={\n3+\dbp@lastangle}
- in
- arc(\n1:\n2:\dbp@rradius pt)
- arc(\n2+180:\n2+180+\dbp@midparam:\dbp@lradius pt)
- arc(\n4:\n3:\dbp@rradius pt)
-}
-\newcommand\dubinspath@rev@lsl{\dubinspath@rsr}
-\newcommand\dubinspath@rev@rsr{\dubinspath@lsl}
-\newcommand\dubinspath@rev@lsr{\dubinspath@lsr}
-\newcommand\dubinspath@rev@rsl{\dubinspath@rsl}
-\newcommand\dubinspath@rev@lrl{\dubinspath@rlr}
-\newcommand\dubinspath@rev@rlr{\dubinspath@lrl}
-
-
-\newcommand\dubinspath[1]{%
- \pgfextra{
- \dubinspathset{#1}
- \ifbool{dubinspathreverse}{
- \edef\newa{\dbp@b}
- \edef\newb{\dbp@a}
- \pgfmathsetmacro\newanga{180+\dbp@angb}
- \pgfmathsetmacro\newangb{180+\dbp@anga}
- \edef\newfirstangle{\dbp@lastangle}
- \edef\newlastangle{\dbp@firstangle}
- \edef\newmethod{rev@\dbp@method}
- \edef\newlradius{\dbp@rradius}
- \edef\newrradius{\dbp@lradius}
- \dubinspathset{
- start point=\newa,
- end point=\newb,
- start angle=\newanga,
- end angle=\newangb,
- first angle=\newfirstangle,
- last angle=\newlastangle,
- left and right minimum radii=\newlradius pt and \newrradius pt,
- method=\newmethod,
- }
- }{}
- %\typeout{dbp@lradius:\dbp@lradius}
- %\typeout{dbp@rradius:\dbp@rradius}
- }
- \csname dubinspath@\dbp@method\endcsname%
-}
-
-
-% solution
-% \xdef\dubinspathmethod{} % type of dubins path
-% \xdef\dubinspathlength{} % lenght (pt)
-% \xdef\dubinspathfirstangle{} % first angle
-% \xdef\dubinspathmiddleparam{} % intermediate angle or straight distance
-% \xdef\dubinspathlastangle{} % last angle
-
-\def\dubinspathstore#1#2{%
- \expandafter\xdef\csname dubinspath@store@#1@#2\endcsname%
- {\csname dubinspath#2\endcsname}%
-}
-\def\dubinspathget#1#2{%
- \csname dubinspath@store@#1@#2\endcsname%
-}
-
-%
-\def\dubinspathsetparams#1#2#3#4#5{% method, length, fisrt angle, middle param, last angle
- \edef\dubinspathmethod{#1}
- \edef\dubinspathlength{#2}
- \edef\dubinspathfirstangle{#3}
- \edef\dubinspathmiddleparam{#4}
- \edef\dubinspathlastangle{#5}
- \ifdef{\dbp@storename}{
- \foreach \p in {method,length,firstangle,middleparam,lastangle}{
- \dubinspathstore{\dbp@storename}{\p}
- }
- }{}
-}
-
-\def\dubinspathupdateparams#1#2#3#4#5{
- \ifpgfmathcond{#2<\dubinspathlength}{
- \dubinspathsetparams{#1}{#2}{#3}{#4}{#5}
- }{}
-}
-
-\tikzset{
- dubins path/.is family,
- dubins path,
- start point/.store in=\dbp@a,
- start angle/.store in=\dbp@anga,
- end point/.store in=\dbp@b,
- end angle/.store in=\dbp@angb,
- store/.store in=\dbp@storename,
- use store/.style={
- method=\dubinspathget{#1}{method},
- first angle=\dubinspathget{#1}{firstangle},
- last angle=\dubinspathget{#1}{lastangle},
- middle param=\dubinspathget{#1}{middleparam},
- },
- minimum radius/.code={
- \pgfmathsetmacro\dbp@radius{#1}
- \pgfmathsetmacro\dbp@rradius{#1}
- \pgfmathsetmacro\dbp@lradius{#1}
- },
- left and right minimum radii/.code args={#1 and #2}{
- \pgfmathsetmacro\dbp@lradius{#1}
- \pgfmathsetmacro\dbp@rradius{#2}
- \pgfmathsetmacro\dbp@radius{(\dbp@lradius + \dbp@rradius)/2}
- },
- method/.store in=\dbp@method,
- first angle/.store in=\dbp@firstangle,
- last angle/.store in=\dbp@lastangle,
- middle param/.store in=\dbp@midparam,
- reverse/.is if=dubinspathreverse,
-}
-
-\newcommand\dubinspathset[1]{\tikzset{dubins path,#1}}
-
-\newcommand\dubinspathcalc[1]{%
- \begingroup
- \dubinspathset{#1}
- \tikzset{
- declare function={
- angtodist(\a,\r)={abs(\a)*.01745329*\r};
- modangr(\a,\b)={
- (Mod(\a,360)<Mod(\b,360)?Mod(\a,360):Mod(\a,360)-360)+\b-Mod(\b,360)
- };
- modangl(\a,\b)={
- (Mod(\a,360)<Mod(\b,360)?Mod(\a,360)+360:Mod(\a,360))+(\b)-Mod(\b,360)
- };
- },
- }
-
- \pgfmathsetmacro\radius{\dbp@rradius}
- \pgfmathsetmacro\anga{mod((\dbp@anga)+180,360)-180}
- \pgfmathsetmacro\angb{mod((\dbp@angb)+180,360)-180}
- %\typeout{radius:\radius,anga:\anga,angb:\angb}
- \path
- let
- \p{a}=(\dbp@a),
- \p{b}=(\dbp@b),
- \p{ar}=($(\p{a}) + (\anga-90:\radius pt)$),
- \p{al}=($(\p{a}) + (\anga+90:\radius pt)$),
- \p{br}=($(\p{b}) + (\angb-90:\radius pt)$),
- \p{bl}=($(\p{b}) + (\angb+90:\radius pt)$)
- in \pgfextra{
- \pgfinterruptpath
-
- % RSR (ar et br)
- %\typeout{RSR begin}
- \anglebetween\rsrarbr{\p{ar}}{\p{br}}
- \distancebetween\rsrdarbr{\p{ar}}{\p{br}}
- \pgfmathsetmacro\rsrangone{Mod(\anga-\rsrarbr,360)}
- \pgfmathsetmacro\rsrangtwo{Mod(\rsrarbr-\angb,360)}
- \pgfmathsetmacro\rsrlen{\rsrdarbr}
- \pgfmathsetmacro\rsrdist{
- angtodist(\rsrangone,\radius)
- +\rsrlen
- +angtodist(\rsrangtwo,\radius)
- }
- \dubinspathsetparams{rsr}{\rsrdist}{\rsrangone}{\rsrlen}{\rsrangtwo}
-
- % LSL (al et bl)
- %\typeout{LSL begin}
- \anglebetween\lslalbl{\p{al}}{\p{bl}}
- \distancebetween\lsldalbl{\p{al}}{\p{bl}}
- \pgfmathsetmacro{\lslangone}{mod(\lslalbl-\anga+720,360)}
- \pgfmathsetmacro{\lslangtwo}{mod(\angb-\lslalbl+720,360)}
- \pgfmathsetmacro\lsllen{\lsldalbl}
- \pgfmathsetmacro\lsldist{
- angtodist(\lslangone,\radius)
- +\lsllen
- +angtodist(\lslangtwo,\radius)
- }
- \dubinspathupdateparams{lsl}{\lsldist}{\lslangone}{\lsllen}{\lslangtwo}
-
- % RSL (ar et bl)
- %\typeout{RSL begin}
- \distancebetween\rsldarbl{\p{ar}}{\p{bl}}
- \pgfmathtruncatemacro\rslok{(\rsldarbl>=2*\radius)?1:0}
- \ifnumequal{\rslok}{1}{
- \anglebetween\rslarbl{\p{ar}}{\p{bl}}
- \pgfmathsetmacro\rslanglesup{
- asin(\radius/\rsldarbl*2)}
- \pgfmathsetmacro\rslangone{Mod(\anga-\rslarbl+\rslanglesup,360)}
- \pgfmathsetmacro\rslangtwo{Mod(\angb-\rslarbl+\rslanglesup,360)}
- \pgfmathsetmacro\rsllen{veclen(\rsldarbl,\radius)}
- \pgfmathsetmacro\rsldist{
- angtodist(\rslangone,\radius)
- +\rsllen
- +angtodist(\rslangtwo,\radius)
- }
-
- \dubinspathupdateparams{rsl}{\rsldist}{\rslangone}{\rsllen}{\rslangtwo}
- }{}
-
- % LSR (al et br)
- %\typeout{LSR begin}
- \distancebetween\lsrdalbr{\p{al}}{\p{br}}
- \pgfmathtruncatemacro\lsrok{(\lsrdalbr>=2*\radius)?1:0}
- \ifnumequal{\lsrok}{1}{
- \anglebetween\lsralbr{\p{al}}{\p{br}}
- \pgfmathsetmacro\lsranglesup{
- asin(\radius/\lsrdalbr*2)}
- \pgfmathsetmacro\lsrangone{Mod(\lsralbr+\lsranglesup-\anga,360)}
- \pgfmathsetmacro\lsrangtwo{Mod(\lsralbr+\lsranglesup-\angb,360)}
- \pgfmathsetmacro\lsrlen{veclen(\lsrdalbr,\radius)}
- \pgfmathsetmacro\lsrdist{
- angtodist(\lsrangone,\radius)
- +\lsrlen
- +angtodist(\lsrangtwo,\radius)
- }
- \dubinspathupdateparams{lsr}{\lsrdist}{\lsrangone}{\lsrlen}{\lsrangtwo}
- }{}
-
- % LRL (al et bl)
- %\typeout{LRL begin}
- \distancebetween\lrldalbl{\p{al}}{\p{bl}}
- \pgfmathtruncatemacro\lrlok{(\lrldalbl<=4*\radius)?1:0}
- \ifnumequal{\lrlok}{1}{
- % \debug{LRL}
- \anglebetween\lrlalbl{\p{al}}{\p{bl}}
- \pgfmathsetmacro\lrlangsup{acos(\lrldalbl/\radius/4)}
- \pgfmathsetmacro\lrlangone{
- modangl(\lrlalbl+\lrlangsup,\anga-90)-(\anga-90)}
- \pgfmathsetmacro\lrlangtwo{%
- (\angb-90)-modangr(\lrlalbl+180-\lrlangsup,\angb-90)}
- \pgfmathsetmacro\lrlangthree{360-2*(90-\lrlangsup)}
- \pgfmathsetmacro\lrldist{
- angtodist(\lrlangone,\radius)
- +angtodist(\lrlangthree,\radius)
- +angtodist(\lrlangtwo,\radius)
- }
- \dubinspathupdateparams{lrl}{\lrldist}{\lrlangone}{\lrlangthree}{\lrlangtwo}
- }{}
-
- % RLR (ar et br)
- %\typeout{RLR begin}
- \distancebetween\rlrdarbr{\p{ar}}{\p{br}}
- \pgfmathtruncatemacro\rlrok{(\rlrdarbr<=4*\radius)?1:0}
- \ifnumequal{\rlrok}{1}{
- \anglebetween\rlrarbr{\p{ar}}{\p{br}}
- \pgfmathsetmacro\rlrangsup{acos(\rlrdarbr/\radius/4)}
- \pgfmathsetmacro\rlrangone{
- (\anga+90)-modangr(\rlrarbr-\rlrangsup,\anga+90)}
- \pgfmathsetmacro\rlrangtwo{%
- modangl(\rlrarbr+180+\rlrangsup,\angb+90)-(\angb+90)}
- \pgfmathsetmacro\rlrangthree{360-2*(90-\rlrangsup)}
- \pgfmathsetmacro\rlrdist{
- angtodist(\rlrangone,\radius)
- +angtodist(\rlrangthree,\radius)
- +angtodist(\rlrangtwo,\radius)
- }
- \dubinspathupdateparams{rlr}{\rlrdist}{\rlrangone}{\rlrangthree}{\rlrangtwo}
- }{}
-
- \endpgfinterruptpath
- };
- \endgroup
-}
-
-%%% Local Variables:
-%%% mode: latex
-%%% TeX-master: t
-%%% End: