texlive[73396] Master/texmf-dist: sankey (11jan25)

commits+karl at tug.org commits+karl at tug.org
Sat Jan 11 00:03:17 CET 2025


Revision: 73396
          https://tug.org/svn/texlive?view=revision&revision=73396
Author:   karl
Date:     2025-01-11 00:03:17 +0100 (Sat, 11 Jan 2025)
Log Message:
-----------
sankey (11jan25)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/sankey/README
    trunk/Master/texmf-dist/doc/latex/sankey/sankey.pdf
    trunk/Master/texmf-dist/source/latex/sankey/sankey.dtx
    trunk/Master/texmf-dist/source/latex/sankey/sankey.ins
    trunk/Master/texmf-dist/tex/latex/sankey/sankey-doc-preamble.sty
    trunk/Master/texmf-dist/tex/latex/sankey/sankey.sty
    trunk/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex

Modified: trunk/Master/texmf-dist/doc/latex/sankey/README
===================================================================
--- trunk/Master/texmf-dist/doc/latex/sankey/README	2025-01-10 23:03:07 UTC (rev 73395)
+++ trunk/Master/texmf-dist/doc/latex/sankey/README	2025-01-10 23:03:17 UTC (rev 73396)
@@ -10,7 +10,7 @@
 license
 =======
 
-Copyright (C) 2016-2021 by Paul Gaborit
+Copyright (C) 2016-2025 by Paul Gaborit
 
 This file may be distributed and/or modified
 

Modified: trunk/Master/texmf-dist/doc/latex/sankey/sankey.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/latex/sankey/sankey.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/sankey/sankey.dtx	2025-01-10 23:03:07 UTC (rev 73395)
+++ trunk/Master/texmf-dist/source/latex/sankey/sankey.dtx	2025-01-10 23:03:17 UTC (rev 73396)
@@ -1,6 +1,6 @@
 % \iffalse meta-comment
 %
-% Copyright (C) 2016, 2021 by Paul Gaborit
+% Copyright (C) 2016-2025 by Paul Gaborit
 % -----------------------------------
 %
 % This work may be distributed and/or modified under the conditions of
@@ -30,6 +30,7 @@
 %
 %<*driver>
 \documentclass[a4paper,10pt,draft]{ltxdoc}
+\SetupDoc{reportchangedates}
 \usepackage{sankey-doc-preamble}
 \EnableCrossrefs
 \CodelineIndex
@@ -40,26 +41,6 @@
 %</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}
@@ -68,6 +49,7 @@
 % \DoNotIndex{\def,\edef,\gdef,\xdef,\ifx,\else,\string,\relax}
 % \DoNotIndex{\csname,\endcsname,\ifcsdef,\expandafter,\ifnumgreater}
 % \DoNotIndex{\NewDocumentCommand,\NewDocumentEnvironment,\IfBooleanTF}
+% \DoNotIndex{\NewCommandCopy,\NewExpandableDocumentCommand}
 % \DoNotIndex{\NeedsTeXFormat,\ProvidesPackage,\RequirePackage,\PackageError,\PackageWarning}
 % \DoNotIndex{\newtoggle,\toggletrue,\togglefalse,\iftoggle,\ifdefempty,\ifundef,\ifdefstrequal}
 % \DoNotIndex{\ifbool,\ifdef,\ifnumequal,\colorlet,\fpeval,\inteval,\newbool}
@@ -104,10 +86,11 @@
 %  pdfauthor=Paul Gaborit,
 % }
 %
+% \def\ttintitle#1{\textmd{\textcolor{red!50!black}{\texttt{#1}}}}
 %
 %
 % \begin{abstract}
-%   The \texttt{sankey} package provides macros and environments to
+%   The \code{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
@@ -119,8 +102,13 @@
 %
 % \end{abstract}
 %
+%
 % \manualparts
 %
+% \clearpage
+%
+% \manualparts
+%
 % \begin{quote}
 %   {\footnotesize Note: the \code{sankey.dtx} and \code{sankey.ins}
 %   files are attachments of the current PDF document.\par}
@@ -131,11 +119,17 @@
 % \label{usermanual}
 %^^A % ------------------------------------------------------------
 %
+% \changes{v3.0.2}{2025/10/10}{Update for new version of \protect\code{ltxdoc} class}
+% 
+% \changes{v3.0.2}{2025/10/10}{Fixed extra parentheses in some code examples}
+%
 % {
 %   \setlength{\parskip}{0pt}
 %   \localtableofcontents
 % }
 %
+% \clearpage
+% 
 %^^A % ------------------------------------------------------------
 % \section{Preamble}
 %^^A % ------------------------------------------------------------
@@ -149,13 +143,13 @@
 % {\small Note: the
 % \code{sankey} package requires automatically the
 % \code{xparse}, \code{etoolbox}, \code{xfp} and
-% \code{tikz} packages, and the \code{calc},
+% \code{tikz} packages, as well as the \code{calc},
 % \code{decorations.markings} and
 % \code{dubins} (cf. \vref{sec:dubins}) TikZ libraries.\par}
 %
 %
 %^^A % ------------------------------------------------------------
-% \section{The \texttt{sankeydiagram} environment}
+% \section{The \ttintitle{sankeydiagram} environment}
 %^^A % ------------------------------------------------------------
 %
 % \DescribeEnv{sankeydiagram} %
@@ -175,21 +169,25 @@
 %^^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).
+% \emph{key=value} pairs with default path \code{/sankey} (and
+% \code{/sankey/node parameters} for Sankey node parameters).
 %
-% The options can be defined via the optional argument of the
-% \code{sankeydiagram} environment:
 %
+% Options can be defined in three ways:
+%
+% \begin{itemize}
+% \item 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:
-%
+% 
+% \item \DescribeMacro{\sankeyset} %
+% via the \code{\sankeyset} macro:
+%   
 % \begin{lstlisting}[style=LaTeXsmall]
 % \begin{sankeydiagram}
 %   \sankeyset{debug=true}
@@ -196,14 +194,16 @@
 %   \sankeynode{name=a,quantity=1,angle=0,at={0,0}}
 % \end{sankeydiagram}
 % \end{lstlisting}
-%
-% The options can be  temporarily modified for a single macro:
+%   
+% \item  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}
-%
+%   
+% \end{itemize}
+% 
 % At the begining of each Sankey diagram, all options are initialized
 % with initial values then the \code{every diagram} style is applied.
 %
@@ -340,9 +340,9 @@
 %^^A % ------------------------------------------------------------
 %
 % \begin{miniblock}
+% \DescribeMacro{\sankeynode} %
 % \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
@@ -363,8 +363,8 @@
 % \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).
+%   The position of the new Sankey node (a TikZ coordinate
+%   \textbf{without} round brackets or parentheses).
 % \end{sankeyoption}
 %
 % \begin{sankeyoption}[/sankey/node parameters]{anchor}{\VAR{anchor}}{}{center}
@@ -392,8 +392,7 @@
 %   \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}
-%
+%     \sankeynode{name=c,quantity=20,angle=-90,at={5,0},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,
@@ -410,6 +409,9 @@
 % %
 % \lstinputlisting[style=LaTeXsmall]{\samplecodename}
 % \end{miniblock}
+%
+%^^A % \clearpage
+%
 %^^A % ------------------------------------------------------------
 % \subsubsection{Choose default parameters}
 %^^A % ------------------------------------------------------------
@@ -424,9 +426,9 @@
 %^^A % ------------------------------------------------------------
 %
 % \begin{miniblock}
+% \DescribeMacro{\sankeynodestart} %
 % \MACRO\code{\sankeynodestart}\OPTARG{\VAR{options}}\ARG{\VAR{node parameters}}
 %
-% \DescribeMacro{\sankeynodestart} %
 % The \code{\sankeynodestart} creates and fills/draws a starting Sankey
 % node:
 %
@@ -449,10 +451,10 @@
 %
 %
 % \begin{miniblock}
+%   \DescribeMacro{\sankeynodeend} %
 %   \MACRO\code{\sankeynodeend}\OPTARG{\VAR{options}}\ARG{\VAR{node
 %   parameters}}
 %   
-%   \DescribeMacro{\sankeynodeend} %
 %   The \code{\sankeynodeend} creates and fills/draws an ending Sankey
 %   node:
 %   
@@ -547,21 +549,21 @@
 % \subsection{Retrieve information from Sankey nodes}
 %^^A % ------------------------------------------------------------
 %
+% \DescribeMacro{\sankeygetnodeqty} %
 % \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}.
 %
+% \DescribeMacro{\sankeyqtytolen} %
 % \MACRO\code{\sankeyqtytolen}\ARG{\VAR{quantity}}
 %
-% \DescribeMacro{\sankeyqtytolen} %
 % The expandable \code{\sankeyqtytolen} macro converts \VAR{quantity} to
 % graphical length using the current ratio.
 %
+% \DescribeMacro{\sankeygetnodeorient} %
 % \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}.
 %
@@ -658,13 +660,14 @@
 %
 %
 % \begin{miniblock}
+%   \DescribeMacro{\sankeyadvance} %
 %   \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.
+%   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}
@@ -677,6 +680,7 @@
 %     \sankeyadvance{b}{1cm}
 %     \sankeynodestart{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
 %     \sankeyadvance{c}{5mm}
+%     \fill[cyan] (0,0) circle(2pt) (2,1) circle(2pt) (5,1) circle(2pt);
 %   \end{sankeydiagram}
 % \end{tikzpicture}
 % \end{VerbatimOut}
@@ -689,12 +693,10 @@
 % \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. A positive \VAR{distance} moves backward while a negative \VAR{distance} moves forward.
 %   
-%   \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}]
@@ -706,6 +708,7 @@
 %     \sankeyadvance*{b}{1cm}
 %     \sankeynodeend{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
 %     \sankeyadvance*{c}{5mm}
+%     \fill[cyan] (0,0) circle(2pt) (2,1) circle(2pt) (5,1) circle(2pt);
 %   \end{sankeydiagram}
 % \end{tikzpicture}
 % \end{VerbatimOut}
@@ -720,10 +723,11 @@
 %^^A % ------------------------------------------------------------
 %
 %\begin{miniblock}
+%   \DescribeMacro{\sankeyturn} %
 %   \MACRO\code{\sankeyturn}\OPTARG{\VAR{options}}\ARG{\VAR{node
 %   name}}\ARG{\VAR{angle}}
 %   
-%   \DescribeMacro{\sankeyturn} The \code{\sankeyturn} macro moves the
+%   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.
@@ -739,6 +743,7 @@
 %     \sankeyturn[minimum radius=1cm]{b}{-45}
 %     \sankeynodestart{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
 %     \sankeyturn{c}{180}
+%     \fill[cyan] (0,0) circle(2pt) (2,1) circle(2pt) (5,1) circle(2pt);
 %   \end{sankeydiagram}
 % \end{tikzpicture}
 % \end{VerbatimOut}
@@ -752,7 +757,7 @@
 %   \MACRO\code{\sankeyturn*}\OPTARG{\VAR{options}}\ARG{\VAR{node
 %   name}}\ARG{\VAR{angle}}
 %   
-%   \DescribeMacro{\sankeyturn*} The \code{\sankeyturn*} macro moves the
+%   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.
@@ -768,6 +773,7 @@
 %     \sankeyturn*[minimum radius=1cm]{b}{-45}
 %     \sankeynodeend{name=c,quantity=10,angle=-90,at={3,1},anchor=right}
 %     \sankeyturn*{c}{180}
+%     \fill[cyan] (0,0) circle(2pt) (2,1) circle(2pt) (3,1) circle(2pt);
 %   \end{sankeydiagram}
 % \end{tikzpicture}
 % \end{VerbatimOut}
@@ -782,13 +788,14 @@
 %^^A % ------------------------------------------------------------
 %
 % \begin{miniblock}
+%   \DescribeMacro{\sankeyturnleft} %
 %   \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.
+%   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}
@@ -801,6 +808,7 @@
 %     \sankeyset{fill/.style={fill=lime!20}}
 %     \sankeynodeend{name=b,quantity=5,angle=-135,at={1,2},anchor=left}
 %     \sankeyturnleft[minimum radius=1cm]{b}{-225}
+%     \fill[cyan] (0,0) circle(2pt) (1,2) circle(2pt);
 % \end{sankeydiagram}
 % \end{tikzpicture}
 % \end{VerbatimOut}
@@ -814,7 +822,7 @@
 %   \MACRO\code{\sankeyturnleft*}\OPTARG{\VAR{options}}\ARG{\VAR{node
 %   name}}\ARG{\VAR{angle}}
 %   
-%   \DescribeMacro{\sankeyturnleft*} The
+%   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
@@ -831,6 +839,7 @@
 %     \sankeyset{fill/.style={fill=lime!20}}
 %     \sankeynodestart{name=b,quantity=5,angle=-135,at={1,2},anchor=left}
 %     \sankeyturnleft*[minimum radius=.75cm]{b}{-225}
+%     \fill[cyan] (0,0) circle(2pt) (1,2) circle(2pt);
 % \end{sankeydiagram}
 % \end{tikzpicture}
 % \end{VerbatimOut}
@@ -841,13 +850,13 @@
 % \end{miniblock}
 %
 % \begin{miniblock}
+%   \DescribeMacro{\sankeyturnleftbackward} %
 %   \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
+%   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}
@@ -861,6 +870,7 @@
 %     \sankeyset{fill/.style={fill=lime!20}}
 %     \sankeynodestart{name=b,quantity=5,angle=-135,at={1,2},anchor=left}
 %     \sankeyturnleftbackward[minimum radius=.75cm]{b}{-225}
+%     \fill[cyan] (0,0) circle(2pt) (1,2) circle(2pt);
 % \end{sankeydiagram}
 % \end{tikzpicture}
 % \end{VerbatimOut}
@@ -874,7 +884,7 @@
 %   \MACRO\code{\sankeyturnleftbackward*}\OPTARG{\VAR{options}}\ARG{\VAR{node
 %   name}}\ARG{\VAR{angle}}
 %   
-%   \DescribeMacro{\sankeyturnleftbackward*} The
+%   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.
@@ -890,6 +900,7 @@
 %     \sankeyset{fill/.style={fill=lime!20}}
 %     \sankeynodeend{name=b,quantity=5,angle=-135,at={1,2},anchor=left}
 %     \sankeyturnleftbackward*[minimum radius=1cm]{b}{-225}
+%     \fill[cyan] (0,0) circle(2pt) (1,2) circle(2pt);
 % \end{sankeydiagram}
 % \end{tikzpicture}
 % \end{VerbatimOut}
@@ -905,13 +916,14 @@
 %^^A % ------------------------------------------------------------
 %
 % \begin{miniblock}
+%   \DescribeMacro{\sankeyturnright} %
 %   \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.
+%   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}
@@ -924,6 +936,7 @@
 %     \sankeyset{fill/.style={fill=lime!20}}
 %     \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
 %     \sankeyturnright[minimum radius=.75cm]{b}{-225}
+%     \fill[cyan] (0,0) circle(2pt) (2,1) circle(2pt);
 % \end{sankeydiagram}
 % \end{tikzpicture}
 % \end{VerbatimOut}
@@ -937,7 +950,7 @@
 %   \MACRO\code{\sankeyturnright*}\OPTARG{\VAR{options}}\ARG{\VAR{node
 %   name}}\ARG{\VAR{angle}}
 %   
-%   \DescribeMacro{\sankeyturnright*} The \code{\sankeyturnright*} macro
+%   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.
@@ -953,6 +966,7 @@
 %     \sankeyset{fill/.style={fill=lime!20}}
 %     \sankeynodestart{name=b,quantity=5,angle=45,at={1,1},anchor=left}
 %     \sankeyturnright*[minimum radius=.75cm]{b}{-225}
+%     \fill[cyan] (0,0) circle(2pt) (1,1) circle(2pt);
 % \end{sankeydiagram}
 % \end{tikzpicture}
 % \end{VerbatimOut}
@@ -963,10 +977,10 @@
 % \end{miniblock}
 %
 % \begin{miniblock}
+%   \DescribeMacro{\sankeyturnrightbackward} %
 %   \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
@@ -983,6 +997,7 @@
 %     \sankeyset{fill/.style={fill=lime!20}}
 %     \sankeynodestart{name=b,quantity=5,angle=45,at={1,1},anchor=left}
 %     \sankeyturnrightbackward[minimum radius=.75cm]{b}{-225}
+%     \fill[cyan] (0,0) circle(2pt) (1,1) circle(2pt);
 % \end{sankeydiagram}
 % \end{tikzpicture}
 % \end{VerbatimOut}
@@ -996,7 +1011,7 @@
 %   \MACRO\code{\sankeyturnrightbackward*}\OPTARG{\VAR{options}}\ARG{\VAR{node
 %   name}}\ARG{\VAR{angle}}
 %   
-%   \DescribeMacro{\sankeyturnrightbackward*} The
+%   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
@@ -1013,6 +1028,7 @@
 %     \sankeyset{fill/.style={fill=lime!20}}
 %     \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
 %     \sankeyturnrightbackward*[minimum radius=.75cm]{b}{-225}
+%     \fill[cyan] (0,0) circle(2pt) (2,1) circle(2pt);
 % \end{sankeydiagram}
 % \end{tikzpicture}
 % \end{VerbatimOut}
@@ -1035,31 +1051,36 @@
 % node to \code{A} node!
 %
 % \begin{miniblock}
+%   \DescribeMacro{\sankeyoutin} %
 %   \MACRO\code{\sankeyoutin}\OPTARG{\VAR{options}}\ARG{\VAR{node
 %   A}}\ARG{\VAR{node B}}
 %   
-%   \DescribeMacro{\sankeyoutin} The \code{\sankeyoutin} macro
+%   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!
+%   \textbf{Note:} The constant width and the minimum curvature are
+%   \emph{not} guaranteed!
 % \end{miniblock}
 %
 % \begin{miniblock}
+%   \DescribeMacro{\sankeydubins} %
 %   \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.
+%   \textbf{Note:} The constant width and the minimum curvature are
+%   guaranteed.
 % \end{miniblock}
 %
+% \clearpage
+%
 %^^A % ------------------------------------------------------------
-% \subsubsection{Comparison between \texttt{outin} and \texttt{dubins}
+% \subsubsection{Comparison between \ttintitle{outin} and \ttintitle{dubins}
 %   paths}
 %^^A % ------------------------------------------------------------
 %
@@ -1083,7 +1104,7 @@
 %
 %     \sankeyset{fill/.style={fill=lime!40}}
 %     \sankeynodestart{name=a,at={4,0},quantity=5}
-%     \sankeynodeend{name=b,at={(8,3},quantity=5}
+%     \sankeynodeend{name=b,at={8,3},quantity=5}
 %     \sankeydubins[minimum radius=5mm]{a}{b}
 %   \end{sankeydiagram}
 % \end{tikzpicture}
@@ -1110,7 +1131,7 @@
 %
 %     \sankeyset{fill/.style={fill=lime!40}}
 %     \sankeynodestart{name=a,at={4,0},quantity=5}
-%     \sankeynodeend{name=b,at={(6,3},quantity=5}
+%     \sankeynodeend{name=b,at={6,3},quantity=5}
 %     \sankeydubins[minimum radius=5mm]{a}{b}
 %   \end{sankeydiagram}
 % \end{tikzpicture}
@@ -1137,7 +1158,7 @@
 %
 %     \sankeyset{fill/.style={fill=lime!40}}
 %     \sankeynodestart{name=a,at={4,0},quantity=5}
-%     \sankeynodeend{name=b,at={(4,3},quantity=5}
+%     \sankeynodeend{name=b,at={4,3},quantity=5}
 %     \sankeydubins[minimum radius=5mm]{a}{b}
 %   \end{sankeydiagram}
 % \end{tikzpicture}
@@ -1149,7 +1170,7 @@
 % \end{miniblock}
 %
 %^^A % ------------------------------------------------------------
-% \subsubsection{Examples of \texttt{dubins} paths}
+% \subsubsection{Examples of \ttintitle{dubins} paths}
 %^^A % ------------------------------------------------------------
 %
 % \begin{miniblock}
@@ -1195,13 +1216,13 @@
 %^^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}:
-%
-%
+%   \DescribeMacro{\sankeystart} %
+%   \MACRO\code{\sankeystart}\OPTARG{\VAR{options}}\ARG{\VAR{name}}
+%   
+%   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}
@@ -1224,9 +1245,9 @@
 %
 %
 % \begin{miniblock}
+%   \DescribeMacro{\sankeyend} %
 %   \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}:
 %
@@ -1257,7 +1278,7 @@
 % \subsubsection{Create and fork a Sankey node}
 %^^A % ------------------------------------------------------------
 %
-% \changes{v3.0}{2021/03/14}{add keys to fork a Sankey node during its
+% \changes{v3.0}{2021/03/14}{Add keys to fork a Sankey node during its
 % creation}
 %
 % \begin{miniblock}
@@ -1314,9 +1335,9 @@
 % \subsubsection{Fork a Sankey node}
 %^^A % ------------------------------------------------------------
 % \begin{miniblock}
+%   \DescribeMacro{\sankeyfork} %
 %   \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
@@ -1344,7 +1365,7 @@
 %^^A % ------------------------------------------------------------
 %
 %^^A % ------------------------------------------------------------
-% \subsection{The \texttt{debug} layer}
+% \subsection{The \ttintitle{debug} layer}
 %^^A % ------------------------------------------------------------
 %
 % The options \code{debug} key uses the \code{sankeydebug} layer to draw
@@ -1378,7 +1399,7 @@
 % \end{lstlisting}
 %
 %^^A % ------------------------------------------------------------
-% \subsection{The \texttt{dubins} TikZ library}
+% \subsection{The \ttintitle{dubins} TikZ library}
 % \label{sec:dubins}
 %^^A % ------------------------------------------------------------
 %
@@ -1390,9 +1411,9 @@
 % \subsection{How to duplicate a Sankey node}
 %^^A % ------------------------------------------------------------
 %
+% \DescribeMacro{\sankeynodealias} %
 % \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}.
 %
@@ -1727,7 +1748,7 @@
 % \section{Example from question on TeX.se}
 %^^A % ------------------------------------------------------------
 %
-% \changes{v3.0}{2021/03/14}{fix bad names in second example}
+% \changes{v3.0}{2021/03/14}{Fix bad names in second example}
 %
 % \embedfile[mimetype=text/plain]{sankey-example2.tex}
 %
@@ -1946,7 +1967,7 @@
 % \section{Reproduction of an example from Google Charts documentation}
 %^^A % ------------------------------------------------------------
 %
-% \changes{v3.0}{2021/03/14}{add the reproduction of an example from
+% \changes{v3.0}{2021/03/14}{Add the reproduction of an example from
 % Google Charts documentation}
 %
 % \embedfile[mimetype=text/plain]{sankey-example3.tex}
@@ -2313,7 +2334,7 @@
 % 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.
+% You can change the data values between lines 27 and 52.
 %
 % See figure~\vref{fig:nice-example}. The \code{sankey-example4.tex}
 % file contains the following code and is an attachement of the current
@@ -2585,13 +2606,13 @@
 % }
 %
 %
-% \changes{v3.0.1}{2022/02/04}{fix options used by the new version of siunitx}
+% \changes{v3.0.1}{2022/02/04}{Fix options used by the new version of \protect\code{siunitx} package}
 %
 %^^A % ------------------------------------------------------------
-% \section{Compiling \texttt{sankey}}
+% \section{Compiling \ttintitle{sankey}}
 %^^A % ------------------------------------------------------------
 %
-% \changes{v3.0.1}{2022/02/04}{instructions for compiling and installing the
+% \changes{v3.0.1}{2022/02/04}{Add instructions for compiling and installing the
 % package}
 %
 % To produce the \code{sankey} package:
@@ -2618,15 +2639,15 @@
 %
 %
 %^^A % ------------------------------------------------------------
-% \section{The \texttt{sankey.sty} file}
+% \section{The \ttintitle{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}
+% \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 \protect\code{.ins} and \protect\code{.dtx} files}
 %
 % \iffalse
 %<*sankey>
@@ -2636,7 +2657,7 @@
 %
 %    \begin{macrocode}
 \NeedsTeXFormat{LaTeX2e}[2015/10/01]
-\ProvidesPackage{sankey}[2022/02/04 v3.0.1 to draw Sankey diagrams]
+\ProvidesPackage{sankey}[2025/01/10 v3.0.2 to draw Sankey diagrams]
 %    \end{macrocode}
 %
 % All required packages and TikZ libraries:
@@ -2700,7 +2721,7 @@
 %
 %^^A % ------------------------------------------------------------
 % \subsubsection{Definition of \emph{global} and \emph{expanded} fields (using
-% \texttt{\protect\string\xdef})}
+% \ttintitle{\protect\string\xdef})}
 %^^A % ------------------------------------------------------------
 %
 % \begin{macro}{\snk at setnodeqty}
@@ -2728,7 +2749,7 @@
 % \end{macro}
 %
 %^^A % ------------------------------------------------------------
-% \subsubsection{Definitions of \emph{local} fields (using \texttt{\protect\string\def})}
+% \subsubsection{Definitions of \emph{local} fields (using \ttintitle{\protect\string\def})}
 %^^A % ------------------------------------------------------------
 %
 % \begin{macro}{\snk at setstartfill}
@@ -2795,7 +2816,7 @@
 % \end{macro}
 %
 %^^A % ------------------------------------------------------------
-% \subsection{The \texttt{sankey node} shape}
+% \subsection{The \ttintitle{sankey node} shape}
 %^^A % ------------------------------------------------------------
 %
 %
@@ -3191,21 +3212,6 @@
   },
 }
 %    \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}
@@ -3217,10 +3223,10 @@
 % node\footnote{Thanks to Andrew Stacey \url{https://tex.stackexchange.com/a/33765/14500}}.
 %
 %    \begin{macrocode}
-  \def\snk at getpos##1##2{%
-    \tikz at scan@one at point\pgfutil at firstofone(##2)\relax%
-    \edef##1{\the\pgf at x,\the\pgf at y}%
-  }
+\def\snk at getpos#1#2{%
+  \tikz at scan@one at point\pgfutil at firstofone(#2)\relax%
+  \edef#1{\the\pgf at x,\the\pgf at y}%
+}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -3229,7 +3235,7 @@
 % The \code{\snk at modulo} macro evaluates \#1 modulo \#2 using \code{\fpeval}.
 % 
 %    \begin{macrocode}
-  \def\snk at modulo##1##2{\fpeval{##1-(floor((##1)/(##2),0)*##2)}}
+\def\snk at modulo#1#2{\fpeval{#1-(floor((#1)/(#2),0)*#2)}}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -3239,9 +3245,9 @@
 % $-180$ and $180$ (using \code{\fpeval}).
 %
 %    \begin{macrocode}
-  \def\snk at normalize@angle##1{%
-    \fpeval{\snk at modulo{(##1)+180}{360}-180}%
-  }
+\def\snk at normalize@angle#1{%
+  \fpeval{\snk at modulo{(#1)+180}{360}-180}%
+}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -3254,22 +3260,22 @@
 % \code{/sankey/debug normal} and \code{/sankey/debug label} Tikz styles.
 %
 %    \begin{macrocode}
-  \def\snk at 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 at len}{\sankeyqtytolen{\qty}/3}
-        \path[/sankey/debug normal] (\name.center)
-        -- ($(\name.center)!\snk at len pt!90:(\name.right)$)
-        node[/sankey/debug label,rotate=\orient+90+\snk at rotate,anchor=north];
-      \end{pgfonlayer}
-      \endgroup
-    }{}
-  }
+\def\snk at 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 at len}{\sankeyqtytolen{\qty}/3}
+      \path[/sankey/debug normal] (\name.center)
+      -- ($(\name.center)!\snk at len pt!90:(\name.right)$)
+      node[/sankey/debug label,rotate=\orient+90+\snk at rotate,anchor=north];
+    \end{pgfonlayer}
+    \endgroup
+  }{}
+}
 %    \end{macrocode}
 % \end{macro}
 % \begin{macro}{\snk at makeforkednode}
@@ -3281,47 +3287,47 @@
 % The \code{\snk at makeforkednode} forks a Sankey node.
 %
 %    \begin{macrocode}
-  \def\snk at makeforkednode{
-    \begingroup
-    \ifdefempty{\snk at listofforks}{
-      \ifdefempty{\snk at forkanchor}{}{
-        \PackageWarning{sankey}%
-        {Can't use 'fork anchor' key without 'forked' key}
-      }
-    }{
-      \def\snk at tot{0}
-      \def\snk at added@values{}
-      \sankeyset{
-        @add forked node/.code args={####1/####2}{
-          \coordinate (####2) at ($(\name.left)%
-          !\fpeval{(\snk at tot+.5*(####1))/\qty}%
-          !(\name.right)$);
-          \edef\snk at orient{\orient}
-          \sankeynode[debug=false]
-          {name=####2,quantity=####1,at=####2,angle=\snk at orient}
-          \edef\snk at tot{\fpeval{\snk at tot+####1}}
-          \edef\snk at added@values{\snk at added@values+####1}
-        },
-        @add forked node/.list/.expand once=\snk at listofforks,
-      }
-      \edef\snk at diff{\fpeval{abs(\qty-\snk at tot)}}
-      \ifnumequal{\snk at diff}{0}{}{
-        \PackageWarning{sankey}%
-        {^^J*** Warning: bad sankey fork: %
-          \qty\space!=\space\snk at added@values(=\snk at tot)%
-          ^^J\snk at listofforks}
-      }
-      \ifdefempty{\snk at forkanchor}{
-        \edef\snk at forkanchor{\name.\snk at anchor}
-      }{}
-      \snk at getpos\snk at c{$(\snk at forkanchor) - (\pos)$}
-      \sankeynode{as=\name,at={$(\name) - (\snk at c)$}}
-      \foreach \snk at subnodeqty/\snk at subnodename in \snk at listofforks {
-        \sankeynode{as=\snk at subnodename,at={$(\snk at subnodename) - (\snk at c)$}}
-      }
+\def\snk at makeforkednode{
+  \begingroup
+  \ifdefempty{\snk at listofforks}{
+    \ifdefempty{\snk at forkanchor}{}{
+      \PackageWarning{sankey}%
+      {Can't use 'fork anchor' key without 'forked' key}
     }
-    \endgroup
+  }{
+    \def\snk at tot{0}
+    \def\snk at added@values{}
+    \sankeyset{
+      @add forked node/.code args={##1/##2}{
+        \coordinate (##2) at ($(\name.left)%
+        !\fpeval{(\snk at tot+.5*(##1))/\qty}%
+        !(\name.right)$);
+        \edef\snk at orient{\orient}
+        \sankeynode[debug=false]
+        {name=##2,quantity=##1,at=##2,angle=\snk at orient}
+        \edef\snk at tot{\fpeval{\snk at tot+##1}}
+        \edef\snk at added@values{\snk at added@values+##1}
+      },
+      @add forked node/.list/.expand once=\snk at listofforks,
+    }
+    \edef\snk at diff{\fpeval{abs(\qty-\snk at tot)}}
+    \ifnumequal{\snk at diff}{0}{}{
+      \PackageWarning{sankey}%
+      {^^J*** Warning: bad sankey fork: %
+        \qty\space!=\space\snk at added@values(=\snk at tot)%
+        ^^J\snk at listofforks}
+    }
+    \ifdefempty{\snk at forkanchor}{
+      \edef\snk at forkanchor{\name.\snk at anchor}
+    }{}
+    \snk at getpos\snk at c{$(\snk at forkanchor) - (\pos)$}
+    \sankeynode{as=\name,at={$(\name) - (\snk at c)$}}
+    \foreach \snk at subnodeqty/\snk at subnodename in \snk at listofforks {
+      \sankeynode{as=\snk at subnodename,at={$(\snk at subnodename) - (\snk at c)$}}
+    }
   }
+  \endgroup
+}
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
@@ -3337,15 +3343,15 @@
 % by default) at \code{\pos} position.
 %
 %    \begin{macrocode}
-  \def\snk at makenode{
-    \begingroup
-    \snk at setnodeqty{\name}{\qty}
-    \edef\orient{\snk at normalize@angle{\orient}}
-    \snk at setnodeorient{\name}{\orient}
-    \ifundef{\snk at anchor}{\def\snk at anchor{center}}{}
-    \node[/sankey/@sankey node={\name}{\pos}{\snk at anchor}];
-    \endgroup
-  }
+\def\snk at makenode{
+  \begingroup
+  \snk at setnodeqty{\name}{\qty}
+  \edef\orient{\snk at normalize@angle{\orient}}
+  \snk at setnodeorient{\name}{\orient}
+  \ifundef{\snk at anchor}{\def\snk at anchor{center}}{}
+  \node[/sankey/@sankey node={\name}{\pos}{\snk at anchor}];
+  \endgroup
+}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -3358,12 +3364,12 @@
 % the Sankey node named \code{\name}.
 %
 %    \begin{macrocode}
-  \def\snk at filldrawstart{
-    \begin{scope}[shift={(\name)},rotate=\orient]
-      \path[/sankey/fill] \snk at getstartfill{\snk at startstyle};
-      \path[/sankey/draw] \snk at getstartdraw{\snk at startstyle};
-    \end{scope}
-  }
+\def\snk at filldrawstart{
+  \begin{scope}[shift={(\name)},rotate=\orient]
+    \path[/sankey/fill] \snk at getstartfill{\snk at startstyle};
+    \path[/sankey/draw] \snk at getstartdraw{\snk at startstyle};
+  \end{scope}
+}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -3376,12 +3382,12 @@
 % the Sankey node named \code{\name}.
 %
 %    \begin{macrocode}
-  \def\snk at filldrawend{
-    \begin{scope}[shift={(\name)},rotate=\sankeygetnodeorient{\name}]
-      \path[/sankey/fill] \snk at getendfill{\snk at endstyle};
-      \path[/sankey/draw] \snk at getenddraw{\snk at endstyle};
-    \end{scope}
-  }
+\def\snk at filldrawend{
+  \begin{scope}[shift={(\name)},rotate=\sankeygetnodeorient{\name}]
+    \path[/sankey/fill] \snk at getendfill{\snk at endstyle};
+    \path[/sankey/draw] \snk at getenddraw{\snk at endstyle};
+  \end{scope}
+}
 %    \end{macrocode}
 % \end{macro}
 %
@@ -3394,19 +3400,19 @@
 % of the macro which requested the verification).
 %
 %    \begin{macrocode}
-  \def\snk at checkquantities##1##2##3{
-    \begingroup
-    \edef\snk at qtyi{\sankeygetnodeqty{##1}}
-    \edef\snk at qtyii{\sankeygetnodeqty{##2}}
-    \ifdefstrequal{\snk at qtyi}{\snk at qtyii}{}{
-      \PackageError{sankey}%
-      {^^J*** \string##3: quantities differ between %
-        ##1 (\snk at qtyi) and ##2 (\snk at qtyii)%
-        ^^J}%
-      {The quantities of the two Sankey nodes must be equal.}
-    }
-    \endgroup
+\def\snk at checkquantities#1#2#3{
+  \begingroup
+  \edef\snk at qtyi{\sankeygetnodeqty{#1}}
+  \edef\snk at qtyii{\sankeygetnodeqty{#2}}
+  \ifdefstrequal{\snk at qtyi}{\snk at qtyii}{}{
+    \PackageError{sankey}%
+    {^^J*** \string#3: quantities differ between %
+      #1 (\snk at qtyi) and #2 (\snk at qtyii)%
+      ^^J}%
+    {The quantities of the two Sankey nodes must be equal.}
   }
+  \endgroup
+}
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
@@ -3416,76 +3422,80 @@
 % \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).
-%
+% The user macros are globally defined as internal (with \code{snk@}
+% prefix) and locally defined in the \code{sankeydiagram} environment as
+% user macros (without the \code{snk@} prefix).
+% 
+% \begin{macro}{\snk at sankeydubins}
+%   
+%   The \code{\snk at 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 at errorifnotdefined{##2}
-    \snk at errorifnotdefined{##3}
-    \snk at 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 at minradius + .5 * \sankeyqtytolen{\qty} pt,
-      },
-    }
-    \dubinspathcalc{sankey,store=sankey}
-    \dubinspathset{
-      left border/.style={
-        sankey, use store=sankey,
-        left and right minimum radii={\snk at minradius}
-        and {\snk at minradius + \sankeyqtytolen{\qty} pt},
-      },
-      right border/.style={
-        sankey, use store=sankey,
-        left and right minimum radii=
-        {\snk at minradius + \sankeyqtytolen{\qty} pt}
-        and {\snk at 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
+\NewDocumentCommand\snk at sankeydubins{O{}mm}{% options, sn, en
+  \snk at errorifnotdefined{#2}
+  \snk at errorifnotdefined{#3}
+  \snk at 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 at minradius + .5 * \sankeyqtytolen{\qty} pt,
+    },
   }
+  \dubinspathcalc{sankey,store=sankey}
+  \dubinspathset{
+    left border/.style={
+      sankey, use store=sankey,
+      left and right minimum radii={\snk at minradius}
+      and {\snk at minradius + \sankeyqtytolen{\qty} pt},
+    },
+    right border/.style={
+      sankey, use store=sankey,
+      left and right minimum radii=
+      {\snk at minradius + \sankeyqtytolen{\qty} pt}
+      and {\snk at 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}{\snk at sankeyoutin}
 %
-% \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 at 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.
-%
+%   The \code{\snk at sankeyoutin} macro links two Sankey nodes via a
+%   Bézier curve.  First, to simulate constant width, it creates
+%   \code{\snk at 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 at errorifnotdefined{##2}
-    \snk at errorifnotdefined{##3}
-    \snk at checkquantities{##2}{##3}{\sankeyoutin}
-    \begingroup
-    \sankeyset{##1}
-    \edef\qty{\sankeygetnodeqty{##2}}
-    \pgfmathsetmacro\snk at len{\sankeyqtytolen{\qty}/2}
-    \edef\snk at step{\fpeval{1/\snk at stepoutin}}
-    \edef\snk at laststep{\inteval{\snk at stepoutin-1}}
-    \path[overlay,decorate,decoration={
+\NewDocumentCommand\snk at sankeyoutin{O{}mm}{% options, sn, en
+  \snk at errorifnotdefined{#2}
+  \snk at errorifnotdefined{#3}
+  \snk at checkquantities{#2}{#3}{\sankeyoutin}
+  \begingroup
+  \sankeyset{#1}
+  \edef\qty{\sankeygetnodeqty{#2}}
+  \pgfmathsetmacro\snk at len{\sankeyqtytolen{\qty}/2}
+  \edef\snk at step{\fpeval{1/\snk at stepoutin}}
+  \edef\snk at laststep{\inteval{\snk at stepoutin-1}}
+  \path[overlay,decorate,decoration={
       markings,
       mark=between positions \snk at step and {\fpeval{1-.5*\snk at step}}
       step \snk at step with {
@@ -3500,533 +3510,563 @@
         ;
       }
     }]
-    (##2.center)
-    to[out=\sankeygetnodeorient{##2},in=\sankeygetnodeorient{##3}+180]
-    (##3.center);
-    \foreach \snk at ptnum in {1,...,\snk at laststep}{
-      \edef\snk at outinmidptname{snk at outinmidpt-\snk at ptnum}
-      \dbp at anglebetween\snk at outinmidptangle%
-      {\snk at outinmidptname-r}{\snk at outinmidptname-l}
-      \sankeynode[debug=false]{%
-        name=\snk at outinmidptname,
-        quantity=\qty,
-        angle=\snk at outinmidptangle-90,%
-        at=\snk at outinmidptname%
-      }
-    }
+  (#2.center)
+  to[out=\sankeygetnodeorient{#2},in=\sankeygetnodeorient{#3}+180]
+  (#3.center);
+  \foreach \snk at ptnum in {1,...,\snk at laststep}{
+    \edef\snk at outinmidptname{snk at outinmidpt-\snk at ptnum}
+    \dbp at anglebetween\snk at outinmidptangle%
+    {\snk at outinmidptname-r}{\snk at outinmidptname-l}
     \sankeynode[debug=false]{%
-      name={snk at outinmidpt-0},
-      quantity=\sankeygetnodeqty{##2},
-      angle=\sankeygetnodeorient{##2},%
-      at={##2}%
+      name=\snk at outinmidptname,
+      quantity=\qty,
+      angle=\snk at outinmidptangle-90,%
+      at=\snk at outinmidptname%
     }
-    \sankeynode[debug=false]{%
-      name={snk at outinmidpt-\snk at stepoutin},
-      quantity={\sankeygetnodeqty{##3}},
-      angle={\sankeygetnodeorient{##3}},%
-      at={##3}%
-    }
-    \path[/sankey/fill,looseness=1]
-    (snk at outinmidpt-0.left)
-    \foreach \snk at curpt
-    [remember=\snk at curpt as \snk at prevpt (initially 0)]
-    in {1,...,\snk at stepoutin}{
-      to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt},
+  }
+  \sankeynode[debug=false]{%
+    name={snk at outinmidpt-0},
+    quantity=\sankeygetnodeqty{#2},
+    angle=\sankeygetnodeorient{#2},%
+    at={#2}%
+  }
+  \sankeynode[debug=false]{%
+    name={snk at outinmidpt-\snk at stepoutin},
+    quantity={\sankeygetnodeqty{#3}},
+    angle={\sankeygetnodeorient{#3}},%
+    at={#3}%
+  }
+  \path[/sankey/fill,looseness=1]
+  (snk at outinmidpt-0.left)
+  \foreach \snk at curpt
+  [remember=\snk at curpt as \snk at prevpt (initially 0)]
+  in {1,...,\snk at stepoutin}{
+    to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt},
       in=\sankeygetnodeorient{snk at outinmidpt-\snk at curpt}+180]
-      (snk at outinmidpt-\snk at curpt.left)
-    }
-    --
-    (snk at outinmidpt-\snk at stepoutin.right)
-    \foreach \snk at curpt
-    [remember=\snk at curpt as \snk at prevpt (initially \snk at stepoutin)]
-    in {\snk at laststep,...,0}{
-      to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt}+180,
+    (snk at outinmidpt-\snk at curpt.left)
+  }
+  --
+  (snk at outinmidpt-\snk at stepoutin.right)
+  \foreach \snk at curpt
+  [remember=\snk at curpt as \snk at prevpt (initially \snk at stepoutin)]
+  in {\snk at laststep,...,0}{
+    to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt}+180,
       in=\sankeygetnodeorient{snk at outinmidpt-\snk at curpt}]
-      (snk at outinmidpt-\snk at curpt.right)
-    }
-    -- cycle;
-    \path[/sankey/draw,looseness=1]
-    (snk at outinmidpt-0.left)
-    \foreach \snk at curpt
-    [remember=\snk at curpt as \snk at prevpt (initially 0)]
-    in {1,...,\snk at stepoutin}{
-      to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt},
+    (snk at outinmidpt-\snk at curpt.right)
+  }
+  -- cycle;
+  \path[/sankey/draw,looseness=1]
+  (snk at outinmidpt-0.left)
+  \foreach \snk at curpt
+  [remember=\snk at curpt as \snk at prevpt (initially 0)]
+  in {1,...,\snk at stepoutin}{
+    to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt},
       in=\sankeygetnodeorient{snk at outinmidpt-\snk at curpt}+180]
-      (snk at outinmidpt-\snk at curpt.left)
-    }
-    (snk at outinmidpt-\snk at stepoutin.right)
-    \foreach \snk at curpt
-    [remember=\snk at curpt as \snk at prevpt (initially \snk at stepoutin)]
-    in {\snk at laststep,...,0}{
-      to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt}+180,
+    (snk at outinmidpt-\snk at curpt.left)
+  }
+  (snk at outinmidpt-\snk at stepoutin.right)
+  \foreach \snk at curpt
+  [remember=\snk at curpt as \snk at prevpt (initially \snk at stepoutin)]
+  in {\snk at laststep,...,0}{
+    to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt}+180,
       in=\sankeygetnodeorient{snk at outinmidpt-\snk at curpt}]
-      (snk at outinmidpt-\snk at curpt.right)
-    };
-    \endgroup
-  }
+    (snk at outinmidpt-\snk at curpt.right)
+  };
+  \endgroup
+}
 %    \end{macrocode}
 % \end{macro}
-% \begin{macro}{\sankeynodealias}
+% \begin{macro}{\snk at sankeynodealias}
+%   
+%   The \code{\snk at sankeynodealias} macro clones the Sankey node named
+%   \code{#1} into a Sankey node named \code{#2}.
 %
-% 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 at errorifnotdefined{##1}
-    \path[late options={name=##1,alias=##2}];
-    \snk at setnodeqty{##2}{\sankeygetnodeqty{##1}}
-    \snk at setnodeorient{##2}{\sankeygetnodeorient{##1}}
-  }
+\NewDocumentCommand\snk at sankeynodealias{mm}{%name, alias
+  \snk at errorifnotdefined{#1}
+  \path[late options={name=#1,alias=#2}];
+  \snk at setnodeqty{#2}{\sankeygetnodeqty{#1}}
+  \snk at setnodeorient{#2}{\sankeygetnodeorient{#1}}
+}
 %    \end{macrocode}
 % \end{macro}
-%
-% \begin{macro}{\sankeynode}
-%
-% The \code{\sankeynode} macro creates the new Sankey
-% node named \code{#2}.
-%
+% 
+% \begin{macro}{\snk at sankeynode}
+%   
+%   The \code{\snk at 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, at initial parameters,/sankey/every node,##2}
-    \snk at makenode{}
-    \snk at makeforkednode{}
-    \iftoggle{sankey node start}{\snk at filldrawstart}{}
-    \iftoggle{sankey node end}{\snk at filldrawend}{}
-    \snk at show@debug{\name}
-    \endgroup
-  }
+\NewDocumentCommand\snk at sankeynode{O{}m}{% options, node parameters
+  \begingroup
+  \sankeyset{#1}
+  \sankeyset{node parameters, at initial parameters,/sankey/every node,#2}
+  \snk at makenode{}
+  \snk at makeforkednode{}
+  \iftoggle{sankey node start}{\snk at filldrawstart}{}
+  \iftoggle{sankey node end}{\snk at filldrawend}{}
+  \snk at show@debug{\name}
+  \endgroup
+}
 %    \end{macrocode}
 % \end{macro}
+% 
+% \begin{macro}{\snk at sankeystart}
+%   
+%   The \code{\snk at sankeystart} macro fills and draws a starting lane
+%   attached to the Sankey node named \code{#2}.
 %
-% \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 at errorifnotdefined{##2}
-    \begingroup
-    \sankeyset{##1}
-    \edef\name{##2}
-    \edef\orient{\sankeygetnodeorient{##2}}
-    \edef\qty{\sankeygetnodeqty{##2}}
-    \snk at filldrawstart
-    \endgroup
-  }
+\NewDocumentCommand\snk at sankeystart{O{}m}{% options, name
+  \snk at errorifnotdefined{#2}
+  \begingroup
+  \sankeyset{#1}
+  \edef\name{#2}
+  \edef\orient{\sankeygetnodeorient{#2}}
+  \edef\qty{\sankeygetnodeqty{#2}}
+  \snk at 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{macro}{\snk at sankeynodestart}
+%   
+%   The \code{\snk at 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}
-  }
+\NewDocumentCommand\snk at 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{macro}{\snk at sankeyend}
+%   
+%   The \code{\snk at 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 at errorifnotdefined{##2}
-    \begingroup
-    \sankeyset{##1}
-    \edef\name{##2}
-    \edef\orient{\sankeygetnodeorient{##2}}
-    \edef\qty{\sankeygetnodeqty{##2}}
-    \snk at filldrawend
-    \endgroup
-  }
+\NewDocumentCommand\snk at sankeyend{O{}m}{%options, name
+  \snk at errorifnotdefined{#2}
+  \begingroup
+  \sankeyset{#1}
+  \edef\name{#2}
+  \edef\orient{\sankeygetnodeorient{#2}}
+  \edef\qty{\sankeygetnodeqty{#2}}
+  \snk at 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{macro}{\snk at sankeynodeend}
+%   
+%   The \code{\snk at 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}
-  }
+\NewDocumentCommand\snk at sankeynodeend{O{}m}{% options, node parameters
+  \sankeynode[#1]{end,#2}
+}
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\sankeyadvance}
-% \begin{macro}{\sankeyadvance*}
+% \begin{macro}{\snk at init@move}
 %
-% 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}.
+%   \changes{v3.0.2}{2025/10/10}{Factorization of the node move initialization code}
 %
+%   The \code{\snk at init@move} macro applies options et clones the
+%   current node before its moving.
+%
 %    \begin{macrocode}
-  \NewDocumentCommand\sankeyadvance{sO{}mm}{%
-    %params: *(reverse), options, name, distance
-    \snk at errorifnotdefined{##3}
-    \begingroup
-    \sankeyset{##2}
-    \edef\name{##3}
-    \edef\snk at oldname{##3-old}
-    \sankeynodealias{\name}{\snk at oldname}
-    \IfBooleanTF{##1}{
-      % move backward
-      \sankeynode{
-        at={$(\snk at oldname.center)!##4!90:(\snk at oldname.left)$},
-        angle=\sankeygetnodeorient{\snk at oldname},
-        quantity=\sankeygetnodeqty{\snk at oldname},
-        name=\name,
-      }
-      \path[/sankey/fill]
-      (\name.left) -- (\snk at oldname.left)
-      -- (\snk at oldname.right) -- (\name.right) -- cycle;
-      \path[/sankey/draw]
-      (\name.left) -- (\snk at oldname.left)
-      (\snk at oldname.right) -- (\name.right);
-    }{
-      % move forward
-      \sankeynode{
-        at={$(\snk at oldname.center)!##4!-90:(\snk at oldname.left)$},
-        angle=\sankeygetnodeorient{\snk at oldname},
-        quantity=\sankeygetnodeqty{\snk at oldname},
-        name=\name,
-      }
-      \path[/sankey/fill]
-      (\snk at oldname.left) -- (\name.left)
-      -- (\name.right) -- (\snk at oldname.right) -- cycle;
-      \path[/sankey/draw]
-      (\snk at oldname.left) -- (\name.left)
-      (\name.right) -- (\snk at oldname.right);
-    }
-    \snk at show@debug{\name}
-    \endgroup
-  }
+\def\snk at init@move#1#2{% params: options, name
+  \sankeyset{#1}
+  \edef\name{#2}
+  \edef\snk at oldname{#2-old}
+  \sankeynodealias{\name}{\snk at oldname}
+  \edef\qty{\sankeygetnodeqty{\name}}
+}
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
-% \begin{macro}{\sankeyturnright}
-% \begin{macro}{\sankeyturnright*}
 %
-% \changes{v3.0}{2021/03/14}{new macro}
+% \begin{macro}{\snk at sankeyadvance}
 %
-% 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}.
-%
+%   The \code{\snk at 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\sankeyturnright{sO{}mm}{
-    % *(reverse), options, name, angle
-    \snk at errorifnotdefined{##3}
-    \begingroup
-    \IfBooleanTF{##1}
-    {\edef\snk at angle{\fpeval{-1*##4}}}
-    {\edef\snk at angle{\fpeval{1*##4}}}
-    \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
-    \ifnumgreater{\snk at anglesign}{-1}{
-      \sankeyset{##2}
-      \edef\name{##3}
-      \edef\snk at oldname{##3-old}
-      \sankeynodealias{\name}{\snk at oldname}
-      \edef\qty{\sankeygetnodeqty{\name}}
-      \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}-\snk at angle}}
-      \snk at getpos\snk at c{$(\name.right)!-\snk at minradius!(\name.left)$}
-      \snk at getpos\pos{$(\snk at c)!1!-\snk at angle:(\name.center)$}
-      \snk at makenode{}
-      % fill the region
-      \path[/sankey/fill] let
-      \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
-      \p3=(\name.left),\p4=(\name.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1},
-      \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient+\snk at angle+90:\orient+90:\n{maxr}) -- (\p3) --
-      (\p4) arc(\orient+90:\orient+\snk at angle+90:\n{minr}) -- (\p2) -- cycle;
-      % draw left and right borders
-      \path[/sankey/draw] let
-      \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
-      \p3=(\name.left),\p4=(\name.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1},
-      \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient+\snk at angle+90:\orient+90:\n{maxr}) 
-      (\p4) arc(\orient+90:\orient+\snk at angle+90:\n{minr});
-      \snk at show@debug{\name}
-    }{
-      \sankeyturnrightbackward[##2]{##3}{-1*\snk at angle}
+\NewDocumentCommand\snk at sankeyadvance{sO{}mm}{%
+  % params: *(reverse), options, name, distance
+  \snk at errorifnotdefined{#3}
+  \begingroup
+  \snk at init@move{#2}{#3}
+  \IfBooleanTF{#1}{
+    % move backward
+    \sankeynode{
+      at={$(\snk at oldname.center)!#4!90:(\snk at oldname.left)$},
+      angle=\sankeygetnodeorient{\snk at oldname},
+      quantity=\sankeygetnodeqty{\snk at oldname},
+      name=\name,
     }
-    \endgroup
+    \path[/sankey/fill]
+    (\name.left) -- (\snk at oldname.left)
+    -- (\snk at oldname.right) -- (\name.right) -- cycle;
+    \path[/sankey/draw]
+    (\name.left) -- (\snk at oldname.left)
+    (\snk at oldname.right) -- (\name.right);
+  }{
+    % move forward
+    \sankeynode{
+      at={$(\snk at oldname.center)!#4!-90:(\snk at oldname.left)$},
+      angle=\sankeygetnodeorient{\snk at oldname},
+      quantity=\sankeygetnodeqty{\snk at oldname},
+      name=\name,
+    }
+    \path[/sankey/fill]
+    (\snk at oldname.left) -- (\name.left)
+    -- (\name.right) -- (\snk at oldname.right) -- cycle;
+    \path[/sankey/draw]
+    (\snk at oldname.left) -- (\name.left)
+    (\name.right) -- (\snk at oldname.right);
   }
+  \snk at show@debug{\name}
+  \endgroup
+}
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
+% \begin{macro}{\snk at 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{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 at errorifnotdefined{##3}
-    \begingroup
-    \IfBooleanTF{##1}
-    {\edef\snk at angle{\fpeval{-1*##4}}}
-    {\edef\snk at angle{\fpeval{1*##4}}}
-    \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
-    \ifnumgreater{\snk at anglesign}{-1}{
-      \sankeyset{##2}
-      \edef\name{##3}
-      \edef\snk at oldname{##3-old}
-      \sankeynodealias{\name}{\snk at oldname}
-      \edef\qty{\sankeygetnodeqty{\name}}
-      \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}+\snk at angle}}
-      \snk at getpos\snk at c{$(\name.right)!-\snk at minradius!(\name.left)$}
-      \snk at getpos\pos{$(\snk at c)!1!\snk at angle:(\name.center)$}
-      \snk at makenode{}
-      % fill the region
-      \path[/sankey/fill] let
-      \p1=(\name.left),\p2=(\name.right),
-      \p3=(\snk at oldname.left),\p4=(\snk at oldname.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient+90:\orient-\snk at angle+90:\n{maxr}) -- (\p3) --
-      (\p4) arc(\orient-\snk at 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 at oldname.left),\p4=(\snk at oldname.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient+90:\orient-\snk at angle+90:\n{maxr}) 
-      (\p4) arc(\orient-\snk at angle+90:\orient+90:\n{minr});
-      \snk at show@debug{\name}
-    }{
-      \sankeyturnright[##2]{##3}{-1*\snk at angle}
-    }
-    \endgroup
+\NewDocumentCommand\snk at sankeyturnright{sO{}mm}{
+  % *(reverse), options, name, angle
+  \snk at errorifnotdefined{#3}
+  \begingroup
+  \IfBooleanTF{#1}
+  {\edef\snk at angle{\fpeval{-1*#4}}}
+  {\edef\snk at angle{\fpeval{1*#4}}}
+  \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
+  \ifnumgreater{\snk at anglesign}{-1}{
+    \snk at init@move{#2}{#3}
+    \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}-\snk at angle}}
+    \snk at getpos\snk at c{$(\name.right)!-\snk at minradius!(\name.left)$}
+    \snk at getpos\pos{$(\snk at c)!1!-\snk at angle:(\name.center)$}
+    \snk at makenode{}
+    % fill the region
+    \path[/sankey/fill] let
+    \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
+    \p3=(\name.left),\p4=(\name.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1},
+    \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient+\snk at angle+90:\orient+90:\n{maxr}) -- (\p3) --
+    (\p4) arc(\orient+90:\orient+\snk at angle+90:\n{minr}) -- (\p2) -- cycle;
+    % draw left and right borders
+    \path[/sankey/draw] let
+    \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
+    \p3=(\name.left),\p4=(\name.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1},
+    \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient+\snk at angle+90:\orient+90:\n{maxr}) 
+    (\p4) arc(\orient+90:\orient+\snk at angle+90:\n{minr});
+    \snk at show@debug{\name}
+  }{
+    \sankeyturnrightbackward[#2]{#3}{-1*\snk at angle}
   }
+  \endgroup
+}
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
-% \begin{macro}{\sankeyturnleft}
-% \begin{macro}{\sankeyturnleft*}
+% 
+% \begin{macro}{\snk at sankeyturnrightbackward}
+%   
+%   \changes{v3.0}{2021/03/14}{New macro}
+%   
+%   The \code{\snk at 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}.
 %
-% \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 at errorifnotdefined{##3}
-    \begingroup
-    \IfBooleanTF{##1}
-    {\edef\snk at angle{\fpeval{-1*##4}}}
-    {\edef\snk at angle{\fpeval{1*##4}}}
-    \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
-    \ifnumgreater{\snk at anglesign}{-1}{
-      \sankeyset{##2}
-      \edef\name{##3}
-      \edef\snk at oldname{##3-old}
-      \sankeynodealias{\name}{\snk at oldname}
-      \edef\qty{\sankeygetnodeqty{\name}}
-      \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}+\snk at angle}}
-      \snk at getpos\snk at c{$(\name.left)!-\snk at minradius!(\name.right)$}
-      \snk at getpos\pos{$(\snk at c)!1!\snk at angle:(\name.center)$}
-      \snk at makenode{}
-      % fill the region
-      \path[/sankey/fill] let
-      \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
-      \p3=(\name.left),\p4=(\name.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient-\snk at angle-90:\orient-90:\n{minr}) -- (\p3) --
-      (\p4) arc(\orient-90:\orient-\snk at angle-90:\n{maxr}) -- (\p2) -- cycle;
-      % draw left and right borders
-      \path[/sankey/draw] let
-      \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
-      \p3=(\name.left),\p4=(\name.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient-\snk at angle-90:\orient-90:\n{minr}) 
-      (\p4) arc(\orient-90:\orient-\snk at angle-90:\n{maxr});
-      \snk at show@debug{\name}
-    }{
-      \sankeyturnleftbackward[##2]{##3}{-1*\snk at angle}
-    }
-    \endgroup
+\NewDocumentCommand\snk at sankeyturnrightbackward{sO{}mm}{
+  % *(reverse), options, name, angle
+  \snk at errorifnotdefined{#3}
+  \begingroup
+  \IfBooleanTF{#1}
+  {\edef\snk at angle{\fpeval{-1*#4}}}
+  {\edef\snk at angle{\fpeval{1*#4}}}
+  \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
+  \ifnumgreater{\snk at anglesign}{-1}{
+    \snk at init@move{#2}{#3}
+    \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}+\snk at angle}}
+    \snk at getpos\snk at c{$(\name.right)!-\snk at minradius!(\name.left)$}
+    \snk at getpos\pos{$(\snk at c)!1!\snk at angle:(\name.center)$}
+    \snk at makenode{}
+    % fill the region
+    \path[/sankey/fill] let
+    \p1=(\name.left),\p2=(\name.right),
+    \p3=(\snk at oldname.left),\p4=(\snk at oldname.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient+90:\orient-\snk at angle+90:\n{maxr}) -- (\p3) --
+    (\p4) arc(\orient-\snk at 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 at oldname.left),\p4=(\snk at oldname.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient+90:\orient-\snk at angle+90:\n{maxr}) 
+    (\p4) arc(\orient-\snk at angle+90:\orient+90:\n{minr});
+    \snk at show@debug{\name}
+  }{
+    \sankeyturnright[#2]{#3}{-1*\snk at angle}
   }
+  \endgroup
+}
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
-% \begin{macro}{\sankeyturnleftbackward}
-% \begin{macro}{\sankeyturnleftbackward*}
+% \begin{macro}{\snk at sankeyturnleft}
+%   
+%   \changes{v3.0}{2021/03/14}{New macro}
+%   
+%   The \code{\snk at 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}.
 %
-% \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 at errorifnotdefined{##3}
-    \begingroup
-    \IfBooleanTF{##1}
-    {\edef\snk at angle{\fpeval{-1*##4}}}
-    {\edef\snk at angle{\fpeval{1*##4}}}
-    \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
-    \ifnumgreater{\snk at anglesign}{-1}{
-      \sankeyset{##2}
-      \edef\name{##3}
-      \edef\snk at oldname{##3-old}
-      \sankeynodealias{\name}{\snk at oldname}
-      \edef\qty{\sankeygetnodeqty{\name}}
-      \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}-\snk at angle}}
-      \snk at getpos\snk at c{$(\name.left)!-\snk at minradius!(\name.right)$}
-      \snk at getpos\pos{$(\snk at c)!1!-\snk at angle:(\name.center)$}
-      \snk at makenode{}
-      % fill the region
-      \path[/sankey/fill] let
-      \p1=(\name.left),\p2=(\name.right),
-      \p3=(\snk at oldname.left),\p4=(\snk at oldname.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient-90:\orient+\snk at angle-90:\n{minr}) -- (\p3) --
-      (\p4) arc(\orient+\snk at 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 at oldname.left),\p4=(\snk at oldname.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient-90:\orient+\snk at angle-90:\n{minr}) 
-      (\p4) arc(\orient+\snk at angle-90:\orient-90:\n{maxr});
-      \snk at show@debug{\name}
-    }{
-      \sankeyturnleft[##2]{##3}{-1*\snk at angle}
-    }
-    \endgroup
+\NewDocumentCommand\snk at sankeyturnleft{sO{}mm}{
+  % *(reverse), options, name, angle
+  \snk at errorifnotdefined{#3}
+  \begingroup
+  \IfBooleanTF{#1}
+  {\edef\snk at angle{\fpeval{-1*#4}}}
+  {\edef\snk at angle{\fpeval{1*#4}}}
+  \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
+  \ifnumgreater{\snk at anglesign}{-1}{
+    \snk at init@move{#2}{#3}
+    \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}+\snk at angle}}
+    \snk at getpos\snk at c{$(\name.left)!-\snk at minradius!(\name.right)$}
+    \snk at getpos\pos{$(\snk at c)!1!\snk at angle:(\name.center)$}
+    \snk at makenode{}
+    % fill the region
+    \path[/sankey/fill] let
+    \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
+    \p3=(\name.left),\p4=(\name.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient-\snk at angle-90:\orient-90:\n{minr}) -- (\p3) --
+    (\p4) arc(\orient-90:\orient-\snk at angle-90:\n{maxr}) -- (\p2) -- cycle;
+    % draw left and right borders
+    \path[/sankey/draw] let
+    \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
+    \p3=(\name.left),\p4=(\name.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient-\snk at angle-90:\orient-90:\n{minr}) 
+    (\p4) arc(\orient-90:\orient-\snk at angle-90:\n{maxr});
+    \snk at show@debug{\name}
+  }{
+    \sankeyturnleftbackward[#2]{#3}{-1*\snk at angle}
   }
+  \endgroup
+}
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
-% \begin{macro}{\sankeyturn}
-% \begin{macro}{\sankeyturn*}
+% \begin{macro}{\snk at sankeyturnleftbackward}
 %
-% \changes{v3.0}{2021/03/14}{simplification by using new \emph{turn} macros}
+%   \changes{v3.0}{2021/03/14}{New macro}
+% 
+%   The \code{\snk at 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}.
 %
-% 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 at errorifnotdefined{##3}
-    \begingroup
-    \edef\snk at anglesign{\fpeval{sign(##4)}}
-    \IfBooleanTF{##1}{
-      \ifnumgreater{\snk at anglesign}{-1}
-      {\sankeyturnleftbackward[##2]{##3}{##4}}
-      {\sankeyturnrightbackward[##2]{##3}{-1*##4}}
-    }{
-      \ifnumgreater{\snk at anglesign}{-1}
-      {\sankeyturnleft[##2]{##3}{##4}}
-      {\sankeyturnright[##2]{##3}{-1*##4}}
-    }
-    \endgroup
+\NewDocumentCommand\snk at sankeyturnleftbackward{sO{}mm}{
+  % *(reverse), options, name, angle
+  \snk at errorifnotdefined{#3}
+  \begingroup
+  \IfBooleanTF{#1}
+  {\edef\snk at angle{\fpeval{-1*#4}}}
+  {\edef\snk at angle{\fpeval{1*#4}}}
+  \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
+  \ifnumgreater{\snk at anglesign}{-1}{
+    \snk at init@move{#2}{#3}
+    \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}-\snk at angle}}
+    \snk at getpos\snk at c{$(\name.left)!-\snk at minradius!(\name.right)$}
+    \snk at getpos\pos{$(\snk at c)!1!-\snk at angle:(\name.center)$}
+    \snk at makenode{}
+    % fill the region
+    \path[/sankey/fill] let
+    \p1=(\name.left),\p2=(\name.right),
+    \p3=(\snk at oldname.left),\p4=(\snk at oldname.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient-90:\orient+\snk at angle-90:\n{minr}) -- (\p3) --
+    (\p4) arc(\orient+\snk at 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 at oldname.left),\p4=(\snk at oldname.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient-90:\orient+\snk at angle-90:\n{minr}) 
+    (\p4) arc(\orient+\snk at angle-90:\orient-90:\n{maxr});
+    \snk at show@debug{\name}
+  }{
+    \sankeyturnleft[#2]{#3}{-1*\snk at angle}
   }
+  \endgroup
+}
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
-% \begin{macro}{\sankeyfork}
+% \begin{macro}{\snk at sankeyturn}
+%   
+%   \changes{v3.0}{2021/03/14}{Simplification by using new \emph{turn} macros}
+%   
+%   The \code{\snk at 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}.
 %
-% 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 at errorifnotdefined{##2}
-    \begingroup
-    \sankeyset{##1}
-    \sankeynode[debug=false]{as={##2},forked={##3}}
-    \foreach \qty/\snk at subnodename in {##3}{\sankeynode{as={\snk at subnodename}}}
-    \endgroup
+\NewDocumentCommand\snk at sankeyturn{sO{}mm}{%
+  % *(reverse), options, name, angle
+  \snk at errorifnotdefined{#3}
+  \begingroup
+  \edef\snk at anglesign{\fpeval{sign(#4)}}
+  \IfBooleanTF{#1}{
+    \ifnumgreater{\snk at anglesign}{-1}
+    {\sankeyturnleftbackward[#2]{#3}{#4}}
+    {\sankeyturnrightbackward[#2]{#3}{-1*#4}}
+  }{
+    \ifnumgreater{\snk at anglesign}{-1}
+    {\sankeyturnleft[#2]{#3}{#4}}
+    {\sankeyturnright[#2]{#3}{-1*#4}}
   }
+  \endgroup
+}
 %    \end{macrocode}
 % \end{macro}
-% \begin{macro}{\sankeyqtytolen}
+% \begin{macro}{\snk at sankeyfork}
+%   
+%   The \code{\snk at 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\snk at sankeyfork{O{}mm}{%options, name, list of forks
+  \snk at errorifnotdefined{#2}
+  \begingroup
+  \sankeyset{#1}
+  \sankeynode[debug=false]{as={#2},forked={#3}}
+  \foreach \qty/\snk at subnodename in {#3}{\sankeynode{as={\snk at subnodename}}}
+  \endgroup
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\snk at sankeyqtytolen}
+%   
+%   The \code{\snk at sankeyqtytolen} macro converts quantity to length
+%   using \code{\fpeval} and the ratio determined by
+%   \code{\snk at totalqty} and \code{\snk at totallen}.
 %
-% The \code{\sankeyqtytolen} macro converts quantity
-% to length using \code{\fpeval} and the ratio determined
-% by \code{\snk at totalqty} and \code{\snk at totallen}.
-%
 %    \begin{macrocode}
-  \def\sankeyqtytolen##1{\fpeval{(##1)/\snk at totalqty*\snk at totallen}}
+\NewExpandableDocumentCommand\snk at sankeyqtytolen{m}{%
+  \fpeval{(#1)/\snk at totalqty*\snk at totallen}%
+}
 %    \end{macrocode}
 % \end{macro}
 %
 %^^A % ------------------------------------------------------------
-% \subsection{The \protect\texttt{sankeydiagram} environment (the end)}
+% \subsection{The \protect\ttintitle{sankeydiagram} environment}
 %^^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{environment}{sankeydiagram}
+%
+%   \changes{v3.0.2}{2025/01/10}{Simplification of the environment by copying internal macros}
+%
+%   The \code{sankeydiagram} environment allows the creation of Sankey
+%   diagrams.
+%   
+%   \DescribeMacro{\sankeyadvance}%
+%   \DescribeMacro{\sankeydubins}%
+%   \DescribeMacro{\sankeyend}%
+%   \DescribeMacro{\sankeyfork}%
+%   \DescribeMacro{\sankeynodealias}%
+%   \DescribeMacro{\sankeynodeend}%
+%   \DescribeMacro{\sankeynodestart}%
+%   \DescribeMacro{\sankeynode}%
+%   \DescribeMacro{\sankeyoutin}%
+%   \DescribeMacro{\sankeyqtytolen}%
+%   \DescribeMacro{\sankeystart}%
+%   \DescribeMacro{\sankeyturnleftbackward}%
+%   \DescribeMacro{\sankeyturnleft}%
+%   \DescribeMacro{\sankeyturnrightbackward}%
+%   \DescribeMacro{\sankeyturnright}%
+%   \DescribeMacro{\sankeyturn}%
+%   It 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{}}{
+  \NewCommandCopy{\sankeyadvance}{\snk at sankeyadvance}
+  \NewCommandCopy{\sankeydubins}{\snk at sankeydubins}
+  \NewCommandCopy{\sankeyend}{\snk at sankeyend}
+  \NewCommandCopy{\sankeyfork}{\snk at sankeyfork}
+  \NewCommandCopy{\sankeynodealias}{\snk at sankeynodealias}
+  \NewCommandCopy{\sankeynodeend}{\snk at sankeynodeend}
+  \NewCommandCopy{\sankeynodestart}{\snk at sankeynodestart}
+  \NewCommandCopy{\sankeynode}{\snk at sankeynode}
+  \NewCommandCopy{\sankeyoutin}{\snk at sankeyoutin}
+  \NewCommandCopy{\sankeyqtytolen}{\snk at sankeyqtytolen}
+  \NewCommandCopy{\sankeystart}{\snk at sankeystart}
+  \NewCommandCopy{\sankeyturnleftbackward}{\snk at sankeyturnleftbackward}
+  \NewCommandCopy{\sankeyturnleft}{\snk at sankeyturnleft}
+  \NewCommandCopy{\sankeyturnrightbackward}{\snk at sankeyturnrightbackward}
+  \NewCommandCopy{\sankeyturnright}{\snk at sankeyturnright}
+  \NewCommandCopy{\sankeyturn}{\snk at sankeyturn}
   \sankeyset{
     @initial options,
     every diagram,
@@ -4097,7 +4137,7 @@
 % \fi
 %
 %^^A % ------------------------------------------------------------
-% \section{\texttt{tikzlibrarydubins.code.tex}}
+% \section{\ttintitle{tikzlibrarydubins.code.tex}}
 %^^A % ------------------------------------------------------------
 %
 % Not yet documented nor commented...
@@ -4108,8 +4148,8 @@
 % \begin{macro}{\tikzlibrarydubins at version}
 % \begin{macro}{\tikzlibrarydubins at date}
 %    \begin{macrocode}
-\def\tikzlibrarydubins at version{v3.0.1}
-\def\tikzlibrarydubins at date{2022/02/04}
+\def\tikzlibrarydubins at version{v3.0.2}
+\def\tikzlibrarydubins at date{2025/01/10}
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
@@ -4453,7 +4493,8 @@
       +\dbp at rsrlen
       +angtodist(\dbp at rsrangtwo,\dbp at radius)
     }
-    \dbp at setparams{rsr}{\dbp at rsrdist}{\dbp at rsrangone}{\dbp at rsrlen}{\dbp at rsrangtwo}
+    \dbp at setparams%
+    {rsr}{\dbp at rsrdist}{\dbp at rsrangone}{\dbp at rsrlen}{\dbp at rsrangtwo}
     
     % LSL (al and bl)
     \dbp at anglebetween\dbp at lslalbl{\p{al}}{\p{bl}}
@@ -4564,21 +4605,29 @@
 %
 % \PrintChanges
 %
-% \setcounter{IndexColumns}{2}
-% \PrintIndex
+% {
+%   \setcounter{IndexColumns}{2}
+%   \let\code\relax
+%   \IndexPrologue{\section{Index} Italic numbers refer page where the
+%   corresponding entry is described; Underlined numbers refer to the
+%   code line of the definition; Roman numbers refer to the code lines
+%   where the entry is used.}
 %
+%   \PrintIndex
+% }
 % \Finale
 %
 % \iffalse
-%<*sankeydocpreamble>
+%<*sankey-doc-preamble>
 \usepackage[paper=a4paper,vmargin=1.5cm,left=4.5cm,right=3.5cm,marginparwidth=3.5cm]{geometry}
 \usepackage[utf8]{inputenc}
 \usepackage{cmap}
 \usepackage[T1]{fontenc}
 \usepackage{lmodern}
+\usepackage{inconsolata}
 \usepackage[final,protrusion=true,expansion=true]{microtype}
 \usepackage{xcolor}
-\PassOptionsToPackage{final,colorlinks,linkcolor=red!60!orange!85!black}{hyperref}
+\PassOptionsToPackage{final,colorlinks,linkcolor=cyan!25!blue!75!black}{hyperref}
 \usepackage{dtxdescribe}
 \usepackage[numbered]{hypdoc}
 \usepackage{fancyvrb}
@@ -4743,17 +4792,17 @@
   % \vspace{.25\baselineskip plus .25\baselineskip minus 0mm}
   \parfillskip 0pt plus 1fil%
   \leavevmode%
-  \DescribeKey{\key}%
+  \expandafter\DescribeKey\expandafter{\key}%
   \ttfamily%
   %\hspace*{-1cm}%
   \textcolor{red!75!black}{\texttt{\docprefix{\keypath/}\key}}%
   \ifdefempty{\val}{}{=\val}%
   \hfill%
-  \ifdefempty{\default}{\null}{(default:\,\constant{\default})}%
-  \ifdefempty{\initially}{\null}{(initially:\,\constant{\initially})}%
+  \ifdefempty{\default}{\null}{{\rmfamily (default:\,\constant{\default})}}%
+  \ifdefempty{\initially}{\null}{{\rmfamily (initially:\,\constant{\initially})}}%
   \mynobreakpar%
   \endgroup%
-  \parskip=.5\baselineskip plus .25\baselineskip minus .25\baselineskip
+  \parskip=.5\baselineskip plus .25\baselineskip minus .3\baselineskip
   \parfillskip=30pt plus 1fil
   \itemize[topsep=0pt,partopsep=0pt,itemsep=0pt]\item[]
 }{%
@@ -4809,37 +4858,7 @@
   \footnotesize
 }
 
-\renewcommand*{\DescribeMacro}[2][]{%
-  \@bsphack%
-  \@ifundefined{@captype}{% not float?
-    \leavevmode%
-    \marginpar{%
-      \hbadness=10000%
-      \hfuzz=5em%
-      \raggedleft%
-      \ifblank{#1}{}{{\scriptsize\textsf{[#1]}} }% class
-      \MacroFont\cmd{#2}% name
-    }% marginpar
-  }{}% not float?
-  \begingroup%
-  \DTXD at origwrindex{%
-    \DTXD at macroname{#2}\actualchar\DTXD at verbatimcmd{#2}% name
-    \ifblank{#1}{}{\levelchar[#1]}% class
-    \encapchar usage}%
-  \ifblank{#1}%
-  {}% no class
-  {% class given
-    \begingroup%
-    \DTXD at origwrindex{%
-      #1\actualchar[#1]:\levelchar%
-      \DTXD at macroname{#2}\actualchar\DTXD at verbatimcmd{#2}%
-      \encapchar usage}%
-  }% class given
-  \@esphack%
-  \ignorespaces%
-}
-
-%</sankeydocpreamble>
+%</sankey-doc-preamble>
 % \fi
 \endinput
 

Modified: trunk/Master/texmf-dist/source/latex/sankey/sankey.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/sankey/sankey.ins	2025-01-10 23:03:07 UTC (rev 73395)
+++ trunk/Master/texmf-dist/source/latex/sankey/sankey.ins	2025-01-10 23:03:17 UTC (rev 73396)
@@ -1,5 +1,5 @@
 %%
-%% Copyright (C) 2016, 2021 by Paul Gaborit
+%% Copyright (C) 2016-2022 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
@@ -31,7 +31,7 @@
 
 This is a generated file.
 
-Copyright (C) 2016, 2021 by Paul Gaborit
+Copyright (C) 2016-2022 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
@@ -65,7 +65,7 @@
   \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}}%
+  \file{sankey-doc-preamble.sty}{\from{sankey.dtx}{sankey-doc-preamble}}%
 }
 
 \Msg{*********************************************************}
@@ -82,4 +82,4 @@
 \Msg{* Happy TeXing!}
 \Msg{*********************************************************}
 
-\endbatchfile
\ No newline at end of file
+\endbatchfile

Modified: trunk/Master/texmf-dist/tex/latex/sankey/sankey-doc-preamble.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/sankey/sankey-doc-preamble.sty	2025-01-10 23:03:07 UTC (rev 73395)
+++ trunk/Master/texmf-dist/tex/latex/sankey/sankey-doc-preamble.sty	2025-01-10 23:03:17 UTC (rev 73396)
@@ -3,9 +3,10 @@
 \usepackage{cmap}
 \usepackage[T1]{fontenc}
 \usepackage{lmodern}
+\usepackage{inconsolata}
 \usepackage[final,protrusion=true,expansion=true]{microtype}
 \usepackage{xcolor}
-\PassOptionsToPackage{final,colorlinks,linkcolor=red!60!orange!85!black}{hyperref}
+\PassOptionsToPackage{final,colorlinks,linkcolor=cyan!25!blue!75!black}{hyperref}
 \usepackage{dtxdescribe}
 \usepackage[numbered]{hypdoc}
 \usepackage{fancyvrb}
@@ -170,17 +171,17 @@
   % \vspace{.25\baselineskip plus .25\baselineskip minus 0mm}
   \parfillskip 0pt plus 1fil%
   \leavevmode%
-  \DescribeKey{\key}%
+  \expandafter\DescribeKey\expandafter{\key}%
   \ttfamily%
   %\hspace*{-1cm}%
   \textcolor{red!75!black}{\texttt{\docprefix{\keypath/}\key}}%
   \ifdefempty{\val}{}{=\val}%
   \hfill%
-  \ifdefempty{\default}{\null}{(default:\,\constant{\default})}%
-  \ifdefempty{\initially}{\null}{(initially:\,\constant{\initially})}%
+  \ifdefempty{\default}{\null}{{\rmfamily (default:\,\constant{\default})}}%
+  \ifdefempty{\initially}{\null}{{\rmfamily (initially:\,\constant{\initially})}}%
   \mynobreakpar%
   \endgroup%
-  \parskip=.5\baselineskip plus .25\baselineskip minus .25\baselineskip
+  \parskip=.5\baselineskip plus .25\baselineskip minus .3\baselineskip
   \parfillskip=30pt plus 1fil
   \itemize[topsep=0pt,partopsep=0pt,itemsep=0pt]\item[]
 }{%
@@ -236,33 +237,3 @@
   \footnotesize
 }
 
-\renewcommand*{\DescribeMacro}[2][]{%
-  \@bsphack%
-  \@ifundefined{@captype}{% not float?
-    \leavevmode%
-    \marginpar{%
-      \hbadness=10000%
-      \hfuzz=5em%
-      \raggedleft%
-      \ifblank{#1}{}{{\scriptsize\textsf{[#1]}} }% class
-      \MacroFont\cmd{#2}% name
-    }% marginpar
-  }{}% not float?
-  \begingroup%
-  \DTXD at origwrindex{%
-    \DTXD at macroname{#2}\actualchar\DTXD at verbatimcmd{#2}% name
-    \ifblank{#1}{}{\levelchar[#1]}% class
-    \encapchar usage}%
-  \ifblank{#1}%
-  {}% no class
-  {% class given
-    \begingroup%
-    \DTXD at origwrindex{%
-      #1\actualchar[#1]:\levelchar%
-      \DTXD at macroname{#2}\actualchar\DTXD at verbatimcmd{#2}%
-      \encapchar usage}%
-  }% class given
-  \@esphack%
-  \ignorespaces%
-}
-

Modified: trunk/Master/texmf-dist/tex/latex/sankey/sankey.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/sankey/sankey.sty	2025-01-10 23:03:07 UTC (rev 73395)
+++ trunk/Master/texmf-dist/tex/latex/sankey/sankey.sty	2025-01-10 23:03:17 UTC (rev 73396)
@@ -8,7 +8,7 @@
 %% 
 %% This is a generated file.
 %% 
-%% Copyright (C) 2016, 2021 by Paul Gaborit
+%% Copyright (C) 2016-2022 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
@@ -31,7 +31,7 @@
 %% sankey-example-energy.tex
 %% 
 \NeedsTeXFormat{LaTeX2e}[2015/10/01]
-\ProvidesPackage{sankey}[2022/02/04 v3.0.1 to draw Sankey diagrams]
+\ProvidesPackage{sankey}[2025/01/10 v3.0.2 to draw Sankey diagrams]
 \RequirePackage{xparse}
 \RequirePackage{etoolbox}
 \RequirePackage{xfp}
@@ -258,154 +258,153 @@
     anchor=#3,
   },
 }
-\NewDocumentEnvironment{sankeydiagram}{O{}}{
-  \def\snk at getpos##1##2{%
-    \tikz at scan@one at point\pgfutil at firstofone(##2)\relax%
-    \edef##1{\the\pgf at x,\the\pgf at y}%
-  }
-  \def\snk at modulo##1##2{\fpeval{##1-(floor((##1)/(##2),0)*##2)}}
-  \def\snk at normalize@angle##1{%
-    \fpeval{\snk at modulo{(##1)+180}{360}-180}%
-  }
-  \def\snk at 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 at len}{\sankeyqtytolen{\qty}/3}
-        \path[/sankey/debug normal] (\name.center)
-        -- ($(\name.center)!\snk at len pt!90:(\name.right)$)
-        node[/sankey/debug label,rotate=\orient+90+\snk at rotate,anchor=north];
-      \end{pgfonlayer}
-      \endgroup
-    }{}
-  }
-  \def\snk at makeforkednode{
+\def\snk at getpos#1#2{%
+  \tikz at scan@one at point\pgfutil at firstofone(#2)\relax%
+  \edef#1{\the\pgf at x,\the\pgf at y}%
+}
+\def\snk at modulo#1#2{\fpeval{#1-(floor((#1)/(#2),0)*#2)}}
+\def\snk at normalize@angle#1{%
+  \fpeval{\snk at modulo{(#1)+180}{360}-180}%
+}
+\def\snk at show@debug#1{% node name
+  \iftoggle{sankey debug}{
     \begingroup
-    \ifdefempty{\snk at listofforks}{
-      \ifdefempty{\snk at forkanchor}{}{
-        \PackageWarning{sankey}%
-        {Can't use 'fork anchor' key without 'forked' key}
-      }
-    }{
-      \def\snk at tot{0}
-      \def\snk at added@values{}
-      \sankeyset{
-        @add forked node/.code args={####1/####2}{
-          \coordinate (####2) at ($(\name.left)%
-          !\fpeval{(\snk at tot+.5*(####1))/\qty}%
-          !(\name.right)$);
-          \edef\snk at orient{\orient}
-          \sankeynode[debug=false]
-          {name=####2,quantity=####1,at=####2,angle=\snk at orient}
-          \edef\snk at tot{\fpeval{\snk at tot+####1}}
-          \edef\snk at added@values{\snk at added@values+####1}
-        },
-        @add forked node/.list/.expand once=\snk at listofforks,
-      }
-      \edef\snk at diff{\fpeval{abs(\qty-\snk at tot)}}
-      \ifnumequal{\snk at diff}{0}{}{
-        \PackageWarning{sankey}%
-        {^^J*** Warning: bad sankey fork: %
-          \qty\space!=\space\snk at added@values(=\snk at tot)%
-          ^^J\snk at listofforks}
-      }
-      \ifdefempty{\snk at forkanchor}{
-        \edef\snk at forkanchor{\name.\snk at anchor}
-      }{}
-      \snk at getpos\snk at c{$(\snk at forkanchor) - (\pos)$}
-      \sankeynode{as=\name,at={$(\name) - (\snk at c)$}}
-      \foreach \snk at subnodeqty/\snk at subnodename in \snk at listofforks {
-        \sankeynode{as=\snk at subnodename,at={$(\snk at subnodename) - (\snk at c)$}}
-      }
-    }
+    \edef\name{#1}
+    \edef\qty{\sankeygetnodeqty{\name}}
+    \edef\orient{\sankeygetnodeorient{\name}}
+    \begin{pgfonlayer}{sankeydebug}
+      \path[/sankey/debug line] (\name.left) -- (\name.right);
+      \pgfmathsetmacro{\snk at len}{\sankeyqtytolen{\qty}/3}
+      \path[/sankey/debug normal] (\name.center)
+      -- ($(\name.center)!\snk at len pt!90:(\name.right)$)
+      node[/sankey/debug label,rotate=\orient+90+\snk at rotate,anchor=north];
+    \end{pgfonlayer}
     \endgroup
-  }
-  \def\snk at makenode{
-    \begingroup
-    \snk at setnodeqty{\name}{\qty}
-    \edef\orient{\snk at normalize@angle{\orient}}
-    \snk at setnodeorient{\name}{\orient}
-    \ifundef{\snk at anchor}{\def\snk at anchor{center}}{}
-    \node[/sankey/@sankey node={\name}{\pos}{\snk at anchor}];
-    \endgroup
-  }
-  \def\snk at filldrawstart{
-    \begin{scope}[shift={(\name)},rotate=\orient]
-      \path[/sankey/fill] \snk at getstartfill{\snk at startstyle};
-      \path[/sankey/draw] \snk at getstartdraw{\snk at startstyle};
-    \end{scope}
-  }
-  \def\snk at filldrawend{
-    \begin{scope}[shift={(\name)},rotate=\sankeygetnodeorient{\name}]
-      \path[/sankey/fill] \snk at getendfill{\snk at endstyle};
-      \path[/sankey/draw] \snk at getenddraw{\snk at endstyle};
-    \end{scope}
-  }
-  \def\snk at checkquantities##1##2##3{
-    \begingroup
-    \edef\snk at qtyi{\sankeygetnodeqty{##1}}
-    \edef\snk at qtyii{\sankeygetnodeqty{##2}}
-    \ifdefstrequal{\snk at qtyi}{\snk at qtyii}{}{
-      \PackageError{sankey}%
-      {^^J*** \string##3: quantities differ between %
-        ##1 (\snk at qtyi) and ##2 (\snk at qtyii)%
-        ^^J}%
-      {The quantities of the two Sankey nodes must be equal.}
+  }{}
+}
+\def\snk at makeforkednode{
+  \begingroup
+  \ifdefempty{\snk at listofforks}{
+    \ifdefempty{\snk at forkanchor}{}{
+      \PackageWarning{sankey}%
+      {Can't use 'fork anchor' key without 'forked' key}
     }
-    \endgroup
-  }
-  \NewDocumentCommand\sankeydubins{O{}mm}{% options, sn, en
-    \snk at errorifnotdefined{##2}
-    \snk at errorifnotdefined{##3}
-    \snk at 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 at minradius + .5 * \sankeyqtytolen{\qty} pt,
+  }{
+    \def\snk at tot{0}
+    \def\snk at added@values{}
+    \sankeyset{
+      @add forked node/.code args={##1/##2}{
+        \coordinate (##2) at ($(\name.left)%
+        !\fpeval{(\snk at tot+.5*(##1))/\qty}%
+        !(\name.right)$);
+        \edef\snk at orient{\orient}
+        \sankeynode[debug=false]
+        {name=##2,quantity=##1,at=##2,angle=\snk at orient}
+        \edef\snk at tot{\fpeval{\snk at tot+##1}}
+        \edef\snk at added@values{\snk at added@values+##1}
       },
+      @add forked node/.list/.expand once=\snk at listofforks,
     }
-    \dubinspathcalc{sankey,store=sankey}
-    \dubinspathset{
-      left border/.style={
-        sankey, use store=sankey,
-        left and right minimum radii={\snk at minradius}
-        and {\snk at minradius + \sankeyqtytolen{\qty} pt},
-      },
-      right border/.style={
-        sankey, use store=sankey,
-        left and right minimum radii=
-        {\snk at minradius + \sankeyqtytolen{\qty} pt}
-        and {\snk at minradius},
-      },
+    \edef\snk at diff{\fpeval{abs(\qty-\snk at tot)}}
+    \ifnumequal{\snk at diff}{0}{}{
+      \PackageWarning{sankey}%
+      {^^J*** Warning: bad sankey fork: %
+        \qty\space!=\space\snk at added@values(=\snk at tot)%
+        ^^J\snk at listofforks}
     }
-    % 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
+    \ifdefempty{\snk at forkanchor}{
+      \edef\snk at forkanchor{\name.\snk at anchor}
+    }{}
+    \snk at getpos\snk at c{$(\snk at forkanchor) - (\pos)$}
+    \sankeynode{as=\name,at={$(\name) - (\snk at c)$}}
+    \foreach \snk at subnodeqty/\snk at subnodename in \snk at listofforks {
+      \sankeynode{as=\snk at subnodename,at={$(\snk at subnodename) - (\snk at c)$}}
+    }
   }
-  \NewDocumentCommand\sankeyoutin{O{}mm}{% options, sn, en
-    \snk at errorifnotdefined{##2}
-    \snk at errorifnotdefined{##3}
-    \snk at checkquantities{##2}{##3}{\sankeyoutin}
-    \begingroup
-    \sankeyset{##1}
-    \edef\qty{\sankeygetnodeqty{##2}}
-    \pgfmathsetmacro\snk at len{\sankeyqtytolen{\qty}/2}
-    \edef\snk at step{\fpeval{1/\snk at stepoutin}}
-    \edef\snk at laststep{\inteval{\snk at stepoutin-1}}
-    \path[overlay,decorate,decoration={
+  \endgroup
+}
+\def\snk at makenode{
+  \begingroup
+  \snk at setnodeqty{\name}{\qty}
+  \edef\orient{\snk at normalize@angle{\orient}}
+  \snk at setnodeorient{\name}{\orient}
+  \ifundef{\snk at anchor}{\def\snk at anchor{center}}{}
+  \node[/sankey/@sankey node={\name}{\pos}{\snk at anchor}];
+  \endgroup
+}
+\def\snk at filldrawstart{
+  \begin{scope}[shift={(\name)},rotate=\orient]
+    \path[/sankey/fill] \snk at getstartfill{\snk at startstyle};
+    \path[/sankey/draw] \snk at getstartdraw{\snk at startstyle};
+  \end{scope}
+}
+\def\snk at filldrawend{
+  \begin{scope}[shift={(\name)},rotate=\sankeygetnodeorient{\name}]
+    \path[/sankey/fill] \snk at getendfill{\snk at endstyle};
+    \path[/sankey/draw] \snk at getenddraw{\snk at endstyle};
+  \end{scope}
+}
+\def\snk at checkquantities#1#2#3{
+  \begingroup
+  \edef\snk at qtyi{\sankeygetnodeqty{#1}}
+  \edef\snk at qtyii{\sankeygetnodeqty{#2}}
+  \ifdefstrequal{\snk at qtyi}{\snk at qtyii}{}{
+    \PackageError{sankey}%
+    {^^J*** \string#3: quantities differ between %
+      #1 (\snk at qtyi) and #2 (\snk at qtyii)%
+      ^^J}%
+    {The quantities of the two Sankey nodes must be equal.}
+  }
+  \endgroup
+}
+\NewDocumentCommand\snk at sankeydubins{O{}mm}{% options, sn, en
+  \snk at errorifnotdefined{#2}
+  \snk at errorifnotdefined{#3}
+  \snk at 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 at minradius + .5 * \sankeyqtytolen{\qty} pt,
+    },
+  }
+  \dubinspathcalc{sankey,store=sankey}
+  \dubinspathset{
+    left border/.style={
+      sankey, use store=sankey,
+      left and right minimum radii={\snk at minradius}
+      and {\snk at minradius + \sankeyqtytolen{\qty} pt},
+    },
+    right border/.style={
+      sankey, use store=sankey,
+      left and right minimum radii=
+      {\snk at minradius + \sankeyqtytolen{\qty} pt}
+      and {\snk at 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
+}
+\NewDocumentCommand\snk at sankeyoutin{O{}mm}{% options, sn, en
+  \snk at errorifnotdefined{#2}
+  \snk at errorifnotdefined{#3}
+  \snk at checkquantities{#2}{#3}{\sankeyoutin}
+  \begingroup
+  \sankeyset{#1}
+  \edef\qty{\sankeygetnodeqty{#2}}
+  \pgfmathsetmacro\snk at len{\sankeyqtytolen{\qty}/2}
+  \edef\snk at step{\fpeval{1/\snk at stepoutin}}
+  \edef\snk at laststep{\inteval{\snk at stepoutin-1}}
+  \path[overlay,decorate,decoration={
       markings,
       mark=between positions \snk at step and {\fpeval{1-.5*\snk at step}}
       step \snk at step with {
@@ -420,348 +419,355 @@
         ;
       }
     }]
-    (##2.center)
-    to[out=\sankeygetnodeorient{##2},in=\sankeygetnodeorient{##3}+180]
-    (##3.center);
-    \foreach \snk at ptnum in {1,...,\snk at laststep}{
-      \edef\snk at outinmidptname{snk at outinmidpt-\snk at ptnum}
-      \dbp at anglebetween\snk at outinmidptangle%
-      {\snk at outinmidptname-r}{\snk at outinmidptname-l}
-      \sankeynode[debug=false]{%
-        name=\snk at outinmidptname,
-        quantity=\qty,
-        angle=\snk at outinmidptangle-90,%
-        at=\snk at outinmidptname%
-      }
-    }
+  (#2.center)
+  to[out=\sankeygetnodeorient{#2},in=\sankeygetnodeorient{#3}+180]
+  (#3.center);
+  \foreach \snk at ptnum in {1,...,\snk at laststep}{
+    \edef\snk at outinmidptname{snk at outinmidpt-\snk at ptnum}
+    \dbp at anglebetween\snk at outinmidptangle%
+    {\snk at outinmidptname-r}{\snk at outinmidptname-l}
     \sankeynode[debug=false]{%
-      name={snk at outinmidpt-0},
-      quantity=\sankeygetnodeqty{##2},
-      angle=\sankeygetnodeorient{##2},%
-      at={##2}%
+      name=\snk at outinmidptname,
+      quantity=\qty,
+      angle=\snk at outinmidptangle-90,%
+      at=\snk at outinmidptname%
     }
-    \sankeynode[debug=false]{%
-      name={snk at outinmidpt-\snk at stepoutin},
-      quantity={\sankeygetnodeqty{##3}},
-      angle={\sankeygetnodeorient{##3}},%
-      at={##3}%
-    }
-    \path[/sankey/fill,looseness=1]
-    (snk at outinmidpt-0.left)
-    \foreach \snk at curpt
-    [remember=\snk at curpt as \snk at prevpt (initially 0)]
-    in {1,...,\snk at stepoutin}{
-      to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt},
-      in=\sankeygetnodeorient{snk at outinmidpt-\snk at curpt}+180]
-      (snk at outinmidpt-\snk at curpt.left)
-    }
-    --
-    (snk at outinmidpt-\snk at stepoutin.right)
-    \foreach \snk at curpt
-    [remember=\snk at curpt as \snk at prevpt (initially \snk at stepoutin)]
-    in {\snk at laststep,...,0}{
-      to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt}+180,
-      in=\sankeygetnodeorient{snk at outinmidpt-\snk at curpt}]
-      (snk at outinmidpt-\snk at curpt.right)
-    }
-    -- cycle;
-    \path[/sankey/draw,looseness=1]
-    (snk at outinmidpt-0.left)
-    \foreach \snk at curpt
-    [remember=\snk at curpt as \snk at prevpt (initially 0)]
-    in {1,...,\snk at stepoutin}{
-      to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt},
-      in=\sankeygetnodeorient{snk at outinmidpt-\snk at curpt}+180]
-      (snk at outinmidpt-\snk at curpt.left)
-    }
-    (snk at outinmidpt-\snk at stepoutin.right)
-    \foreach \snk at curpt
-    [remember=\snk at curpt as \snk at prevpt (initially \snk at stepoutin)]
-    in {\snk at laststep,...,0}{
-      to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt}+180,
-      in=\sankeygetnodeorient{snk at outinmidpt-\snk at curpt}]
-      (snk at outinmidpt-\snk at curpt.right)
-    };
-    \endgroup
   }
-  \NewDocumentCommand\sankeynodealias{mm}{%name, alias
-    \snk at errorifnotdefined{##1}
-    \path[late options={name=##1,alias=##2}];
-    \snk at setnodeqty{##2}{\sankeygetnodeqty{##1}}
-    \snk at setnodeorient{##2}{\sankeygetnodeorient{##1}}
+  \sankeynode[debug=false]{%
+    name={snk at outinmidpt-0},
+    quantity=\sankeygetnodeqty{#2},
+    angle=\sankeygetnodeorient{#2},%
+    at={#2}%
   }
-  \NewDocumentCommand\sankeynode{O{}m}{% options, node parameters
-    \begingroup
-    \sankeyset{##1}
-    \sankeyset{node parameters, at initial parameters,/sankey/every node,##2}
-    \snk at makenode{}
-    \snk at makeforkednode{}
-    \iftoggle{sankey node start}{\snk at filldrawstart}{}
-    \iftoggle{sankey node end}{\snk at filldrawend}{}
-    \snk at show@debug{\name}
-    \endgroup
+  \sankeynode[debug=false]{%
+    name={snk at outinmidpt-\snk at stepoutin},
+    quantity={\sankeygetnodeqty{#3}},
+    angle={\sankeygetnodeorient{#3}},%
+    at={#3}%
   }
-  \NewDocumentCommand\sankeystart{O{}m}{% options, name
-    \snk at errorifnotdefined{##2}
-    \begingroup
-    \sankeyset{##1}
-    \edef\name{##2}
-    \edef\orient{\sankeygetnodeorient{##2}}
-    \edef\qty{\sankeygetnodeqty{##2}}
-    \snk at filldrawstart
-    \endgroup
+  \path[/sankey/fill,looseness=1]
+  (snk at outinmidpt-0.left)
+  \foreach \snk at curpt
+  [remember=\snk at curpt as \snk at prevpt (initially 0)]
+  in {1,...,\snk at stepoutin}{
+    to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt},
+      in=\sankeygetnodeorient{snk at outinmidpt-\snk at curpt}+180]
+    (snk at outinmidpt-\snk at curpt.left)
   }
-  \NewDocumentCommand\sankeynodestart{O{}m}{% option, node parameters
-    \sankeynode[##1]{start,##2}
+  --
+  (snk at outinmidpt-\snk at stepoutin.right)
+  \foreach \snk at curpt
+  [remember=\snk at curpt as \snk at prevpt (initially \snk at stepoutin)]
+  in {\snk at laststep,...,0}{
+    to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt}+180,
+      in=\sankeygetnodeorient{snk at outinmidpt-\snk at curpt}]
+    (snk at outinmidpt-\snk at curpt.right)
   }
-  \NewDocumentCommand\sankeyend{O{}m}{%options, name
-    \snk at errorifnotdefined{##2}
-    \begingroup
-    \sankeyset{##1}
-    \edef\name{##2}
-    \edef\orient{\sankeygetnodeorient{##2}}
-    \edef\qty{\sankeygetnodeqty{##2}}
-    \snk at filldrawend
-    \endgroup
+  -- cycle;
+  \path[/sankey/draw,looseness=1]
+  (snk at outinmidpt-0.left)
+  \foreach \snk at curpt
+  [remember=\snk at curpt as \snk at prevpt (initially 0)]
+  in {1,...,\snk at stepoutin}{
+    to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt},
+      in=\sankeygetnodeorient{snk at outinmidpt-\snk at curpt}+180]
+    (snk at outinmidpt-\snk at curpt.left)
   }
-  \NewDocumentCommand\sankeynodeend{O{}m}{% options, node parameters
-    \sankeynode[##1]{end,##2}
-  }
-  \NewDocumentCommand\sankeyadvance{sO{}mm}{%
-    %params: *(reverse), options, name, distance
-    \snk at errorifnotdefined{##3}
-    \begingroup
-    \sankeyset{##2}
-    \edef\name{##3}
-    \edef\snk at oldname{##3-old}
-    \sankeynodealias{\name}{\snk at oldname}
-    \IfBooleanTF{##1}{
-      % move backward
-      \sankeynode{
-        at={$(\snk at oldname.center)!##4!90:(\snk at oldname.left)$},
-        angle=\sankeygetnodeorient{\snk at oldname},
-        quantity=\sankeygetnodeqty{\snk at oldname},
-        name=\name,
-      }
-      \path[/sankey/fill]
-      (\name.left) -- (\snk at oldname.left)
-      -- (\snk at oldname.right) -- (\name.right) -- cycle;
-      \path[/sankey/draw]
-      (\name.left) -- (\snk at oldname.left)
-      (\snk at oldname.right) -- (\name.right);
-    }{
-      % move forward
-      \sankeynode{
-        at={$(\snk at oldname.center)!##4!-90:(\snk at oldname.left)$},
-        angle=\sankeygetnodeorient{\snk at oldname},
-        quantity=\sankeygetnodeqty{\snk at oldname},
-        name=\name,
-      }
-      \path[/sankey/fill]
-      (\snk at oldname.left) -- (\name.left)
-      -- (\name.right) -- (\snk at oldname.right) -- cycle;
-      \path[/sankey/draw]
-      (\snk at oldname.left) -- (\name.left)
-      (\name.right) -- (\snk at oldname.right);
+  (snk at outinmidpt-\snk at stepoutin.right)
+  \foreach \snk at curpt
+  [remember=\snk at curpt as \snk at prevpt (initially \snk at stepoutin)]
+  in {\snk at laststep,...,0}{
+    to[out=\sankeygetnodeorient{snk at outinmidpt-\snk at prevpt}+180,
+      in=\sankeygetnodeorient{snk at outinmidpt-\snk at curpt}]
+    (snk at outinmidpt-\snk at curpt.right)
+  };
+  \endgroup
+}
+\NewDocumentCommand\snk at sankeynodealias{mm}{%name, alias
+  \snk at errorifnotdefined{#1}
+  \path[late options={name=#1,alias=#2}];
+  \snk at setnodeqty{#2}{\sankeygetnodeqty{#1}}
+  \snk at setnodeorient{#2}{\sankeygetnodeorient{#1}}
+}
+\NewDocumentCommand\snk at sankeynode{O{}m}{% options, node parameters
+  \begingroup
+  \sankeyset{#1}
+  \sankeyset{node parameters, at initial parameters,/sankey/every node,#2}
+  \snk at makenode{}
+  \snk at makeforkednode{}
+  \iftoggle{sankey node start}{\snk at filldrawstart}{}
+  \iftoggle{sankey node end}{\snk at filldrawend}{}
+  \snk at show@debug{\name}
+  \endgroup
+}
+\NewDocumentCommand\snk at sankeystart{O{}m}{% options, name
+  \snk at errorifnotdefined{#2}
+  \begingroup
+  \sankeyset{#1}
+  \edef\name{#2}
+  \edef\orient{\sankeygetnodeorient{#2}}
+  \edef\qty{\sankeygetnodeqty{#2}}
+  \snk at filldrawstart
+  \endgroup
+}
+\NewDocumentCommand\snk at sankeynodestart{O{}m}{% option, node parameters
+  \sankeynode[#1]{start,#2}
+}
+\NewDocumentCommand\snk at sankeyend{O{}m}{%options, name
+  \snk at errorifnotdefined{#2}
+  \begingroup
+  \sankeyset{#1}
+  \edef\name{#2}
+  \edef\orient{\sankeygetnodeorient{#2}}
+  \edef\qty{\sankeygetnodeqty{#2}}
+  \snk at filldrawend
+  \endgroup
+}
+\NewDocumentCommand\snk at sankeynodeend{O{}m}{% options, node parameters
+  \sankeynode[#1]{end,#2}
+}
+\def\snk at init@move#1#2{% params: options, name
+  \sankeyset{#1}
+  \edef\name{#2}
+  \edef\snk at oldname{#2-old}
+  \sankeynodealias{\name}{\snk at oldname}
+  \edef\qty{\sankeygetnodeqty{\name}}
+}
+\NewDocumentCommand\snk at sankeyadvance{sO{}mm}{%
+  % params: *(reverse), options, name, distance
+  \snk at errorifnotdefined{#3}
+  \begingroup
+  \snk at init@move{#2}{#3}
+  \IfBooleanTF{#1}{
+    % move backward
+    \sankeynode{
+      at={$(\snk at oldname.center)!#4!90:(\snk at oldname.left)$},
+      angle=\sankeygetnodeorient{\snk at oldname},
+      quantity=\sankeygetnodeqty{\snk at oldname},
+      name=\name,
     }
-    \snk at show@debug{\name}
-    \endgroup
-  }
-  \NewDocumentCommand\sankeyturnright{sO{}mm}{
-    % *(reverse), options, name, angle
-    \snk at errorifnotdefined{##3}
-    \begingroup
-    \IfBooleanTF{##1}
-    {\edef\snk at angle{\fpeval{-1*##4}}}
-    {\edef\snk at angle{\fpeval{1*##4}}}
-    \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
-    \ifnumgreater{\snk at anglesign}{-1}{
-      \sankeyset{##2}
-      \edef\name{##3}
-      \edef\snk at oldname{##3-old}
-      \sankeynodealias{\name}{\snk at oldname}
-      \edef\qty{\sankeygetnodeqty{\name}}
-      \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}-\snk at angle}}
-      \snk at getpos\snk at c{$(\name.right)!-\snk at minradius!(\name.left)$}
-      \snk at getpos\pos{$(\snk at c)!1!-\snk at angle:(\name.center)$}
-      \snk at makenode{}
-      % fill the region
-      \path[/sankey/fill] let
-      \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
-      \p3=(\name.left),\p4=(\name.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1},
-      \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient+\snk at angle+90:\orient+90:\n{maxr}) -- (\p3) --
-      (\p4) arc(\orient+90:\orient+\snk at angle+90:\n{minr}) -- (\p2) -- cycle;
-      % draw left and right borders
-      \path[/sankey/draw] let
-      \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
-      \p3=(\name.left),\p4=(\name.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1},
-      \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient+\snk at angle+90:\orient+90:\n{maxr})
-      (\p4) arc(\orient+90:\orient+\snk at angle+90:\n{minr});
-      \snk at show@debug{\name}
-    }{
-      \sankeyturnrightbackward[##2]{##3}{-1*\snk at angle}
+    \path[/sankey/fill]
+    (\name.left) -- (\snk at oldname.left)
+    -- (\snk at oldname.right) -- (\name.right) -- cycle;
+    \path[/sankey/draw]
+    (\name.left) -- (\snk at oldname.left)
+    (\snk at oldname.right) -- (\name.right);
+  }{
+    % move forward
+    \sankeynode{
+      at={$(\snk at oldname.center)!#4!-90:(\snk at oldname.left)$},
+      angle=\sankeygetnodeorient{\snk at oldname},
+      quantity=\sankeygetnodeqty{\snk at oldname},
+      name=\name,
     }
-    \endgroup
+    \path[/sankey/fill]
+    (\snk at oldname.left) -- (\name.left)
+    -- (\name.right) -- (\snk at oldname.right) -- cycle;
+    \path[/sankey/draw]
+    (\snk at oldname.left) -- (\name.left)
+    (\name.right) -- (\snk at oldname.right);
   }
-  \NewDocumentCommand\sankeyturnrightbackward{sO{}mm}{
-    % *(reverse), options, name, angle
-    \snk at errorifnotdefined{##3}
-    \begingroup
-    \IfBooleanTF{##1}
-    {\edef\snk at angle{\fpeval{-1*##4}}}
-    {\edef\snk at angle{\fpeval{1*##4}}}
-    \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
-    \ifnumgreater{\snk at anglesign}{-1}{
-      \sankeyset{##2}
-      \edef\name{##3}
-      \edef\snk at oldname{##3-old}
-      \sankeynodealias{\name}{\snk at oldname}
-      \edef\qty{\sankeygetnodeqty{\name}}
-      \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}+\snk at angle}}
-      \snk at getpos\snk at c{$(\name.right)!-\snk at minradius!(\name.left)$}
-      \snk at getpos\pos{$(\snk at c)!1!\snk at angle:(\name.center)$}
-      \snk at makenode{}
-      % fill the region
-      \path[/sankey/fill] let
-      \p1=(\name.left),\p2=(\name.right),
-      \p3=(\snk at oldname.left),\p4=(\snk at oldname.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient+90:\orient-\snk at angle+90:\n{maxr}) -- (\p3) --
-      (\p4) arc(\orient-\snk at 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 at oldname.left),\p4=(\snk at oldname.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient+90:\orient-\snk at angle+90:\n{maxr})
-      (\p4) arc(\orient-\snk at angle+90:\orient+90:\n{minr});
-      \snk at show@debug{\name}
-    }{
-      \sankeyturnright[##2]{##3}{-1*\snk at angle}
-    }
-    \endgroup
+  \snk at show@debug{\name}
+  \endgroup
+}
+\NewDocumentCommand\snk at sankeyturnright{sO{}mm}{
+  % *(reverse), options, name, angle
+  \snk at errorifnotdefined{#3}
+  \begingroup
+  \IfBooleanTF{#1}
+  {\edef\snk at angle{\fpeval{-1*#4}}}
+  {\edef\snk at angle{\fpeval{1*#4}}}
+  \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
+  \ifnumgreater{\snk at anglesign}{-1}{
+    \snk at init@move{#2}{#3}
+    \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}-\snk at angle}}
+    \snk at getpos\snk at c{$(\name.right)!-\snk at minradius!(\name.left)$}
+    \snk at getpos\pos{$(\snk at c)!1!-\snk at angle:(\name.center)$}
+    \snk at makenode{}
+    % fill the region
+    \path[/sankey/fill] let
+    \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
+    \p3=(\name.left),\p4=(\name.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1},
+    \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient+\snk at angle+90:\orient+90:\n{maxr}) -- (\p3) --
+    (\p4) arc(\orient+90:\orient+\snk at angle+90:\n{minr}) -- (\p2) -- cycle;
+    % draw left and right borders
+    \path[/sankey/draw] let
+    \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
+    \p3=(\name.left),\p4=(\name.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1},
+    \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient+\snk at angle+90:\orient+90:\n{maxr})
+    (\p4) arc(\orient+90:\orient+\snk at angle+90:\n{minr});
+    \snk at show@debug{\name}
+  }{
+    \sankeyturnrightbackward[#2]{#3}{-1*\snk at angle}
   }
-  \NewDocumentCommand\sankeyturnleft{sO{}mm}{
-    % *(reverse), options, name, angle
-    \snk at errorifnotdefined{##3}
-    \begingroup
-    \IfBooleanTF{##1}
-    {\edef\snk at angle{\fpeval{-1*##4}}}
-    {\edef\snk at angle{\fpeval{1*##4}}}
-    \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
-    \ifnumgreater{\snk at anglesign}{-1}{
-      \sankeyset{##2}
-      \edef\name{##3}
-      \edef\snk at oldname{##3-old}
-      \sankeynodealias{\name}{\snk at oldname}
-      \edef\qty{\sankeygetnodeqty{\name}}
-      \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}+\snk at angle}}
-      \snk at getpos\snk at c{$(\name.left)!-\snk at minradius!(\name.right)$}
-      \snk at getpos\pos{$(\snk at c)!1!\snk at angle:(\name.center)$}
-      \snk at makenode{}
-      % fill the region
-      \path[/sankey/fill] let
-      \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
-      \p3=(\name.left),\p4=(\name.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient-\snk at angle-90:\orient-90:\n{minr}) -- (\p3) --
-      (\p4) arc(\orient-90:\orient-\snk at angle-90:\n{maxr}) -- (\p2) -- cycle;
-      % draw left and right borders
-      \path[/sankey/draw] let
-      \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
-      \p3=(\name.left),\p4=(\name.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient-\snk at angle-90:\orient-90:\n{minr})
-      (\p4) arc(\orient-90:\orient-\snk at angle-90:\n{maxr});
-      \snk at show@debug{\name}
-    }{
-      \sankeyturnleftbackward[##2]{##3}{-1*\snk at angle}
-    }
-    \endgroup
+  \endgroup
+}
+\NewDocumentCommand\snk at sankeyturnrightbackward{sO{}mm}{
+  % *(reverse), options, name, angle
+  \snk at errorifnotdefined{#3}
+  \begingroup
+  \IfBooleanTF{#1}
+  {\edef\snk at angle{\fpeval{-1*#4}}}
+  {\edef\snk at angle{\fpeval{1*#4}}}
+  \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
+  \ifnumgreater{\snk at anglesign}{-1}{
+    \snk at init@move{#2}{#3}
+    \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}+\snk at angle}}
+    \snk at getpos\snk at c{$(\name.right)!-\snk at minradius!(\name.left)$}
+    \snk at getpos\pos{$(\snk at c)!1!\snk at angle:(\name.center)$}
+    \snk at makenode{}
+    % fill the region
+    \path[/sankey/fill] let
+    \p1=(\name.left),\p2=(\name.right),
+    \p3=(\snk at oldname.left),\p4=(\snk at oldname.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient+90:\orient-\snk at angle+90:\n{maxr}) -- (\p3) --
+    (\p4) arc(\orient-\snk at 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 at oldname.left),\p4=(\snk at oldname.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient+90:\orient-\snk at angle+90:\n{maxr})
+    (\p4) arc(\orient-\snk at angle+90:\orient+90:\n{minr});
+    \snk at show@debug{\name}
+  }{
+    \sankeyturnright[#2]{#3}{-1*\snk at angle}
   }
-  \NewDocumentCommand\sankeyturnleftbackward{sO{}mm}{
-    % *(reverse), options, name, angle
-    \snk at errorifnotdefined{##3}
-    \begingroup
-    \IfBooleanTF{##1}
-    {\edef\snk at angle{\fpeval{-1*##4}}}
-    {\edef\snk at angle{\fpeval{1*##4}}}
-    \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
-    \ifnumgreater{\snk at anglesign}{-1}{
-      \sankeyset{##2}
-      \edef\name{##3}
-      \edef\snk at oldname{##3-old}
-      \sankeynodealias{\name}{\snk at oldname}
-      \edef\qty{\sankeygetnodeqty{\name}}
-      \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}-\snk at angle}}
-      \snk at getpos\snk at c{$(\name.left)!-\snk at minradius!(\name.right)$}
-      \snk at getpos\pos{$(\snk at c)!1!-\snk at angle:(\name.center)$}
-      \snk at makenode{}
-      % fill the region
-      \path[/sankey/fill] let
-      \p1=(\name.left),\p2=(\name.right),
-      \p3=(\snk at oldname.left),\p4=(\snk at oldname.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient-90:\orient+\snk at angle-90:\n{minr}) -- (\p3) --
-      (\p4) arc(\orient+\snk at 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 at oldname.left),\p4=(\snk at oldname.right),
-      \n1={\sankeyqtytolen{\qty}},
-      \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
-      in
-      (\p1) arc(\orient-90:\orient+\snk at angle-90:\n{minr})
-      (\p4) arc(\orient+\snk at angle-90:\orient-90:\n{maxr});
-      \snk at show@debug{\name}
-    }{
-      \sankeyturnleft[##2]{##3}{-1*\snk at angle}
-    }
-    \endgroup
+  \endgroup
+}
+\NewDocumentCommand\snk at sankeyturnleft{sO{}mm}{
+  % *(reverse), options, name, angle
+  \snk at errorifnotdefined{#3}
+  \begingroup
+  \IfBooleanTF{#1}
+  {\edef\snk at angle{\fpeval{-1*#4}}}
+  {\edef\snk at angle{\fpeval{1*#4}}}
+  \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
+  \ifnumgreater{\snk at anglesign}{-1}{
+    \snk at init@move{#2}{#3}
+    \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}+\snk at angle}}
+    \snk at getpos\snk at c{$(\name.left)!-\snk at minradius!(\name.right)$}
+    \snk at getpos\pos{$(\snk at c)!1!\snk at angle:(\name.center)$}
+    \snk at makenode{}
+    % fill the region
+    \path[/sankey/fill] let
+    \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
+    \p3=(\name.left),\p4=(\name.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient-\snk at angle-90:\orient-90:\n{minr}) -- (\p3) --
+    (\p4) arc(\orient-90:\orient-\snk at angle-90:\n{maxr}) -- (\p2) -- cycle;
+    % draw left and right borders
+    \path[/sankey/draw] let
+    \p1=(\snk at oldname.left),\p2=(\snk at oldname.right),
+    \p3=(\name.left),\p4=(\name.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient-\snk at angle-90:\orient-90:\n{minr})
+    (\p4) arc(\orient-90:\orient-\snk at angle-90:\n{maxr});
+    \snk at show@debug{\name}
+  }{
+    \sankeyturnleftbackward[#2]{#3}{-1*\snk at angle}
   }
-  \NewDocumentCommand\sankeyturn{sO{}mm}{%
-    % *(reverse), options, name, angle
-    \snk at errorifnotdefined{##3}
-    \begingroup
-    \edef\snk at anglesign{\fpeval{sign(##4)}}
-    \IfBooleanTF{##1}{
-      \ifnumgreater{\snk at anglesign}{-1}
-      {\sankeyturnleftbackward[##2]{##3}{##4}}
-      {\sankeyturnrightbackward[##2]{##3}{-1*##4}}
-    }{
-      \ifnumgreater{\snk at anglesign}{-1}
-      {\sankeyturnleft[##2]{##3}{##4}}
-      {\sankeyturnright[##2]{##3}{-1*##4}}
-    }
-    \endgroup
+  \endgroup
+}
+\NewDocumentCommand\snk at sankeyturnleftbackward{sO{}mm}{
+  % *(reverse), options, name, angle
+  \snk at errorifnotdefined{#3}
+  \begingroup
+  \IfBooleanTF{#1}
+  {\edef\snk at angle{\fpeval{-1*#4}}}
+  {\edef\snk at angle{\fpeval{1*#4}}}
+  \edef\snk at anglesign{\fpeval{sign(\snk at angle)}}
+  \ifnumgreater{\snk at anglesign}{-1}{
+    \snk at init@move{#2}{#3}
+    \edef\orient{\snk at normalize@angle{\sankeygetnodeorient{\name}-\snk at angle}}
+    \snk at getpos\snk at c{$(\name.left)!-\snk at minradius!(\name.right)$}
+    \snk at getpos\pos{$(\snk at c)!1!-\snk at angle:(\name.center)$}
+    \snk at makenode{}
+    % fill the region
+    \path[/sankey/fill] let
+    \p1=(\name.left),\p2=(\name.right),
+    \p3=(\snk at oldname.left),\p4=(\snk at oldname.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient-90:\orient+\snk at angle-90:\n{minr}) -- (\p3) --
+    (\p4) arc(\orient+\snk at 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 at oldname.left),\p4=(\snk at oldname.right),
+    \n1={\sankeyqtytolen{\qty}},
+    \n{maxr}={\snk at minradius+\n1}, \n{minr}={\snk at minradius}
+    in
+    (\p1) arc(\orient-90:\orient+\snk at angle-90:\n{minr})
+    (\p4) arc(\orient+\snk at angle-90:\orient-90:\n{maxr});
+    \snk at show@debug{\name}
+  }{
+    \sankeyturnleft[#2]{#3}{-1*\snk at angle}
   }
-  \NewDocumentCommand\sankeyfork{O{}mm}{%options, name, list of forks
-    \snk at errorifnotdefined{##2}
-    \begingroup
-    \sankeyset{##1}
-    \sankeynode[debug=false]{as={##2},forked={##3}}
-    \foreach \qty/\snk at subnodename in {##3}{\sankeynode{as={\snk at subnodename}}}
-    \endgroup
+  \endgroup
+}
+\NewDocumentCommand\snk at sankeyturn{sO{}mm}{%
+  % *(reverse), options, name, angle
+  \snk at errorifnotdefined{#3}
+  \begingroup
+  \edef\snk at anglesign{\fpeval{sign(#4)}}
+  \IfBooleanTF{#1}{
+    \ifnumgreater{\snk at anglesign}{-1}
+    {\sankeyturnleftbackward[#2]{#3}{#4}}
+    {\sankeyturnrightbackward[#2]{#3}{-1*#4}}
+  }{
+    \ifnumgreater{\snk at anglesign}{-1}
+    {\sankeyturnleft[#2]{#3}{#4}}
+    {\sankeyturnright[#2]{#3}{-1*#4}}
   }
-  \def\sankeyqtytolen##1{\fpeval{(##1)/\snk at totalqty*\snk at totallen}}
+  \endgroup
+}
+\NewDocumentCommand\snk at sankeyfork{O{}mm}{%options, name, list of forks
+  \snk at errorifnotdefined{#2}
+  \begingroup
+  \sankeyset{#1}
+  \sankeynode[debug=false]{as={#2},forked={#3}}
+  \foreach \qty/\snk at subnodename in {#3}{\sankeynode{as={\snk at subnodename}}}
+  \endgroup
+}
+\NewExpandableDocumentCommand\snk at sankeyqtytolen{m}{%
+  \fpeval{(#1)/\snk at totalqty*\snk at totallen}%
+}
+\NewDocumentEnvironment{sankeydiagram}{O{}}{
+  \NewCommandCopy{\sankeyadvance}{\snk at sankeyadvance}
+  \NewCommandCopy{\sankeydubins}{\snk at sankeydubins}
+  \NewCommandCopy{\sankeyend}{\snk at sankeyend}
+  \NewCommandCopy{\sankeyfork}{\snk at sankeyfork}
+  \NewCommandCopy{\sankeynodealias}{\snk at sankeynodealias}
+  \NewCommandCopy{\sankeynodeend}{\snk at sankeynodeend}
+  \NewCommandCopy{\sankeynodestart}{\snk at sankeynodestart}
+  \NewCommandCopy{\sankeynode}{\snk at sankeynode}
+  \NewCommandCopy{\sankeyoutin}{\snk at sankeyoutin}
+  \NewCommandCopy{\sankeyqtytolen}{\snk at sankeyqtytolen}
+  \NewCommandCopy{\sankeystart}{\snk at sankeystart}
+  \NewCommandCopy{\sankeyturnleftbackward}{\snk at sankeyturnleftbackward}
+  \NewCommandCopy{\sankeyturnleft}{\snk at sankeyturnleft}
+  \NewCommandCopy{\sankeyturnrightbackward}{\snk at sankeyturnrightbackward}
+  \NewCommandCopy{\sankeyturnright}{\snk at sankeyturnright}
+  \NewCommandCopy{\sankeyturn}{\snk at sankeyturn}
   \sankeyset{
     @initial options,
     every diagram,

Modified: trunk/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex	2025-01-10 23:03:07 UTC (rev 73395)
+++ trunk/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex	2025-01-10 23:03:17 UTC (rev 73396)
@@ -8,7 +8,7 @@
 %% 
 %% This is a generated file.
 %% 
-%% Copyright (C) 2016, 2021 by Paul Gaborit
+%% Copyright (C) 2016-2022 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
@@ -30,8 +30,8 @@
 %% sankey-example3-variation.tex, sankey-example4.tex,
 %% sankey-example-energy.tex
 %% 
-\def\tikzlibrarydubins at version{v3.0.1}
-\def\tikzlibrarydubins at date{2022/02/04}
+\def\tikzlibrarydubins at version{v3.0.2}
+\def\tikzlibrarydubins at date{2025/01/10}
 \usetikzlibrary{calc}
 \RequirePackage{etoolbox}
 \RequirePackage{xfp}
@@ -258,7 +258,8 @@
       +\dbp at rsrlen
       +angtodist(\dbp at rsrangtwo,\dbp at radius)
     }
-    \dbp at setparams{rsr}{\dbp at rsrdist}{\dbp at rsrangone}{\dbp at rsrlen}{\dbp at rsrangtwo}
+    \dbp at setparams%
+    {rsr}{\dbp at rsrdist}{\dbp at rsrangone}{\dbp at rsrlen}{\dbp at rsrangtwo}
 
     % LSL (al and bl)
     \dbp at anglebetween\dbp at lslalbl{\p{al}}{\p{bl}}



More information about the tex-live-commits mailing list.