texlive[57535] Master: sankey (27jan21)

commits+karl at tug.org commits+karl at tug.org
Wed Jan 27 23:04:48 CET 2021


Revision: 57535
          http://tug.org/svn/texlive?view=revision&revision=57535
Author:   karl
Date:     2021-01-27 23:04:47 +0100 (Wed, 27 Jan 2021)
Log Message:
-----------
sankey (27jan21)

Modified Paths:
--------------
    trunk/Master/tlpkg/bin/tlpkg-ctan-check
    trunk/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/latex/sankey/
    trunk/Master/texmf-dist/doc/latex/sankey/README
    trunk/Master/texmf-dist/doc/latex/sankey/sankey-doc.pdf
    trunk/Master/texmf-dist/doc/latex/sankey/sankey-doc.tex
    trunk/Master/texmf-dist/tex/latex/sankey/
    trunk/Master/texmf-dist/tex/latex/sankey/sankey.sty
    trunk/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex
    trunk/Master/tlpkg/tlpsrc/sankey.tlpsrc

Added: trunk/Master/texmf-dist/doc/latex/sankey/README
===================================================================
--- trunk/Master/texmf-dist/doc/latex/sankey/README	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/sankey/README	2021-01-27 22:04:47 UTC (rev 57535)
@@ -0,0 +1,16 @@
+sankey
+======
+
+LaTeX package to build Sankey diagram.
+
+
+license
+=======
+
+Copyright (C) 2016-2021 by Paul Gaborit
+
+This file may be distributed and/or modified
+
+  1. under the LaTeX Project Public License and/or
+
+  2. under the GNU Public License.


Property changes on: trunk/Master/texmf-dist/doc/latex/sankey/README
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/sankey/sankey-doc.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex/sankey/sankey-doc.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/sankey/sankey-doc.pdf	2021-01-27 00:54:19 UTC (rev 57534)
+++ trunk/Master/texmf-dist/doc/latex/sankey/sankey-doc.pdf	2021-01-27 22:04:47 UTC (rev 57535)

Property changes on: trunk/Master/texmf-dist/doc/latex/sankey/sankey-doc.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/sankey/sankey-doc.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/sankey/sankey-doc.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/sankey/sankey-doc.tex	2021-01-27 22:04:47 UTC (rev 57535)
@@ -0,0 +1,1599 @@
+% -*- coding: utf-8; -*-
+
+% Copyright (C) 2016-2021 by Paul Gaborit
+%
+% This file may be distributed and/or modified
+%
+%   1. under the LaTeX Project Public License and/or
+%
+%   2. under the GNU Public License.
+
+\documentclass[a4paper,onecolumn,10pt]{article}
+%\usepackage[rgb]{xcolor}
+\usepackage[paper=a4paper,vmargin=1.5cm,hmargin=4cm]{geometry}
+\usepackage[utf8]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage{xcolor}
+\usepackage[colorlinks]{hyperref}
+\usepackage{fancyvrb}
+\usepackage{listings}
+\usepackage{enumitem}
+\usepackage{pgfilecontents}
+\usepackage{microtype}
+\usepackage{bookmark}
+\usepackage{cmap}
+\usepackage{sankey}
+\usepackage{siunitx}
+\usepackage{mdframed}
+\usepackage{footnote}
+\usepackage{accsupp}
+\usetikzlibrary{positioning,patterns.meta}
+\usepackage[british]{babel}
+
+\colorlet{fondcode}{gray!5!white}
+\colorlet{keyword}{blue!50!cyan!50!black}
+\colorlet{comment}{red!75!black}
+
+\newcommand\emptyaccsupp[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}}
+
+\lstset{
+  literate=
+  {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ú}{{\'u}}1
+  {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1
+  {à}{{\`a}}1 {è}{{\`e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1
+  {À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1
+  {ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1
+  {Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1
+  {â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1
+  {Â}{{\^A}}1 {Ê}{{\^E}}1 {Î}{{\^I}}1 {Ô}{{\^O}}1 {Û}{{\^U}}1
+  {œ}{{\oe}}1 {Œ}{{\OE}}1 {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1
+  {ç}{{\c c}}1 {Ç}{{\c C}}1 {ø}{{\o}}1 {å}{{\r a}}1 {Å}{{\r A}}1
+  {€}{{\texteuro}}1 {£}{{\pounds}}1 {°}{{\degres}}1
+  {’}{{\textquoteright}}1 {‘}{{\textquoteleft}}1
+  {«}{{<<}}1 {»}{{>>}}1
+  {—}{{---}}1 {−}{{$-$}}1
+}
+
+\lstset{
+  fancyvrb=true,
+  %fvcmdparams=samepage,
+  escapechar=`,           % pour introduire du latex dans un environnement verbatim
+  extendedchars=true,
+  fontadjust=true,
+  columns=fullflexible,   % pour pouvoir copier/coller les chaines de caractères
+  flexiblecolumns=true,
+  % frame=leftline,
+  inputencoding=utf8,
+  keepspaces=true,        % keeps spaces in text, code indentation
+  backgroundcolor=\color{fondcode},
+  basicstyle=\mdseries\ttfamily,
+  keywordstyle=\color{keyword}\bfseries,%
+  stringstyle=\ttfamily\color{green!50!black},%
+  commentstyle=\color{comment}\itshape,%
+  emphstyle=\bfseries\color{red},
+  numbersep=5pt,
+  %numbers=left,
+  numberstyle=\tiny\emptyaccsupp,
+  showstringspaces=false,
+  upquote=true,           % pour pouvoir copier/coller le code avec des quotes
+  aboveskip=\parskip,
+  belowskip=\parskip,
+  framexleftmargin=1pt,
+  framexrightmargin=1pt,
+}
+
+\lstdefinestyle{textsmall}{basicstyle=\color{black}\small\mdseries\ttfamily}
+\lstdefinestyle{textfootnotesize}{basicstyle=\color{black}\footnotesize\mdseries\ttfamily}
+\lstdefinestyle{textscriptsize}{basicstyle=\color{black}\scriptsize\mdseries\ttfamily}
+\lstdefinestyle{texttiny}{basicstyle=\color{black}\tiny\mdseries\ttfamily}
+
+\lstdefinestyle{LaTeX}{
+  language=[LaTeX]TeX,
+  %backgroundcolor=\color{latexbg},
+  moretexcs={
+    coordinate,
+    definecolor,
+    draw,
+    fill,
+    foreach,
+    hashband,
+    node,
+    sankeyadvance,
+    sankeydubins,
+    sankeyend,
+    sankeyend,
+    sankeyfork,
+    sankeynode,
+    sankeynodealias,
+    sankeynodeend,
+    sankeynodestart,
+    sankeyoutin,
+    sankeyset,
+    sankeystart,
+    sankeyturn,
+    sisetup,
+    tikzset,
+    turnandstop,
+    usepackage,
+  }
+}
+\lstdefinestyle{LaTeXsmall}{style=LaTeX,style=textsmall}
+\lstdefinestyle{LaTeXfootnotesize}{style=LaTeX,style=textfootnotesize}
+\lstdefinestyle{LaTeXscriptsize}{style=LaTeX,style=textscriptsize}
+\lstdefinestyle{LaTeXtiny}{style=LaTeX,style=texttiny}
+
+\def\code{\lstinline[basicstyle=\mdseries\ttfamily\color{red!50!black}]}
+
+\edef\samplecodename{\jobname-code.vrb}
+
+\newcommand\constant[1]{\textcolor{violet}{\texttt{#1}}}
+\newcommand\ARG[1]{\texttt{\{#1\}}}
+\newcommand\OPTARG[1]{\textcolor{green!50!black}{\texttt{[#1]}}}
+\newcommand\VAR[1]{\textit{\texttt{<#1>}}}
+\newcommand\NOTE[1]{\leavevmode\marginpar{#1}}
+
+\makeatletter
+\def\mynobreakpar{\par\nobreak\@afterheading}
+\makeatother
+\def\docprefix#1{\texttt{\textcolor{gray}{#1}}}
+\def\sankeykeysprefix{/sankey}
+
+\newenvironment{sankeyoption}[5][]{% [prefix] key, val, default, initially
+  % \begingroup
+  \bgroup%
+  % 
+  \def\path{#1}%
+  \def\key{#2}%
+  \def\val{#3}%
+  \def\default{#4}%
+  \def\initially{#5}%
+  %\setlength\parindent{\dimexpr.5\parindent\relax}%
+  % \vspace{.25\baselineskip plus .25\baselineskip minus 0mm}
+  \parfillskip 0pt plus 1fil%
+  \leavevmode%
+  \ttfamily%
+  \hspace*{-1cm}\textcolor{red!75!black}{\texttt{\docprefix{\ifdefempty{\path}{\sankeykeysprefix/}{\path/}}\key}}%
+  \ifdefempty{\val}{}{=\textit{\val}}%
+  \hfill
+  \ifdefempty{\default}{\null}{(default:\,\constant{\default})}%
+  \ifdefempty{\initially}{\null}{(initially:\,\constant{\initially})}%
+  \mynobreakpar\egroup%
+  \parskip=.5\baselineskip plus .25\baselineskip minus .25\baselineskip
+  \parfillskip=30pt plus 1fil
+  \itemize[topsep=0pt,partopsep=0pt,itemsep=0pt]\item[]
+}{%
+  \enditemize%
+}
+
+\newcommand\MACRO{\hspace*{-1cm}}
+
+\newlist{sankeyconstantsdesc}{description}{1}
+\setlist[sankeyconstantsdesc]{align=right,labelindent=1.5em,labelsep=.5em,leftmargin=!,font=\normalfont}
+
+\newlength{\myparskip}
+\setlength{\myparskip}{.75\baselineskip plus 8\baselineskip minus .25\baselineskip}
+\usepackage[skip=\myparskip]{parskip}
+%\setlength{\parskip}{\myparskip}
+\newenvironment{miniblock}{%
+  \vspace{.5\parskip}%
+  \csname minipage*\endcsname[t]{1.0\linewidth}%
+  \setlength{\parskip}{\myparskip}%
+}{%
+  \csname endminipage*\endcsname%
+}
+
+
+\makeatletter
+\title{How to use the \texttt{sankey} package\\ to build Sankey diagrams\footnote{This file described version v\sankey at version.}}
+\date{Released \sankey at date}
+\author{Paul Gaborit\footnote{\href{mailto:paul.gaborit at gmail.com}{\texttt{paul.gaborit at gmail.com}}}}
+
+\hypersetup{
+  pdftitle=How to use the sankey package to buid Sankey diagrams (v\sankey at version),
+  pdfauthor=Paul Gaborit,
+}
+\makeatother
+
+
+\begin{document}
+\maketitle
+
+\begin{abstract}
+  The \texttt{sankey} package provides macros and environments to build
+  \emph{Sankey diagrams}%
+  \footnote{\url{https://en.wikipedia.org/wiki/Sankey_diagram}} (or
+  \emph{flow diagram} in which the width of the arrows is proportional
+  to the flow rate).  The idea cames out from
+  \href{https://tex.stackexchange.com/q/40159/14500}{this question} on
+  \href{https://tex.stackexchange.com/}{TeX.StackExchange}.
+  %
+\end{abstract}
+
+{
+  \setlength{\parskip}{0pt}
+  \tableofcontents
+  \listoffigures
+}
+
+% ------------------------------------------------------------
+\section{Preamble}
+% ------------------------------------------------------------
+
+To use the \code{sankey} package, insert the following line in your preamble:
+
+\begin{lstlisting}[style=LaTeXsmall]
+\usepackage{sankey}
+\end{lstlisting}
+
+% ------------------------------------------------------------
+\section{The \texttt{sankeydiagram} environment}
+% ------------------------------------------------------------
+
+A \code{sankeydiagram} environment nested in a \code{tikzpicture}
+environment activates the sankey macros:
+
+\begin{lstlisting}[style=LaTeXsmall]
+\begin{tikzpicture}
+  \begin{sankeydiagram}[... options ...]
+    ... sankey macros ...
+  \end{sankeydiagram}  
+\end{tikzpicture}
+\end{lstlisting}
+
+% ------------------------------------------------------------
+\section{Sankey diagram options}
+% ------------------------------------------------------------
+
+The \code{sankey} package uses \code{pgfkeys} to define options via
+\emph{key=value} pairs.
+
+The options can be defined via the optional argument of the
+\code{sankeydiagram} environment:
+
+\begin{lstlisting}[style=LaTeXsmall]
+\begin{sankeydiagram}[debug=true]
+  \sankeynode{name=a,quantity=1,angle=0,at={0,0}}
+\end{sankeydiagram}
+\end{lstlisting}
+
+The options can also be modified via the \code{\sankeyset} macro:
+
+\begin{lstlisting}[style=LaTeXsmall]
+\begin{sankeydiagram}
+  \sankeyset{debug=true}
+  \sankeynode{name=a,quantity=1,angle=0,at={0,0}}
+\end{sankeydiagram}
+\end{lstlisting}
+
+The options can be  temporarily modified for a single macro:
+\begin{lstlisting}[style=LaTeXsmall]
+\begin{sankeydiagram}
+  \sankeynode[debug=true]{name=a,quantity=1,angle=0,at={0,0}}
+\end{sankeydiagram}
+\end{lstlisting}
+% ------------------------------------------------------------
+\subsection{Keys to choose the scale}
+% ------------------------------------------------------------
+
+The scale or ratio of the Sankey diagram is the ratio between the %
+\code{ratio length} and the \code{ratio quantity}.
+
+\begin{sankeyoption}{ratio quantity}{\VAR{number}}{}{10}
+  Quantity (in units of flow) to define ratio. The \VAR{number} can be
+  any math expression.
+\end{sankeyoption}
+
+\begin{sankeyoption}{ratio length}{\VAR{distance}}{}{1cm}
+  Distance (a graphical distance) to define scale.
+\end{sankeyoption}
+
+\begin{sankeyoption}{ratio}{\VAR{distance}/\VAR{number}}{}{1cm/10}
+  Fix the ratio to \VAR{distance}/\VAR{number}.
+\end{sankeyoption}
+
+The initial ratio is 1\,cm/10 units.
+
+
+\textbf{Note:} the \code{sankey} package uses the \code{xfp} package to
+evaluate all math expressions that use quantities (in units of
+flow). You can therefore use quantities of a very large or very small
+order of magnitude. In contrast, for graphic distances, the sankey
+package uses the \code{pgfmath} package (all calculations must not
+exceed $\pm 16383.99999$).
+
+% ------------------------------------------------------------
+\subsection{Keys to define drawing parameters}
+% ------------------------------------------------------------
+
+\begin{sankeyoption}{minimum radius}{\VAR{distance}}{}{5mm}
+  The minimum radius used by \code{\sankeyturn} and
+  \code{\sankeydubins}.
+\end{sankeyoption}
+
+\begin{sankeyoption}{outin steps}{\VAR{integer}}{}{10}
+  Number of steps used by the \code{\sankeyoutin} macro to simulate flow
+  lanes with constant width.
+\end{sankeyoption}
+
+% ------------------------------------------------------------
+\subsection{Keys to choose drawing styles}
+% ------------------------------------------------------------
+
+\begin{sankeyoption}{fill/.style}{\VAR{style}}{}{{line width=0pt,fill=white}}
+  This TikZ style is used to \emph{fill} all sankey paths.
+\end{sankeyoption}
+
+\begin{sankeyoption}{draw/.style}{\VAR{style}}{}{draw=black,line width=.4pt}
+  This TikZ style is used to \emph{draw} all sankey paths.
+\end{sankeyoption}
+
+\begin{sankeyoption}{start style}{\VAR{style name}}{}{none}
+  There are three predefined \emph{start} styles: \constant{none},
+  \constant{simple}, \constant{arrow}.
+\end{sankeyoption}
+
+\begin{sankeyoption}{end style}{\VAR{style name}}{}{none}
+  There are three predefined \emph{end} styles: \constant{none},
+  \constant{simple}, \constant{arrow}.
+\end{sankeyoption}
+
+% ------------------------------------------------------------
+\subsection{Keys to define new \emph{start} and \emph{end} styles}
+% ------------------------------------------------------------
+
+\begin{sankeyoption}{new start style}{\{\VAR{name}\}\{\VAR{fill
+      path}\}\{\VAR{draw path}\}}{}{}
+  Define the new start style named \VAR{name} with its \VAR{fill
+    path} and its \VAR{draw path}.
+\end{sankeyoption}
+
+\begin{sankeyoption}{new end style}{\{\VAR{name}\}\{\VAR{fill
+      path}\}\{\VAR{draw path}\}}{}{}
+  Define the new end style named \VAR{name} with its \VAR{fill
+    path} and its \VAR{draw path}.
+\end{sankeyoption}
+
+\emph{Fill} and \emph{draw} paths are composed in a TikZ scope where
+the origin is the current Sankey node center (and its name is
+\code{\name}) and the coordinate system is rotated by its orientation.
+
+% ------------------------------------------------------------
+\subsection{The \emph{debug} key}
+% ------------------------------------------------------------
+
+\begin{sankeyoption}{debug}{\VAR{boolean}}{true}{false}
+  To debug a sankey diagram.
+\end{sankeyoption}
+
+% ------------------------------------------------------------
+\section{Sankey nodes and flows}
+% ------------------------------------------------------------
+
+% ------------------------------------------------------------
+\subsection{Create Sankey nodes}
+% ------------------------------------------------------------
+
+% ------------------------------------------------------------
+
+\begin{miniblock}
+\MACRO\code{\sankeynode}\OPTARG{\VAR{options}}\ARG{\VAR{node parameters}}
+
+The \code{\sankeynode} macro defines a Sankey node. The \VAR{options}
+can be any Sankey diagram keys. To define a Sankey node, you must
+provide a \emph{name}, a \emph{quantity}, an \emph{angle} and a
+\emph{position} as \VAR{node parameters}.
+
+\begin{sankeyoption}[/sankey/node parameters]{name}{\VAR{name}}{}{}
+  The \VAR{name} of the new Sankey node (and the associated TikZ node).
+\end{sankeyoption}
+
+\begin{sankeyoption}[/sankey/node parameters]{quantity}{\VAR{quantity}}{}{}
+  The quantity (in flow unit) of the new Sankey node. The \VAR{quantity}
+  can be any math expression.
+\end{sankeyoption}
+
+\begin{sankeyoption}[/sankey/node parameters]{angle}{\VAR{angle}}{}{}
+  The orientation of the flow (0 points to the right) of the new Sankey
+  node.
+\end{sankeyoption}
+
+\begin{sankeyoption}[/sankey/node parameters]{at}{\VAR{at}}{}{}
+  The position of the new Sankey node (a TikZ coordinate \emph{without}
+  round brackets or parentheses).
+\end{sankeyoption}
+
+\begin{sankeyoption}[/sankey/node parameters]{anchor}{\VAR{anchor}}{center}{center}
+  Specify the anchor of the Sankey node. Possible values are
+  \constant{center}, \constant{left} or \constant{right}.
+\end{sankeyoption}
+
+\begin{sankeyoption}[/sankey/node parameters]{as}{\VAR{name}}{}{}
+  Copy the \emph{name}, the \emph{quantity}, the \emph{angle} and the
+  \emph{position} of the Sankey node named \VAR{name}.
+\end{sankeyoption}
+
+A Sankey node is also a Tikz node but with only three anchors:
+\code{left}, \code{center} and \code{right}.
+
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}[debug]
+    \draw[gray!30] (-1,-1) grid (8,2);
+    \sankeynode{name=a,quantity=10,angle=0,at={0,0}}
+    \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+    \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
+
+    \foreach \nodename/\pos in {a/left,b/below left,c/above}{
+      \foreach \ancname in {left,center,right}{
+        \node[node font=\ttfamily\footnotesize,\pos=1mm of \nodename.\ancname,
+        inner sep=0pt,rotate=\sankeygetnodeorient{\nodename},anchor=east]
+        {\ancname\vphantom{g}};
+        \fill[black] (\nodename.\ancname) circle(1pt);
+      }
+    }
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+% ------------------------------------------------------------
+
+\begin{miniblock}
+\MACRO\code{\sankeynodestart}\OPTARG{\VAR{options}}\ARG{\VAR{node parameters}}
+
+The \code{\sankeynodestart} creates and fills/draws a starting Sankey node:
+
+
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}]
+    \draw[gray!30] (-1,-1) grid (8,2);
+    \sankeynodestart{name=a,quantity=10,angle=0,at={0,0}}
+    \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+    \sankeynodestart{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+% ------------------------------------------------------------
+
+
+\begin{miniblock}
+\MACRO\code{\sankeynodeend}\OPTARG{\VAR{options}}\ARG{\VAR{node
+    parameters}}
+
+The \code{\sankeynodeend} creates
+and fills/draws an ending Sankey node:
+
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}[end style=simple,fill/.style={fill=orange!20}]
+    \draw[gray!30] (-1,-1) grid (8,2);
+    \sankeynodeend{name=a,quantity=10,angle=0,at={0,0}}
+    \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+    \sankeynodeend{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+
+\subsection{Retrieve informations from a Sankey node}
+
+\MACRO\code{\sankeygetnodeqty}\ARG{\VAR{node name}}
+
+The expandable command \code{\sankeygetnodeqty} returns the quantity
+assigned to the Sankey node named \VAR{node name}.
+
+\MACRO\code{\sankeygetnodeorient}\ARG{\VAR{node name}}
+
+The expandable command \code{\sankeygetnodeorient} returns the angle
+(orientation) assigned to the Sankey node named \VAR{node name}.
+
+% ------------------------------------------------------------
+\newpage
+\subsection{Move nodes}
+% ------------------------------------------------------------
+
+The \code{\sankeyadvance} and \code{\sankeyturn} commands move a Sankey
+node (and fill/draw a portion of the Sankey flow). Then the previous
+position of the Sankey node is accessible via the \code{-old} suffix (if
+you move the \code{a} node, its previous position is the \code{a-old}
+node).
+
+\subsubsection{forward commands}
+
+\begin{miniblock}
+\MACRO\code{\sankeyadvance}\OPTARG{\VAR{options}}\ARG{\VAR{node
+    name}}\ARG{\VAR{distance}}
+
+The \code{\sankeyadvance} moves the sankey node straight ahead and
+fills/draws this portion of the sankey path.
+
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}]
+    \draw[gray!30] (-1,-1) grid (8,2);
+    \sankeynodestart{name=a,quantity=10,angle=0,at={0,0}}
+    \sankeyadvance{a}{1cm}
+    \sankeynode[debug]{as=a}
+    \sankeynode[debug]{as=a-old}
+    \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+    \sankeyadvance{b}{1cm}
+    \sankeynodestart{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
+    \sankeyadvance{c}{5mm}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+
+\begin{miniblock}
+\MACRO\code{\sankeyturn}\OPTARG{\VAR{options}}\ARG{\VAR{node
+    name}}\ARG{\VAR{angle}}
+
+The \code{\sankeyturn} macro moves the sankey node by turning to one
+side or the other and fills/draws this portion of the sankey path. A
+\emph{positive} \VAR{angle} turns left while a \emph{negative}
+\VAR{angle} turns right.
+
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}]
+    \draw[gray!30] (-1,-1) grid (8,2);
+    \sankeynodestart{name=a,quantity=10,angle=0,at={0,0}}
+    \sankeyturn{a}{90}
+    \sankeynode[debug]{as=a}
+    \sankeynode[debug]{as=a-old}
+    \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+    \sankeyturn[minimum radius=1cm]{b}{-45}
+    \sankeynodestart{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
+    \sankeyturn{c}{180}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+
+\subsubsection{backward commands}
+
+\begin{miniblock}
+\MACRO\code{\sankeyadvance*}\OPTARG{\VAR{options}}\ARG{\VAR{node
+    name}}\ARG{\VAR{distance}}
+
+The \code{\sankeyadvance*} moves the sankey node straight back and
+fills/draws this portion of the sankey path.
+
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}[end style=arrow,fill/.style={fill=orange!20}]
+    \draw[gray!30] (-1,-1) grid (8,2);
+    \sankeynodeend{name=a,quantity=10,angle=0,at={0,0}}
+    \sankeyadvance*{a}{1cm}
+    \sankeynode[debug]{as=a}
+    \sankeynode[debug]{as=a-old}
+    \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+    \sankeyadvance*{b}{1cm}
+    \sankeynodeend{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
+    \sankeyadvance*{c}{5mm}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+
+\begin{miniblock}
+\MACRO\code{\sankeyturn*}\OPTARG{\VAR{options}}\ARG{\VAR{node
+    name}}\ARG{\VAR{angle}}
+
+The \code{\sankeyturn*} macro moves the sankey node backwards by turning
+right or left and fills/draws this portion of the sankey path. A
+\emph{positive} \VAR{angle} turns left while a \emph{negative}
+\VAR{angle} turns right.
+
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}[end style=simple,fill/.style={fill=orange!20}]
+    \draw[gray!30] (-1,-1) grid (8,2);
+    \sankeynodeend{name=a,quantity=10,angle=0,at={0,0}}
+    \sankeyturn*{a}{90}
+    \sankeynode[debug]{as=a}
+    \sankeynode[debug]{as=a-old}
+    \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+    \sankeyturn*[minimum radius=1cm]{b}{-45}
+    \sankeynodeend{name=c,quantity=10,angle=-90,at={5,1},anchor=right}
+    \sankeyturn*{c}{180}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+
+\subsection{Links between nodes}
+
+\begin{miniblock}
+  \MACRO\code{\sankeyoutin}\OPTARG{\VAR{options}}\ARG{\VAR{node
+      A}}\ARG{\VAR{node B}}
+  
+  The \code{\sankeyoutin} macro fills/draws a lane between \VAR{node A}
+  and \VAR{node B} using a Bézier curve with regular steps (10 steps by
+  default) to simulate constant width lane.
+  
+  The constant width and the minimum curvature are \emph{not} guaranted!
+\end{miniblock}
+
+\begin{miniblock}
+  \MACRO\code{\sankeydubins}\OPTARG{\VAR{options}}\ARG{\VAR{node
+      A}}\ARG{\VAR{node B}}
+  
+  The \code{\sankeydubins} macro fills/draws a lane between \VAR{node A}
+  and \VAR{node B} using a Dubins
+  path\footnote{\url{https://en.wikipedia.org/wiki/Dubins_path}}.
+  
+  The constant width and the minimum curvature are guaranted.
+\end{miniblock}
+
+\subsubsection{Comparison betwen \texttt{outin} and \texttt{dubins}
+  paths}
+
+\begin{miniblock}
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}[start style=simple,end style=arrow]
+    \draw[gray!30] (0,-1) grid (10,3.5);
+    % 
+    \sankeyset{fill/.style={fill=orange!20}}
+    \sankeynodestart{name=a,at={1,0},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={5,3},angle=0,quantity=5}
+    \sankeyoutin{a}{b}
+    % 
+    \sankeyset{fill/.style={fill=red!20}}
+    \sankeynodestart{name=a,at={3,0},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={7,3},angle=0,quantity=5}
+    \sankeyoutin[outin steps=2]{a}{b}
+    %
+    \sankeyset{fill/.style={fill=lime!40}}
+    \sankeynodestart{name=a,at={5,0},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={(9,3},angle=0,quantity=5}
+    \sankeydubins[minimum radius=5mm]{a}{b}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+
+\begin{miniblock}
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}[start style=simple,end style=arrow]
+    \draw[gray!30] (0,0) grid (8,4.5);
+    % 
+    \sankeyset{fill/.style={fill=orange!20}}
+    \sankeynodestart{name=a,at={1,1},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={3,4},angle=0,quantity=5}
+    \sankeyoutin{a}{b}
+    % 
+    \sankeyset{fill/.style={fill=red!20}}
+    \sankeynodestart{name=a,at={3,1},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={5,4},angle=0,quantity=5}
+    \sankeyoutin[outin steps=2]{a}{b}
+    %
+    \sankeyset{fill/.style={fill=lime!40}}
+    \sankeynodestart{name=a,at={5,1},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={(7,4},angle=0,quantity=5}
+    \sankeydubins[minimum radius=5mm]{a}{b}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+
+\begin{miniblock}
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}[start style=simple,end style=arrow]
+    \draw[gray!30] (0,0) grid ((6,4.5);
+    % 
+    \sankeyset{fill/.style={fill=orange!20}}
+    \sankeynodestart{name=a,at={1,1},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={1,4},angle=0,quantity=5}
+    \sankeyoutin{a}{b}
+    % 
+    \sankeyset{fill/.style={fill=red!20}}
+    \sankeynodestart{name=a,at={3,1},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={3,4},angle=0,quantity=5}
+    \sankeyoutin[outin steps=2]{a}{b}
+    %
+    \sankeyset{fill/.style={fill=lime!40}}
+    \sankeynodestart{name=a,at={5,1},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={(5,4},angle=0,quantity=5}
+    \sankeydubins[minimum radius=5mm]{a}{b}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+
+\subsubsection{Examples of \texttt{dubins} paths}
+
+\begin{miniblock}
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}[start style=simple,end style=arrow]
+    \draw[gray!30] (-1,-1) grid (10,2.5);
+
+    \sankeyset{
+      fill/.style={fill=lime!40},
+      draw/.style={draw=green!50!black,line width=2pt},
+    }
+
+    \sankeynodestart{name=a,at={0,0},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={0,2},angle=0,quantity=5}
+    \sankeydubins[minimum radius=2mm]{a}{b}
+
+    \fill[green!50!black] (2,0) coordinate (c) circle(2pt);
+    \sankeynodestart{name=a,at={[shift={(c)}]90:5mm},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={[shift={(c)}]150:5mm},angle=60,quantity=5}
+    \sankeydubins[minimum radius=2.5mm]{a}{b}
+    
+    \sankeynodestart{name=a,at={3.5,0},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={3.5,.75},angle=-180,quantity=5}
+    \sankeydubins[minimum radius=5mm]{a}{b}
+
+    \sankeynodestart{name=a,at={7,1},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={7,1.75},angle=0,quantity=5}
+    \sankeydubins[minimum radius=2.5mm]{a}{b}
+
+    \sankeynodestart{name=a,at={9,0},angle=0,quantity=5}
+    \sankeynodeend{name=b,at={9,2},angle=180,quantity=5}
+    \sankeydubins[minimum radius=2.5mm]{a}{b}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+
+\subsection{Pure filling/drawing macros}
+
+\begin{miniblock}
+\MACRO\code{\sankeystart}\OPTARG{\VAR{options}}\ARG{\VAR{name}}
+
+The \code{\sankeystart} fills/draws a starting extremity attached to the
+preexistent Sankey node \VAR{name}:
+
+
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}
+    [start style=arrow,fill/.style={fill=cyan!20},draw/.style={draw=blue}]
+    \draw[gray!30] (-1,-1) grid (8,2);
+    \sankeynode{name=a,quantity=10,angle=0,at={0,0}}
+    \sankeystart{a}
+    \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+    \sankeystart{b}
+    \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
+    \sankeystart{c}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+% ------------------------------------------------------------
+
+
+\begin{miniblock}
+  \MACRO\code{\sankeyend}\OPTARG{\VAR{options}}\ARG{\VAR{name}}
+  
+  The \code{\sankeyend} fills/draws an ending extremity attached to the
+  preexistent Sankey node \VAR{name}:
+  
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}
+    [end style=simple,fill/.style={fill=cyan!20},draw/.style={draw=blue}]
+    \draw[gray!30] (-1,-1) grid (8,2);
+    \sankeynode{name=a,quantity=10,angle=0,at={0,0}}
+    \sankeyend{a}
+    \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left}
+    \sankeyend{b}
+    \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right}
+    \sankeyend{c}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+% 
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+% 
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+
+\subsection{Forked node}
+
+\begin{miniblock}
+  \MACRO\code{\sankeyfork}\OPTARG{\VAR{options}}\ARG{\VAR{node}}\ARG{\VAR{quantity/name pairs}}
+
+  The \code{\sankeyfork} macro splits a Sankey node in a list of new
+  Sankey nodes. The \VAR{quantity/name pairs} is a comma separated list
+  of \emph{quantity/name} pairs. The sum of all quantities \emph{must}
+  be equal to the quantity of the node to fork.
+  
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}[debug]
+    \draw[gray!30] (-3,-2) grid (3,1);
+    \sankeynode{name=a,quantity=50,angle=-80,at={0,0}}
+    \sankeyfork{a}{30/b,10/c,10/d}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+% 
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \begin{sankeydiagram}
+    \sankeyset{
+      start style=arrow,end style=arrow,
+      fill/.style={fill=yellow!10,line width=0pt,draw=yellow!10},
+    }
+    \draw[gray!30] (-4,-3) grid (4,4);
+    \sankeynode{name=a,quantity=40,angle=-90,at={0,0}}
+    \sankeyfork{a}{25/b,10/c,5/d}
+    \sankeyturn*{b}{90}
+    \sankeyturn*[minimum radius=2cm]{c}{-45}
+    \sankeyturn*[minimum radius=2cm]{c}{45}
+    \sankeyturn*[minimum radius=5mm]{d}{-90}
+    \sankeyadvance{a}{2cm}
+    \foreach \nodename in {b,c,d}{
+      \sankeystart{\nodename}
+    }
+    \sankeyend{a}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+% 
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+{\centering\input{\samplecodename}\par}
+\end{miniblock}
+
+\section{Miscellaneous}
+
+\subsection{The \texttt{debug} layer}
+
+The \code{debug} option key uses the \code{sankeydebug} layer to draw
+above the \code{main} TikZ layer (via \code{\pgfsetlayers}, the
+\code{sankey} package installs four layers: \code{background},
+\code{main}, \code{foreground}, \code{sankeydebug}).
+
+The four following styles define how to display debug informations:
+
+
+\begin{lstlisting}[style=LaTeXsmall]
+\sankeyset{
+  % debug color used by all debug macros
+  debug color/.style={/utils/exec={\colorlet{debug color}{#1}}},
+  debug color=red!75!black,
+  % debug line between left and right anchors
+  debug line/.style={draw=debug color,|-|},
+  % debug line between center and label
+  debug normal/.style={draw=debug color},
+  % debug node label
+  debug label/.style={
+    draw,
+    font=\ttfamily\tiny,
+    text=debug color,text opacity=1,
+    inner sep=.1em,
+    fill=white,fill opacity=1,
+    rounded corners=.1em,
+  },
+}
+\end{lstlisting}
+
+\subsection{The \texttt{dubins} TikZ library}
+
+The \code{sankey} package uses the \code{dubins} TikZ library (the
+\code{tikzlibrarydubins.code.tex} file) to compute Dubins paths. The
+documentation for this library does not yet exist.
+
+\subsection{How to duplicate a Sankey node}
+
+\MACRO\code{\sankeynodealias}\ARG{\VAR{origname}}\ARG{\VAR{clonename}}
+
+The \code{\sankeynodealias} macro clones the Sankey node named
+\VAR{origname} into the Sankey node named \VAR{clonename}.
+
+So, you can clone a Sankey node via two methods:
+
+\begin{lstlisting}[style=LaTeXsmall]
+\sankeynode{name=a,quantity=10,angle=0,at={0,0}}
+\sankeynode{as=a,name=b}
+\end{lstlisting}
+
+\begin{lstlisting}[style=LaTeXsmall]
+\sankeynode{name=a,quantity=10,angle=0,at={0,0}}
+\sankeynodealias{a}{b}
+\end{lstlisting}
+
+\subsection{How to define new start and end styles}
+
+Here are the definitions of the \code{arrow} styles:
+
+\begin{lstlisting}[style=LaTeXsmall]
+\sankeyset{
+  % arrow style
+  new start style={arrow}{
+    (\name.left) -- ++(-10pt,0)
+    -- ([xshift=-10pt/6]\name.center)
+    -- ([xshift=-10pt]\name.right)
+    -- (\name.right) -- cycle
+  }{
+    (\name.left) -- ++(-10pt,0)
+    -- ([xshift=-10pt/6]\name.center)
+    -- ([xshift=-10pt]\name.right)
+    -- (\name.right)
+  },
+  new end style={arrow}{
+    (\name.left) -- ([yshift=1mm]\name.left)
+    -- ([xshift=10pt]\name.center)
+    -- ([yshift=-1mm]\name.right) -- (\name.right) -- cycle
+  }{
+    (\name.left) -- ([yshift=1mm]\name.left)
+    -- ([xshift=10pt]\name.center)
+    -- ([yshift=-1mm]\name.right) -- (\name.right)
+  },
+}
+\end{lstlisting}
+
+\section{History}
+
+\begin{itemize}
+\item[v2.0] (2021/01/27)
+  \begin{itemize}
+  \item First public version (on CTAN).
+  \end{itemize}
+\item[v1.0] (2016/03/06)
+  \begin{itemize}
+  \item First version.
+  \end{itemize}
+\end{itemize}
+
+\clearpage
+\section{Examples}
+
+\subsection{Simple example}
+
+See figure~\ref{fig:simple-example}.
+
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \colorlet{cold}[rgb]{cyan!75!blue!50!white}
+  \colorlet{hot}[rgb]{red!50!orange!75!white}
+  \begin{sankeydiagram}
+    \sankeyset{
+      ratio=90pt/6,
+      minimum radius=15pt,
+      start style=simple,
+      end style=simple,
+      % debug,
+      draw/.style={
+        draw=blue!50!cyan,
+        line width=1pt,
+        line cap=round,line join=round,
+      },
+      cold/.style={
+        fill/.style={
+          draw=cold,
+          line width=0pt,
+          fill=cold,
+        },
+      },
+      cold to hot/.style={
+        fill/.style={
+          fill=none,
+          top color=cold,
+          bottom color=hot,
+          middle color=yellow,
+        },
+      },
+      hot/.style={
+        fill/.style={
+          draw=hot,
+          line width=0pt,
+          fill=hot,
+        },
+      },
+    }
+
+    \sankeyset{cold}
+    \sankeynodestart{name=p0,at={0,100},angle=-90,quantity=6}
+    \sankeyadvance{p0}{50pt}
+    
+    \sankeyfork{p0}{3/p1,3/p2}
+
+    \sankeyturn{p1}{90}
+    \sankeyadvance{p1}{20pt}
+
+    \sankeyadvance{p2}{60pt}
+
+    \sankeyfork{p2}{2/p3,1/p4}
+
+    \sankeyturn{p3}{90}
+    \sankeyadvance{p3}{50pt}
+
+    \sankeyfork{p3}{1/p5,1/p6}
+
+    \sankeyadvance{p5}{70pt}
+
+    \sankeyfork{p1}{1/p7,1/p8,1/p9}
+    \sankeyadvance{p7}{50pt}
+    \sankeyadvance{p9}{50pt}
+
+    \sankeyadvance{p4}{40pt}
+    \sankeyturn{p4}{90}
+    \sankeyadvance{p4}{65pt}
+
+    \sankeyadvance{p7}{40pt}
+
+    \sankeynode{name=p11,at={[shift={(50pt,-15pt)}]p7},angle=0,quantity=3}
+    \sankeyfork{p11}{1/p7a,1/p9a,1/p5a}
+    \sankeyoutin{p7}{p7a}
+    \sankeyoutin{p9}{p9a}
+    \sankeyoutin{p5}{p5a}
+    \sankeyadvance{p11}{30pt}
+    \sankeyend{p11}
+
+    \sankeyturn{p8}{-90}
+    \sankeyturn{p6}{-90}
+    \sankeyturn{p4}{-90}
+    
+    \sankeyset{hot}
+    
+    \sankeyadvance[cold to hot]{p8}{40pt}
+    
+    \sankeynode{name=p10,at={[shift={(-15pt,-60pt)}]p8},angle=-90,quantity=3}
+    \sankeyfork{p10}{1/p8a,1/p6a,1/p4a}
+    \sankeyoutin[cold to hot]{p4}{p4a}
+    \sankeyoutin[cold to hot]{p6}{p6a}
+    \sankeyoutin{p8}{p8a}
+    \sankeyadvance{p10}{30pt}
+    \sankeyend{p10}
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+% 
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+\begin{figure}[b!]
+  \centering
+  \input{\samplecodename}
+  \caption{Simple example}
+  \label{fig:simple-example}
+\end{figure}
+\clearpage
+\subsection{Example from question on TeX.se}
+
+This example cames from
+\href{https://tex.stackexchange.com/q/40159/14500}{this question} on
+\href{https://tex.stackexchange.com/}{TeX.StackExchange}.
+
+See figure~\ref{fig:texse-example}.
+
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  \renewcommand*\sfdefault{txss}
+
+  \begin{sankeydiagram}
+
+    \sankeyset{
+      ratio=4cm/524.3,
+      minimum radius=3mm,
+      start style=arrow,
+      end style=arrow,
+      % debug,
+      fill/.style={
+        line width=0pt,
+        fill=cyan!50!blue!50!black,
+        draw=cyan!50!blue!50!black,
+      },
+      draw/.style={draw=none},
+    }
+    
+    \sankeynodestart{name=B,at={-.5,0},angle=-90,quantity=7.2}
+    \coordinate[below=1mm of B.center] (B label);
+    \sankeyadvance{B}{5mm}
+    \sankeynodestart{name=GI,at={1,0},angle=-90,quantity=137.3}
+    \coordinate[below=1mm of GI.center] (GI label);
+    \sankeyadvance{GI}{5mm}
+    \sankeynodestart{name=I,at={4,0},angle=-90,quantity=397.8}
+    \coordinate[below=1mm of I.center] (I label);
+    \sankeynode{name=EI,at={2.86,-3},angle=-90,quantity=542.3}
+    \sankeyfork{EI}{397.8/Ia,137.3/GIa,7.2/Ba}
+    \sankeydubins[minimum radius=1.2cm]{I}{Ia}
+    \sankeyoutin{GI}{GIa}
+    \sankeyoutin{B}{Ba}
+    \sankeyadvance{EI}{5mm}
+    \coordinate (EI label) at (EI);
+    \sankeyadvance{EI}{5mm}
+    \sankeyfork{EI}{63.1/EB,479.2/P}
+
+    \sankeyturn{EB}{90}
+    \sankeyadvance{EB}{4cm}
+    \coordinate (EB label) at ($(EB)!.5!(EB-old)$);
+    \sankeyend{EB}
+
+    \sankeyadvance{P}{10mm}
+    \coordinate (P label) at (P);
+    \sankeyadvance{P}{5mm}
+
+    \sankeyfork{P}{33.5/NV,445.7/P}
+    
+    {
+      \colorlet{NV color}{cyan!80!lime!50!gray}
+      \sankeyset{fill/.append style={fill=NV color,draw=NV color}}
+      \sankeyturn{NV}{90}
+      \sankeynode{as=NV,name=NV2,at=NV -| EB}
+      \sankeyoutin{NV}{NV2}
+      \coordinate (NV label) at (NV -| EB label);
+      \sankeyend{NV2}
+    }
+
+    \sankeyadvance{P}{10mm}
+    \sankeyfork{P}{118.1/U,327.6/P}
+
+    {
+      \sankeyset{
+        fill/.style={fill=orange!70!gray!50,draw=orange!70!gray!50}
+      }
+      \sankeyturn{U}{90}
+      \sankeynode{as=U,name=U2,at=U -| EB}
+      \sankeyoutin{U}{U2}
+      \coordinate (U label) at (U -| EB label);
+      \sankeyend{U2}
+    }
+
+    \sankeyadvance{P}{10mm}
+
+    \sankeyfork{P}{327.2/P,0.4/SD}
+
+    {
+      \sankeyturn{SD}{-90}
+      \sankeyadvance{SD}{15mm}
+      \coordinate (SD label) at (SD);
+      \sankeyadvance{SD}{15mm}
+      \sankeyend{SD}
+    }
+    
+    \sankeyadvance{P}{8mm}
+    \sankeyfork{P}{18.8/VE,308.4/E}
+
+    {
+      \sankeyset{fill/.append style={orange!70!gray!30}}
+      \sankeyturn{VE}{90}
+      \sankeynode{as=VE,name=VE2,at=VE -| EB}
+      \sankeyoutin{VE}{VE2}
+      \coordinate (VE label) at (VE -| EB label);
+      \sankeyend{VE2}
+    }
+    
+    \sankeyadvance{E}{8mm}
+    \coordinate (E label) at (E);
+    \sankeyadvance{E}{20mm}
+    
+    \sankeyfork{E}{135.1/H+GHD,87.2/V,86.1/In}
+
+    \sankeyturn{In}{-90}
+    \sankeyadvance{In}{10mm}
+    \sankeyturn{In}{90}
+    \sankeyadvance{In}{5mm}
+    \coordinate (In label)  at (In);
+    \sankeyadvance{In}{10mm}
+    \sankeyend{In}
+
+    \sankeynode{as=V,name=V2,at=V|-In label}
+    \sankeyoutin{V}{V2}
+    \coordinate (V label) at (V2);
+    \sankeyadvance{V2}{10mm}
+    \sankeyend{V2}
+    
+    \sankeyturn{H+GHD}{90}
+    \sankeyadvance{H+GHD}{5mm}
+    \sankeyfork{H+GHD}{47.0/GHD,88.1/H}
+
+    \sankeyturn{H}{-90}
+    \sankeynode{as=H,name=H2,at=H|-In label}
+    \sankeyoutin{H}{H2}
+    \coordinate (H label) at (H2);
+    \sankeyadvance{H2}{10mm}
+    \sankeyend{H2}
+
+    \sankeyadvance{GHD}{30mm}
+    \sankeyturn{GHD}{-90}
+    \sankeynode{as=GHD,name=GHD2,at=GHD|-In label}
+    \sankeyoutin{GHD}{GHD2}
+    \coordinate (GHD label) at (GHD2);
+    \sankeyadvance{GHD2}{10mm}
+    \sankeyend{GHD2}
+  \end{sankeydiagram}
+  
+  % labels
+  \tikzset{
+    label/.style={
+      fill=white,fill opacity=.8,text opacity=1,
+      inner sep=1mm,
+      text=cyan!50!blue!50!black,
+      inner xsep=2mm,
+      font=\sffamily\bfseries\footnotesize,
+      align=center,
+    },
+  }
+  \node[label,anchor=north] (B label) at (B label) {7.2};
+  \node[label,left=1mm of B label] {Bestands-\\entnahme};
+  \node[label,anchor=north] at (GI label) {137.3};
+  \node[label,above=5mm of GI label] {Gewinnung\\im Inland};
+  \node[label,anchor=north] at (I label) {397.8};
+  \node[label,above=5mm of I label] {Import};
+  
+  \node[label] at (EI label) {542.3\\Energieaufkommen im Inland};
+  
+  \node[label,anchor=center] (EB label) at (EB label) {63.1};
+  \node[label,above=1mm of EB label] {Export und\\Bunkerung};
+  
+  \node[label] at (P label) {479.2\\Primärenergieverbrauch};
+
+  \node[label,anchor=center] (NV label) at (NV label) {33.5};
+  \node[label,above=0mm of NV label] {Nichtenergetischer Verbrauch};
+  
+  \node[label,anchor=center] (U label) at (U label) {118.1};
+  \node[label,below=3mm of U label] {Umwandlungsverluste};
+  
+  \node[label,anchor=center] (SD label) at (SD label) {0.4};
+  \node[label,above=0mm of SD label] {Statistische\\Differenzen};
+  
+  \node[label,anchor=center] (VE label) at (VE label) {18.8};
+  \node[label,below=0mm of VE label] {Verbrauch in den\\Energiesktoren};
+  
+  \node[label,anchor=north] (E label) at (E label)
+  {308.4\\Endenergieverbrauch};
+  
+  \node[label,anchor=north] (In label) at (In label) {86.1};
+  \node[label,anchor=north,below=1cm of In label] {Industrie};
+  
+  \node[label,anchor=north] (V label) at (V label) {87.2};
+  \node[label,anchor=north,below=1cm of V label] {Verkehr};
+  
+  \node[label,anchor=north] (H label) at (H label) {88.1};
+  \node[label,anchor=north,below=1cm of H label] {Haushalte};
+  
+  \node[label,anchor=north] (GHD label) at (GHD label) {47.0};
+  \node[label,anchor=north,below=1cm of GHD label]
+  {Gewerbe, Handel\\Diensleistungen};
+\end{tikzpicture}
+\end{filecontents*}
+% 
+\lstinputlisting[style=LaTeXsmall]{\samplecodename}
+%
+\begin{figure}
+  \centering
+  %\rule{\linewidth}{1pt}\\
+  \input{\samplecodename}
+  \caption{Example from TeX.se question}
+  \label{fig:texse-example}
+\end{figure}
+
+\clearpage
+\subsection{Very nice example -- Nadieh Bremer creation}
+
+Graphic designer Nadieh Bremer created this very nice Sankey
+diagram\footnote{\url{https://www.visualcinnamon.com/portfolio/adyen-report-2019/}}
+for Adyen's second half 2018 report to shareholders. It is coded here
+with her kind permission.
+
+You can change the data values between lines 28 and 53.
+
+See figure~\ref{fig:nice-example}.
+
+\begin{filecontents*}{\samplecodename}
+\begin{tikzpicture}
+  % 
+  \renewcommand*\sfdefault{txss}
+  \sffamily
+  \sisetup{
+    detect-all=true,
+    group-separator={,},
+    group-minimum-digits=4,
+  }
+  % storage of labels
+  \newcommand\LabSet[2]{% none name, label
+    \expandafter\edef\csname #1Lab\endcsname{#2}}
+  \newcommand\Lab[1]{% node name
+    \csname #1Lab\endcsname}
+  % storage of quantities
+  \newcommand\QtySet[2]{% node name, quantity
+    \expandafter\edef\csname #1Qty\endcsname{\fpeval{#2}}}
+  \newcommand\Qty[1]{% node name
+    \csname #1Qty\endcsname}
+  % all nodes with their name, label and quantity
+  \sankeyset{
+    def data/.code args={#1/#2/#3}{% node name/label/values
+      \LabSet{#1}{#2}
+      \QtySet{#1}{#3}
+      \typeout{#1: \Qty{#1}€ (\Lab{#1})}
+    },
+    def data/.list={
+      {Pf/Processing\\fees/71713},
+      {Sog/Sales of\\good/4547},
+      {Sf/Settlement\\fees/842075},
+      {Os/Other\\services/37532},
+      {R/Revenues/\Qty{Pf}+\Qty{Sog}+\Qty{Sf}+\Qty{Os}},
+      {Coi/Cost of Inventory/5151},
+      {Ciffi/Cost insecure from financial institutions/758234},
+      {Nr/Net revenue/\Qty{R}-\Qty{Coi}-\Qty{Ciffi}},
+      {Aadotaifa/Amortization and\\depreciation of tangible and\\%
+        intangible fixed assets/4688},
+      {Ssapc/Social securities and\\pension costs/7860},
+      {Was/Wages and salaries/35627},
+      {Ooe/Other operating expenses/37346},
+      {Nr2/-/\Qty{Nr}-\Qty{Aadotaifa}-\Qty{Ssapc}-\Qty{Was}-\Qty{Ooe}},
+      {Oi/Other income/47},
+      {Ibiiieait/Income before interest income,\\interest expense and %
+        income taxes/\Qty{Nr2}+\Qty{Oi}},
+      {Fe/Finance expense/561},
+      {Ofr/Other financial results/2533},
+      {Ibiiieait2/-/\Qty{Ibiiieait}-\Qty{Fe}-\Qty{Ofr}},
+      {Fi/Finance income/204},
+      {Ibit/Income before income taxes/\Qty{Ibiiieait2}+\Qty{Fi}},
+      {It/Income taxes/21134},
+      {Niftp/Net income for the period/\Qty{Ibit}-\Qty{It}},
+      {Octa/Other currency\\translation adjustments/785},
+      {Tci/Total comprehensive income/\Qty{Niftp}+\Qty{Octa}}
+    },
+  }
+  
+  \definecolor{mygreen}{RGB}{9,192,82}
+  \tikzset{
+    cost node/.style 2 args={
+      overlay,
+      align=flush center,
+      node font=\footnotesize\sffamily\bfseries,
+      inner sep=0,
+      node contents={%
+        {\mdseries€\,\num{#1}}\\%
+        #2\vphantom{g}%
+      },
+    },
+    white hash/.style={
+      draw=none,fill=none,
+      pattern={Lines[angle=60,line width=2pt,distance=4pt]},
+      pattern color=white,
+    },
+    line sep/.style={draw=white,line width=1pt},
+    left label/.style={left=#1,align=flush right,anchor=north east},
+    right label/.style={right=#1,align=flush left},
+    right label hashed/.style={
+      right=1mm of $(#1.left)!.5!(#1-old.left)$,align=flush left,
+    },
+    left label hashed/.style={
+      left=1mm of $(#1.right)!.5!(#1-old.right)$,align=flush right,
+    },
+  }
+  
+  \newcommand\turnandstop[1]{
+    \sankeyturn[green to greenwhite]{#1}{-90}
+    \sankeynode{as=#1,name=#1-e,at={#1 -| Coi}}
+    \sankeyoutin[greenwhite to white]{#1}{#1-e}
+    \node[cost node={\Qty{#1}}{\Lab{#1}},left label={1mm of #1-e.right}];
+  }
+    
+  \begin{sankeydiagram}
+    \sankeyset{
+      ratio=28em/1000000,
+      minimum radius=2cm,
+      start style=none,
+      % default fill and draw styles
+      fill/.style={
+        line width=0pt,
+        fill=mygreen,
+      },
+      draw/.style={draw=none},
+      % specific fill and draw styles
+      green to greenwhite/.style={
+        fill/.style={
+          line width=0pt,
+          right color=mygreen,
+          left color=mygreen!20!white,
+        }
+      },
+      greenwhite to white/.style={
+        fill/.style={
+          line width=0pt,
+          right color=mygreen!20!white,
+          left color=mygreen!5!white,
+        }
+      },
+      dashed/.style={draw/.style={draw=mygreen,dashed}},
+      % debug,
+    }
+
+    \coordinate (top) at (0,2em);
+    
+    \sankeynodestart{name=Pf,quantity=\Qty{Pf},
+      at={0,0},angle=-90}
+    \node[cost node={\Qty{Pf}}{\Lab{Pf}},above=.5em of Pf.center];
+    
+    \sankeynodestart{name=Sog,quantity=\Qty{Sog},
+      at={[xshift=4em]Pf.left},angle=-90,anchor=right}
+    \node[cost node={\Qty{Sog}}{\Lab{Sog}},above=.5em of Sog.center];
+    
+    \sankeynodestart{name=Sf,quantity=\Qty{Sf},
+      at={[xshift=2em]Sog.left},angle=-90,anchor=right}
+    \node[cost node={\Qty{Sf}}{\Lab{Sf}},above=.5em of Sf.center];
+
+    \sankeynodestart{name=Os,quantity=\Qty{Os},
+      at={[xshift=2em]Sf.left},angle=-90,anchor=right}
+    \node[cost node={\Qty{Os}}{\Lab{Os}},above=.5em of Os.center];
+
+    \sankeynode{name=R,quantity=\Qty{R},
+      at={[yshift=-10em]Sf.center},angle=-90}
+    \sankeyfork{R}{\Qty{Os}/Os-a,\Qty{Sf}/Sf-a,\Qty{Sog}/Sog-a,\Qty{Pf}/Pf-a}
+
+    \foreach \nodename in {Pf,Sog,Sf,Os}{
+      \sankeyoutin[fill/.style={top color=white,bottom color=mygreen}]
+      {\nodename}{\nodename-a}
+    }
+
+    \sankeyadvance{R}{1em}
+    \node[cost node={\Qty{R}}{\Lab{R}},right label hashed=R];
+
+    \sankeyfork{R}{\Qty{Ciffi}/Ciffi,\Qty{Nr}/Nr,\Qty{Coi}/Coi}
+
+    \sankeyturn[minimum radius=1.cm]{Ciffi}{90}
+    \node[cost node={\Qty{Ciffi}}{\Lab{Ciffi}},
+    at={([shift={(1mm,0)}]Ciffi.center)},rotate=-90,
+    anchor=south,align=flush left,node font=\scriptsize\sffamily\bfseries];
+
+    \sankeyturn[green to greenwhite]{Coi}{-90}
+    \sankeyadvance[greenwhite to white]{Coi}{1em}
+    \node[cost node={\Qty{Coi}}{\Lab{Coi}},
+    left={1mm of [yshift=.75ex]Coi.left},
+    align=flush right,anchor=north east,overlay];
+
+    \sankeyadvance{Nr}{9em}
+    \sankeyadvance{Nr}{1em}
+    \node[cost node={\Qty{Nr}}{\Lab{Nr}},
+    left label hashed=Nr,node font=\large\sffamily\bfseries];
+
+    \sankeyfork{Nr}{\Qty{Nr2}/Nr2,\Qty{Ooe}/Ooe,
+      \Qty{Was}/Was,\Qty{Ssapc}/Ssapc,\Qty{Aadotaifa}/Aadotaifa}
+    
+    \turnandstop{Aadotaifa}
+    
+    \sankeyadvance{Ssapc}{5em}
+    \turnandstop{Ssapc}
+    
+    \sankeyadvance{Was}{9em}
+    \turnandstop{Was}
+    
+    \sankeyadvance{Ooe}{12em}
+    \turnandstop{Ooe}
+    
+    \sankeyadvance{Nr2}{15em}
+    \sankeynode{name=Ibiiieait,quantity=\Qty{Ibiiieait},
+      angle=-90,anchor=right,at={Nr2.right}}
+    \sankeyfork{Ibiiieait}{\Qty{Oi}/Oi,\Qty{Nr2}/Nr2-e}
+    
+    \sankeyturn*[minimum radius=1cm,dashed]{Oi}{90}
+    \node[cost node={\Qty{Oi}}{\Lab{Oi}},right label=1mm of Oi.left];
+
+    \sankeyadvance{Ibiiieait}{1em}
+    \node[cost node={\Qty{Ibiiieait}}{\Lab{Ibiiieait}},
+    right label hashed=Ibiiieait];
+
+    \sankeyfork{Ibiiieait}
+    {\Qty{Ibiiieait2}/Ibiiieait2,\Qty{Ofr}/Ofr,\Qty{Fe}/Fe}
+
+    \turnandstop{Fe}
+    
+    \sankeyadvance{Ofr}{3em}
+    \turnandstop{Ofr}
+    
+    \sankeyadvance{Ibiiieait2}{6em}
+    \sankeynode{name=Ibit,quantity={\Qty{Ibiiieait2}+\Qty{Fi}},
+      angle=-90,anchor=right,at={Ibiiieait2.right}}
+    \sankeyfork{Ibit}{\Qty{Fi}/Fi,\Qty{Ibiiieait2}/Ibiiieait2-e}
+
+    \sankeyturn*[minimum radius=1cm,dashed]{Fi}{90}
+    \node[cost node={\Qty{Fi}}{\Lab{Fi}},right label=1mm of Fi.left];
+
+    \sankeyadvance{Ibit}{1em}
+    \node[cost node={\Qty{Ibit}}{\Lab{Ibit}},right label hashed=Ibit];
+
+    \sankeyfork{Ibit}{\Qty{Niftp}/Niftp,\Qty{It}/It}
+    
+    \turnandstop{It}
+    
+    \sankeyadvance{Niftp}{6em}
+
+    \sankeyadvance{Niftp}{1em}
+    \node[cost node={\Qty{Niftp}}{\Lab{Niftp}},right label hashed=Niftp];
+
+    \sankeynode{name=Tci,quantity=\Qty{Niftp}+\Qty{Octa},
+      angle=-90,anchor=right,at={[yshift=-6em]Niftp.right}}
+    \sankeyfork{Tci}{\Qty{Octa}/Octa,\Qty{Niftp}/Niftp-e}
+    \sankeyoutin{Niftp}{Niftp-e}
+    
+    \sankeyturn*[minimum radius=1cm]{Octa}{90}
+    \node[cost node={\Qty{Octa}}{\Lab{Octa}},right label=1mm of Octa.left];
+
+    \sankeyadvance{Tci}{1em}
+    \node[cost node={\Qty{Tci}}{\Lab{Tci}},right label hashed=Tci];
+
+    \newcommand\hashband[1]{
+      \draw[line sep] (#1-old.right) -- (#1-old.left);
+      \draw[line sep] (#1.right) -- (#1.left);
+      \path[white hash] (#1-old.right) rectangle (#1.left);
+    }
+
+    \foreach \nodename in {R,Nr,Nr,Ibiiieait,Ibit,Niftp,Tci}{
+      \hashband{\nodename}
+    }
+      
+  \end{sankeydiagram}
+\end{tikzpicture}
+\end{filecontents*}
+%
+\lstinputlisting[numbers=left,style=LaTeXsmall]{\samplecodename}
+%
+\begin{figure}
+  \centering
+  \input{\samplecodename}
+  \caption{Very nice example -- Nadieh Bremer's creation}
+  (from
+  \href{https://www.visualcinnamon.com/portfolio/adyen-report-2019/}{Adyen's
+    Shareholder Report})
+  \label{fig:nice-example}
+\end{figure}
+\end{document}
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: t
+%%% End:


Property changes on: trunk/Master/texmf-dist/doc/latex/sankey/sankey-doc.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/latex/sankey/sankey.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/sankey/sankey.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/sankey/sankey.sty	2021-01-27 22:04:47 UTC (rev 57535)
@@ -0,0 +1,722 @@
+% Copyright (C) 2016-2021 by Paul Gaborit
+%
+% This file may be distributed and/or modified
+%
+%   1. under the LaTeX Project Public License and/or
+%
+%   2. under the GNU Public License.
+
+\def\sankey at version{2.0}
+\def\sankey at date{2021/01/27}
+\ProvidesPackage{sankey}[\sankey at date\space\sankey at version\space sankey package]
+
+\RequirePackage{xparse}
+\RequirePackage{xfp}
+\RequirePackage{tikz}
+\usetikzlibrary{calc,decorations.markings,dubins}
+\usepackage{etoolbox}
+
+% add a new layer to debug sankey diagrams
+\pgfdeclarelayer{background}
+\pgfdeclarelayer{foreground}
+\pgfdeclarelayer{sankeydebug}
+\pgfsetlayers{background,main,foreground,sankeydebug}
+
+% flag to debug sankey diagrams
+\newtoggle{sankey debug}
+\newtoggle{sankey node start}
+\newtoggle{sankey node end}
+
+% macros to store and to retrieve the orientation and the quantity
+% associated with each sankey node
+
+\def\sankeysetnodeqty#1#2{\expandafter\xdef\csname sankey at node@#1 at qty\endcsname{#2}}
+
+\def\sankeygetnodeqty#1{%
+  \ifcsmacro{sankey at node@#1 at qty}{%
+    \csname sankey at node@#1 at qty\endcsname%
+  }{%
+    \PackageWarning{sankey}{Unknown sankey node '#1'}%
+  }%
+}
+
+\def\sankeysetnodeorient#1#2{\expandafter\xdef\csname sankey at node@#1 at orient\endcsname{#2}}
+
+\def\sankeygetnodeorient#1{%
+  \ifcsmacro{sankey at node@#1 at orient}{%
+    \csname sankey at node@#1 at orient\endcsname%
+  }{%
+    \PackageWarning{sankey}{Unknown sankey node '#1'}%
+  }%
+}
+
+\def\sankeysetstartfill#1#2{\expandafter\gdef\csname sankey at start@fill@#1\endcsname{#2}}
+\def\sankeysetstartdraw#1#2{\expandafter\gdef\csname sankey at start@draw@#1\endcsname{#2}}
+\def\sankeysetendfill#1#2{\expandafter\gdef\csname sankey at end@fill@#1\endcsname{#2}}
+\def\sankeysetenddraw#1#2{\expandafter\gdef\csname sankey at end@draw@#1\endcsname{#2}}
+%
+\def\sankeygetstartfill#1{\csname sankey at start@fill@#1\endcsname}
+\def\sankeygetstartdraw#1{\csname sankey at start@draw@#1\endcsname}
+\def\sankeygetendfill#1{\csname sankey at end@fill@#1\endcsname}
+\def\sankeygetenddraw#1{\csname sankey at end@draw@#1\endcsname}
+
+% new shape
+\pgfdeclareshape{sankey node}{
+  \inheritsavedanchors[from=rectangle]
+  \inheritanchor[from=rectangle]{center}
+  %\inheritanchorborder[from=rectangle]
+  \anchor{left}{\pgf at process{\northeast}}
+  \anchor{right}{\pgf at process{\southwest}}
+}
+
+% pgfkeys family 'sankey'
+\pgfkeys{/sankey/.is family}
+
+\NewDocumentCommand\sankeyset{m}{\pgfkeys{sankey,#1}}
+
+\sankeyset{
+  ratio length/.code={
+    \pgfmathsetmacro\sankeytotallen{#1}
+    \edef\sankeytotallen{\sankeytotallen pt}
+  },
+  ratio length/.value required,
+  ratio quantity/.code={\edef\sankeytotalqty{\fpeval{#1}}},
+  ratio quantity/.value required,
+  ratio/.style args={#1/#2}{
+    ratio length=#1,
+    ratio quantity=#2,
+  },
+  ratio/.value required,
+  minimum radius/.estore in=\sankeyminradius,
+  minimum radius/.value required,
+  outin steps/.estore in=\sankeystepoutin,
+  outon steps/.value required,
+  %
+  debug/.is choice,
+  debug/true/.code={\toggletrue{sankey debug}},
+  debug/false/.code={\togglefalse{sankey debug}},
+  debug/.default=true,
+  %
+  start style/.is choice,
+  %
+  end style/.is choice,
+  % default values
+  default parameters/.style={
+    % default values
+    ratio=1cm/10,
+    minimum radius=5mm,%
+    outin steps=10,
+    debug=false,
+    start style=none,
+    end style=none,
+  },
+  % to make node
+  node parameters/.style={
+    quantity/.code={%
+      %\typeout{quantity=##1}%
+      \edef\qty{\fpeval{##1}}%
+      %\typeout{qty=\qty}%
+    },
+    quantity/.value required,
+    angle/.code={%
+      %\typeout{angle:##1}%
+      \pgfmathsetmacro\orient{##1}%
+    },
+    angle/.value required,
+    name/.store in=\name,
+    name/.value required,
+    at/.store in=\pos,
+    at/.value required,
+    as/.style={
+      name=##1,
+      quantity=\sankeygetnodeqty{##1},
+      angle=\sankeygetnodeorient{##1},
+      at={##1.center},
+    },
+    as/.value required,
+    %
+    anchor/.is choice,
+    anchor/left/.code={\def\sankeyanchor{left}},
+    anchor/right/.code={\def\sankeyanchor{right}},
+    anchor/center/.code={\def\sankeyanchor{center}},
+    anchor=center,
+    %
+    start/.is choice,
+    start/true/.code={\toggletrue{sankey node start}},
+    start/false/.code={\togglefalse{sankey node start}},
+    start/.default=true,
+    start=false,
+    %
+    end/.is choice,
+    end/true/.code={\toggletrue{sankey node end}},
+    end/false/.code={\togglefalse{sankey node end}},
+    end/.default=true,
+    end=false,
+  },
+}
+
+% some styles
+\sankeyset{
+  node/.style={
+    shape=sankey node,
+    inner sep=0,minimum height={\sankeyqtytolen{#1}},
+    minimum width=0,draw=none,line width=0pt,
+    node contents={},
+  },
+  fill/.style={line width=0pt,fill=white},
+  draw/.style={draw=black,line width=.4pt},
+  % debug color used by all debug macros
+  debug color/.style={/utils/exec={\colorlet{debug color}{#1}}},
+  debug color=red!75!black,
+  % debug line between left and right anchors
+  debug line/.style={draw=debug color,|-|},
+  % debug line between center and label
+  debug normal/.style={draw=debug color},
+  % debug node label
+  debug label/.style={
+    draw,
+    font=\ttfamily\tiny,
+    text=debug color,text opacity=1,
+    inner sep=.1em,
+    fill=white,fill opacity=1,
+    rounded corners=.1em,
+  },
+}
+
+\sankeyset{
+  new start style/.code n args={3}{% name, fill path, draw path
+    \sankeysetstartfill{#1}{#2}
+    \sankeysetstartdraw{#1}{#3}
+    \sankeyset{start style/#1/.code={\def\sankeystartstyle{#1}}}
+  },
+  new end style/.code n args={3}{% name, fill path, draw path
+    \sankeysetendfill{#1}{#2}
+    \sankeysetenddraw{#1}{#3}
+    \sankeyset{end style/#1/.code={\def\sankeyendstyle{#1}}}
+  },
+}
+
+% the new 'sankeydiagram' environment
+\NewDocumentEnvironment{sankeydiagram}{O{}+b}{
+
+  \newcommand\sankeyarc[2]{% sn, en
+    \begingroup
+    \pgfmathsetmacro\startangle{\sankeygetnodeorient{##1}}
+    \pgfmathsetmacro\endangle{\sankeygetnodeorient{##2}}
+    \pgfmathsetmacro\rotateangle{\endangle-\startangle}
+    \pgfmathtruncatemacro\acwrotate{\rotateangle>0?1:0}
+    \path let
+    \p1=(##1.left),\p2=(##1.right),
+    \p3=(##2.left),\p4=(##2.right),
+    \n1={\sankeyqtytolen{\sankeygetnodeqty{##1}}},
+    \n{maxr}={\sankeyminradius+\n1},
+    \n{minr}={\sankeyminradius}
+    in \pgfextra{
+      \ifnumequal{\acwrotate}{1}{
+        \begin{pgfinterruptpath}
+          % fill the region
+          \path[/sankey/fill]
+          (\p1) arc(\startangle-90:\endangle-90:\n{minr}) -- (\p3) --
+          (\p4) arc(\endangle-90:\startangle-90:\n{maxr}) -- (\p2) -- cycle;
+          % draw left and right borders
+          \path[/sankey/draw]
+          (\p1) arc(\startangle-90:\endangle-90:\n{minr}) 
+          (\p4) arc(\endangle-90:\startangle-90:\n{maxr});
+        \end{pgfinterruptpath}
+      }{
+        \begin{pgfinterruptpath}
+          % fill the region
+          \path[/sankey/fill]
+          (\p1) arc(\startangle+90:\endangle+90:\n{maxr}) -- (\p3) --
+          (\p4) arc(\endangle+90:\startangle+90:\n{minr}) -- (\p2) -- cycle;
+          % draw left and right borders
+          \path[/sankey/draw]
+          (\p1) arc(\startangle+90:\endangle+90:\n{maxr}) 
+          (\p4) arc(\endangle+90:\startangle+90:\n{minr});
+        \end{pgfinterruptpath}
+      }
+    };
+    \endgroup
+  }
+
+  \newcommand\sankeymakenodenodebug{
+    \begingroup
+    \sankeysetnodeqty{\name}{\qty}
+    \sankeysetnodeorient{\name}{\orient}
+    % \typeout{\qty,\orient}
+    \ifundef{\sankeyanchor}{\def\sankeyanchor{center}}{}
+    \node[/sankey/node=\qty,rotate=\orient,at/.expanded={(\pos)},name=\name,anchor=\sankeyanchor];
+    \endgroup
+  }
+
+  \newcommand\sankeymakenode{
+    \begingroup
+    \sankeymakenodenodebug{}
+    \iftoggle{sankey debug}{
+      \begin{pgfonlayer}{sankeydebug}
+        \pgfset{
+          number format/relative*=-1,
+          number format/precision=1,
+          number format/fixed,
+        }
+        \path[/sankey/debug line] (\name.left) -- (\name.right);
+        \pgfmathsetmacro{\len}{\sankeyqtytolen{\qty}/3}
+        \path[/sankey/debug normal] (\name.center)
+        -- ($(\name.center)!\len pt!90:(\name.right)$)
+        node[/sankey/debug label,rotate=\orient+90,anchor=north] {\name:\pgfmathprintnumber{\qty}};
+      \end{pgfonlayer}
+    }{}
+    \endgroup
+  }
+  
+  \newcommand\sankeynodenodebug[1]{
+    \begingroup
+    \sankeyset{node parameters,##1}
+    %\typeout{sankeynodenodebug: '\name' at(\pos) angle(\orient) qty(\qty)}
+    \sankeymakenodenodebug{}
+    \endgroup
+  }
+
+  % ============================================================
+  % user commands
+  % ============================================================
+  
+  \NewDocumentCommand\sankeydubins{O{}mm}{% options, sn, en
+    \begingroup
+    \sankeyset{##1}
+    \pgfmathsetmacro\startangle{\sankeygetnodeorient{##2}}
+    \pgfmathsetmacro\endangle{\sankeygetnodeorient{##3}}
+    \edef\sqty{\sankeygetnodeqty{##2}}
+    \edef\eqty{\sankeygetnodeqty{##3}}
+    \ifdefstrequal{\sqty}{\eqty}{}{
+      \PackageError{sankey}%
+      {^^J*** \string\sankeyoutin: quantities differ between ##2 (\sqty) and ##3 (\eqty)^^J}%
+      {The quantities of the two Sankey nodes must be equal.}
+    }
+    \pgfmathsetmacro\qty{\sankeygetnodeqty{##2}}
+    \pgfmathsetmacro\width{\sankeyqtytolen{\qty}}
+    %\typeout{startangle:\startangle,endangle:\endangle,qty:\qty,width:\width}
+    \dubinspathset{
+      sankey/.style={
+        start point=##2.center,start angle=\startangle,
+        end point=##3.center,end angle=\endangle,
+        minimum radius=\sankeyminradius + .5 * \width pt,
+      },
+    }
+    \dubinspathcalc{sankey,store=sankey}
+    
+    \dubinspathset{
+      left border/.style={
+        sankey, use store=sankey,
+        left and right minimum radii=
+        {\sankeyminradius} and {\sankeyminradius + \width pt},
+      },
+      right border/.style={
+        sankey, use store=sankey,
+        left and right minimum radii=
+        {\sankeyminradius + \width pt} and {\sankeyminradius},
+      },
+    }
+    
+    \path let
+    \p1=(##2.left),\p2=(##2.right),
+    \p3=(##3.left),\p4=(##3.right)
+    in \pgfextra{
+      \begin{pgfinterruptpath}
+        % fill the region
+        \path[/sankey/fill]
+        (\p1)
+        \dubinspath{left border}
+        -- (\p3) --
+        (\p4) \dubinspath{right border,reverse}
+        -- (\p2) -- cycle;
+        
+        % draw left and right borders
+        \path[/sankey/draw]
+        (\p1)
+        \dubinspath{left border}
+        (\p2)
+        \dubinspath{right border}
+        ;
+      \end{pgfinterruptpath}
+    };
+    \endgroup
+  }
+  
+
+  \NewDocumentCommand\sankeyoutin{O{}mm}{% options, sn, en
+    \begingroup
+    \sankeyset{##1}
+    \edef\sn{##2}
+    \edef\en{##3}
+    \edef\sqty{\sankeygetnodeqty{\sn}}
+    \edef\eqty{\sankeygetnodeqty{\en}}
+    \ifdefstrequal{\sqty}{\eqty}{}{
+      \PackageError{sankey}%
+      {^^J*** \string\sankeyoutin: quantities differ between \sn (\sqty) and \en (\eqty)^^J}%
+      {The quantities of the two Sankey nodes must be equal.}
+    }
+    %\typeout{*** sankeyoutin: \sn\space to \en\space (\sankeystepoutin)}
+    \pgfmathsetmacro\qty{\sankeygetnodeqty{\sn}}
+    \pgfmathsetmacro\mylength{\sankeyqtytolen{\qty}/2}
+    \pgfmathsetmacro\mystep{1/\sankeystepoutin}
+    %\typeout{*** a}
+    \pgfmathsetmacro\mybound{1-.5*\mystep}
+    %\typeout{*** b}
+    \pgfmathsetmacro\laststep{int(\sankeystepoutin-1)}
+    %\typeout{sankeystepoutin(\sankeystepoutin) mystep(\mystep) mybound(\mybound) laststep(\laststep)}
+    %\typeout{*** sankeyoutin: \startangle to \endangle}
+    \path[decorate,overlay,decoration={
+      markings,
+      mark=between positions \mystep and \mybound step \mystep with {
+        \def\sankeyoutinmidptname{sankeyoutinmidpt \pgfkeysvalueof{/pgf/decoration/mark info/sequence number}}
+        \path
+        (0,0) coordinate(\sankeyoutinmidptname)
+        (0,-\mylength pt) coordinate (\sankeyoutinmidptname\space r)
+        (0,\mylength pt) coordinate (\sankeyoutinmidptname\space l)
+        ;
+      }
+    }](\sn.center) to[out=\sankeygetnodeorient{\sn},in=\sankeygetnodeorient{\en}+180] (\en.center);
+    \foreach \myptnum in {1,...,\laststep}{
+      \def\sankeyoutinmidptname{sankeyoutinmidpt \myptnum}
+      \anglebetween\sankeyoutinmidptangle{\sankeyoutinmidptname\space r}{\sankeyoutinmidptname\space l}
+      \sankeynodenodebug{quantity=\qty,angle=\sankeyoutinmidptangle-90,name=\sankeyoutinmidptname,at=\sankeyoutinmidptname}
+    }
+    \sankeynodenodebug{quantity=\sankeygetnodeqty{\sn},angle=\sankeygetnodeorient{\sn},name={sankeyoutinmidpt 0},at={\sn}}
+    \sankeynodenodebug{quantity={\sankeygetnodeqty{\en}},angle={\sankeygetnodeorient{\en}},name={sankeyoutinmidpt \sankeystepoutin},at={\en}}
+
+    %\typeout{*********************}
+    \path[/sankey/fill,looseness=1]
+    (sankeyoutinmidpt 0.left)
+    \foreach \curpt[remember=\curpt as \prevpt (initially 0)] in {1,...,\sankeystepoutin}{
+      to[out=\sankeygetnodeorient{sankeyoutinmidpt \prevpt},in=\sankeygetnodeorient{sankeyoutinmidpt \curpt}+180]
+      (sankeyoutinmidpt \curpt.left)
+    }
+    --
+    (sankeyoutinmidpt \sankeystepoutin.right)
+    \foreach \curpt[remember=\curpt as \prevpt (initially \sankeystepoutin)] in {\laststep,...,0}{
+      to[out=\sankeygetnodeorient{sankeyoutinmidpt \prevpt}+180,in=\sankeygetnodeorient{sankeyoutinmidpt \curpt}]
+      (sankeyoutinmidpt \curpt.right)
+    }
+    -- cycle;
+    
+    \path[/sankey/draw,looseness=1]
+    (sankeyoutinmidpt 0.left)
+    \foreach \curpt[remember=\curpt as \prevpt (initially 0)] in {1,...,\sankeystepoutin}{
+      to[out=\sankeygetnodeorient{sankeyoutinmidpt \prevpt},in=\sankeygetnodeorient{sankeyoutinmidpt \curpt}+180]
+      (sankeyoutinmidpt \curpt.left)
+    }
+    %
+    (sankeyoutinmidpt \sankeystepoutin.right)
+    \foreach \curpt[remember=\curpt as \prevpt (initially \sankeystepoutin)] in {\laststep,...,0}{
+      to[out=\sankeygetnodeorient{sankeyoutinmidpt \prevpt}+180,in=\sankeygetnodeorient{sankeyoutinmidpt \curpt}]
+      (sankeyoutinmidpt \curpt.right)
+    }
+    ;
+    
+    \endgroup
+  }
+  
+  \NewDocumentCommand\sankeynodealias{mm}{%name, alias
+    \path [late options={name=##1,alias=##2}];
+    \sankeysetnodeqty{##2}{\sankeygetnodeqty{##1}}
+    \sankeysetnodeorient{##2}{\sankeygetnodeorient{##1}}
+  }
+
+  \newcommand\sankeynode[2][]{
+    \begingroup
+    \sankeyset{##1}
+    \sankeyset{node parameters,##2}
+    %\typeout{sankeynode: '\name' at(\pos) angle(\orient) qty(\qty)}
+    \sankeymakenode{}
+    \endgroup
+  }
+
+  \def\sankeyfilldrawstart{
+    \begin{scope}[shift={(\name)},rotate=\orient]
+      \path[/sankey/fill] \sankeygetstartfill{\sankeystartstyle};
+      \path[/sankey/draw] \sankeygetstartdraw{\sankeystartstyle};
+    \end{scope}
+  }
+  
+  \NewDocumentCommand\sankeystart{O{}m}{
+    \begingroup
+    \sankeyset{##1}
+    \edef\name{##2}
+    \edef\orient{\sankeygetnodeorient{##2}}
+    \edef\qty{\sankeygetnodeqty{##2}}
+    \sankeyfilldrawstart
+    \endgroup
+  }
+
+  \NewDocumentCommand\sankeynodestart{O{}m}{
+    \begingroup
+    %\typeout{sankeynodestart: ##2}
+    \sankeyset{##1}
+    \sankeyset{node parameters,##2}
+    %\typeout{sankeynodestart: '\name' at(\pos) angle(\orient) qty(\qty)}
+    \sankeymakenode{}
+    %\typeout{sankeynodestart: sankeynode ok}
+    %\typeout{sankeynodestart: '\name' at(\pos) angle(\orient) qty(\qty)}
+    \sankeyfilldrawstart
+    \endgroup
+  }
+
+  \def\sankeyfilldrawend{
+    \begin{scope}[shift={(\name)},rotate=\sankeygetnodeorient{\name}]
+      \path[/sankey/fill] \sankeygetendfill{\sankeyendstyle};
+      \path[/sankey/draw] \sankeygetenddraw{\sankeyendstyle};
+    \end{scope}
+  }
+  
+  \NewDocumentCommand\sankeyend{O{}m}{%name
+    \begingroup
+    \sankeyset{##1}
+    \edef\name{##2}
+    \edef\orient{\sankeygetnodeorient{##2}}
+    \edef\qty{\sankeygetnodeqty{##2}}
+    \sankeyfilldrawend
+    \endgroup
+  }
+
+  \NewDocumentCommand\sankeynodeend{O{}m}{
+    \begingroup
+    %\typeout{sankeynodestart: ##2}
+    \sankeyset{##1}
+    \sankeyset{node parameters,##2}
+    %\typeout{sankeynodestart: '\name' at(\pos) angle(\orient) qty(\qty)}
+    \sankeymakenode{}
+    %\typeout{sankeynodestart: sankeynode ok}
+    %\typeout{sankeynodestart: '\name' at(\pos) angle(\orient) qty(\qty)}
+    \sankeyfilldrawend
+    \endgroup
+  }
+
+
+  
+  \NewDocumentCommand\sankeyadvance{sO{}mm}{% *(reverse), options, name, distance
+    \begingroup
+    \sankeyset{##2}
+    \def\newname{##3}
+    \def\oldname{##3-old}
+    \sankeynodealias{\newname}{\oldname}
+    % \typeout{*** sankeyadvance: ok (\oldname => \newname)}
+    \IfBooleanTF{##1}{
+      % reverse advance
+      \sankeynode{
+        at={$(\oldname.center)!##4!90:(\oldname.left)$},
+        angle=\sankeygetnodeorient{\oldname},
+        quantity=\sankeygetnodeqty{\oldname},
+        name=\newname,
+      }
+      \path[/sankey/fill]
+      (\newname.left) -- (\oldname.left)
+      --
+      (\oldname.right) -- (\newname.right)
+      -- cycle;
+      \path[/sankey/draw]
+      (\newname.left) -- (\oldname.left)
+      (\oldname.right) -- (\newname.right);
+      \endgroup
+    }{
+      % advance
+      \sankeynode{
+        at={$(\oldname.center)!##4!-90:(\oldname.left)$},
+        angle=\sankeygetnodeorient{\oldname},
+        quantity=\sankeygetnodeqty{\oldname},
+        name=\newname,
+      }
+      \path[/sankey/fill]
+      (\oldname.left) -- (\newname.left)
+      --
+      (\newname.right) -- (\oldname.right)
+      -- cycle;
+      \path[/sankey/draw]
+      (\oldname.left) -- (\newname.left)
+      (\newname.right) -- (\oldname.right);
+      \endgroup
+    }
+  }
+  
+  \NewDocumentCommand\sankeyturn{sO{}mm}{% *(reverse), options, name, angle
+    \begingroup
+    \sankeyset{##2}
+    \def\name{##3}
+    \def\oldname{##3-old}
+    \sankeynodealias{\name}{\oldname}
+    \pgfmathsetmacro\qty{\sankeygetnodeqty{\oldname}}
+    \pgfmathsetmacro\oldangle{\sankeygetnodeorient{\oldname}}
+    \IfBooleanTF{##1}{
+      % turn in reverse
+      \pgfmathsetmacro\orient{\oldangle-##4}
+      % \typeout{TURN: \oldangle=>\orient}
+      \ifnumgreater{##4}{0}{% anti-clockwise turn
+        \path let
+        \p1=(##3.left), \p2=(##3.right),
+        % center of rotation
+        \p{c}=($(\p1)!-\sankeyminradius!(\p2)$),
+        % starting position
+        \p{s}=(##3.center),
+        % ending position
+        \p{e}=($(\p{c})!1!-##4:(\p{s})$)
+        in \pgfextra{
+          \begin{pgfinterruptpath}
+            % \typeout{acw turn:\qty:\orient}
+            \def\pos{\p{e}}
+            \sankeymakenode{}
+            \sankeyarc{\name}{\oldname}
+          \end{pgfinterruptpath}
+        };
+      }{ % clockwise turn
+        \path let
+        \p1=(##3.right), \p2=(##3.left),
+        % center of rotation
+        \p{c}=($(\p1)!-\sankeyminradius!(\p2)$),
+        % starting position
+        \p{s}=(##3.center),
+        % ending position
+        \p{e}=($(\p{c})!1!-##4:(\p{s})$)
+        in \pgfextra{
+          % \typeout{cw turn:\qty:\orient}
+          \begin{pgfinterruptpath}
+            \def\pos{\p{e}}
+            \sankeymakenode{}
+            \sankeyarc{\name}{\oldname}
+          \end{pgfinterruptpath}
+        };
+      }
+    }{
+      % turn
+      \pgfmathsetmacro\orient{\oldangle+##4}
+      % \typeout{TURN: \oldangle=>\orient}
+      \ifnumgreater{##4}{0}{% anti-clockwise turn
+        \path let
+        \p1=(##3.left), \p2=(##3.right),
+        % center of rotation
+        \p{c}=($(\p1)!-\sankeyminradius!(\p2)$),
+        % starting position
+        \p{s}=(##3.center),
+        % ending position
+        \p{e}=($(\p{c})!1!##4:(\p{s})$)
+        in \pgfextra{
+          \begin{pgfinterruptpath}
+            % \typeout{acw turn:\qty:\orient}
+            \def\pos{\p{e}}
+            \sankeymakenode{}
+            \sankeyarc{\oldname}{\name}
+          \end{pgfinterruptpath}
+        };
+      }{ % clockwise turn
+        \path let
+        \p1=(##3.right), \p2=(##3.left),
+        % center of rotation
+        \p{c}=($(\p1)!-\sankeyminradius!(\p2)$),
+        % starting position
+        \p{s}=(##3.center),
+        % ending position
+        \p{e}=($(\p{c})!1!##4:(\p{s})$)
+        in \pgfextra{
+          % \typeout{cw turn:\qty:\orient}
+          \begin{pgfinterruptpath}
+            \def\pos{\p{e}}
+            \sankeymakenode{}
+            \sankeyarc{\oldname}{\name}
+          \end{pgfinterruptpath}
+        };
+      }
+    }
+    \endgroup
+  }
+
+  \NewDocumentCommand\sankeyfork{mm}{%name,list of forks
+    \def\listofforks{##2}
+    \xdef\sankeytot{0}
+    \xdef\sankeycalculus{0}
+    \pgfmathsetmacro\iqty{\sankeygetnodeqty{##1}}
+    \pgfmathsetmacro\iorient{\sankeygetnodeorient{##1}}
+    \pgfmathsetmacro\orient{\iorient}
+    %\typeout{iname:##1, iqty:\iqty,iorient:\iorient}
+    \foreach \qty/\name[count=\c] in \listofforks {
+      %\typeout{sankeyfork foreach: qty(\qty) name(\name) count(\c)}
+      \path
+      let
+      \p1=(##1.left),\p2=(##1.right),
+      \p{start}=($(\p1)!\fpeval{\sankeytot/\iqty}!(\p2)$),
+      \n{nexttot}={\fpeval{\sankeytot+\qty}},
+      \p{end}=($(\p1)!\fpeval{\n{nexttot}/\iqty}!(\p2)$),
+      \p{mid}=($(\p{start})!.5!(\p{end})$)
+      in \pgfextra{
+        %\typeout{new fork:\name}
+        %\typeout{qty:\qty,name:\name,count:\c,pos=\p{mid}}
+        \xdef\sankeytot{\n{nexttot}}
+        \xdef\sankeycalculus{\fpeval{\sankeycalculus+\qty}}
+        \begin{pgfinterruptpath}
+          \def\pos{\p{mid}}
+          \sankeymakenode{}
+        \end{pgfinterruptpath}
+      };
+    }
+    \edef\diff{\fpeval{abs(\iqty-\sankeytot)}}
+    %\typeout{sankeyfork diff: \diff}
+    %\pgfmathsetmacro{\diff}{abs(\iqty-\sankeytot)}
+    %\pgfmathtruncatemacro{\finish}{\diff<0.01?1:0}
+    \ifnumequal{\diff}{0}{}{
+      \PackageWarning{sankey}{^^J*** Warning: bad sankey fork: \iqty\space!=\space\sankeycalculus(=\sankeytot)^^J##2}
+    }
+  }
+  
+  \def\sankeyqtytolen##1{\fpeval{(##1)/\sankeytotalqty*\sankeytotallen}}
+  
+  \sankeyset{
+    % % default values,
+    % /tikz/declare function={
+    %   % sankeyqtytolen(\qty)=\qty/\sankeytotalqty*\sankeytotallen;
+    %   % sankeylentoqty(\len)=\len/\sankeytotallen*\sankeytotalqty;
+    % },%
+    default parameters,%
+    % user values
+    #1}
+
+  %\typeout{sankeytotallen: \sankeytotallen}
+  
+  #2 % body of sankeydiagram environment 
+}
+
+
+\sankeyset{
+  % none style
+  new start style={none}{}{},
+  new end style={none}{}{},
+  % simple style
+  new start style={simple}{
+    (\name.left) -- ([xshift=-.5\pgflinewidth]\name.left) -- ([xshift=-.5\pgflinewidth]\name.right) -- (\name.right) -- cycle
+  }{
+    (\name.left) -- ([xshift=-.5\pgflinewidth]\name.left) -- ([xshift=-.5\pgflinewidth]\name.right) -- (\name.right)
+  },
+  new end style={simple}{
+    (\name.left) -- ([xshift=2mm]\name.center) -- (\name.right) -- cycle
+  }{
+    (\name.left) -- ([xshift=2mm]\name.center) -- (\name.right)
+  },
+  % arrow style
+  new start style={arrow}{
+    (\name.left) -- ++(-10pt,0)
+    -- ([xshift=-10pt/6]\name.center)
+    -- ([xshift=-10pt]\name.right)
+    -- (\name.right) -- cycle
+  }{
+    (\name.left) -- ++(-10pt,0)
+    -- ([xshift=-10pt/6]\name.center)
+    -- ([xshift=-10pt]\name.right)
+    -- (\name.right)
+  },
+  new end style={arrow}{
+    (\name.left) -- ([yshift=1mm]\name.left)
+    -- ([xshift=10pt]\name.center)
+    -- ([yshift=-1mm]\name.right) -- (\name.right) -- cycle
+  }{
+    (\name.left) -- ([yshift=1mm]\name.left)
+    -- ([xshift=10pt]\name.center)
+    -- ([yshift=-1mm]\name.right) -- (\name.right)
+  },
+}
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/tex/latex/sankey/sankey.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex	2021-01-27 22:04:47 UTC (rev 57535)
@@ -0,0 +1,361 @@
+% Copyright (C) 2016-2021 by Paul Gaborit
+%
+% This file may be distributed and/or modified
+%
+%   1. under the LaTeX Project Public License and/or
+%
+%   2. under the GNU Public License.
+
+\usetikzlibrary{calc}
+
+\RequirePackage{etoolbox}
+\RequirePackage{etextools}
+\RequirePackage{xfp}
+
+\newbool{dubinspathreverse}
+
+\def\ifpgfmathcond#1{%
+  \pgfmathparse{(#1)?1:0}%
+  \ifnumequal{\pgfmathresult}{1}%
+}
+
+\def\anglebetween#1#2#3{%macro, s, t
+  \path let
+  \p{s}=(#2), \p{t}=(#3),
+  \n{angle}={atan2(\y{t}-\y{s},\x{t}-\x{s})}
+  in \pgfextra {
+    \pgfmathsetmacro#1{\n{angle}}
+    \aftergroup at def#1
+  };
+}
+
+\def\distancebetween#1#2#3{%macro, s, t
+  \path let
+  \p{s}=(#2), \p{t}=(#3),
+  %\n{dist}={veclen(\x{t}-\x{s},\y{t}-\y{s}))}
+  \n{dist}={\fpeval{sqrt((\x{t}-\x{s})*(\x{t}-\x{s})+(\y{t}-\y{s})*(\y{t}-\y{s}))}}
+  in \pgfextra {
+    %\typeout{n{dist}:\n{dist}}
+    \pgfmathsetmacro#1{\n{dist}}
+    \aftergroup at def#1
+  };
+}
+
+\newcommand\dubinspath at rsr{% s, sa, t, ta, as, len, at, r
+  let
+  \p{tr}=([shift={(\dbp at angb-90:\dbp at radius pt)}]\dbp at b),
+  \n1={\dbp at anga+90},
+  \n2={\dbp at angb+90},
+  \n3={\n2+\dbp at lastangle}
+  in
+  arc(\n1:\n1-\dbp at firstangle:\dbp at rradius pt)
+  -- ([shift={(\p{tr})}]\n3:\dbp at rradius pt)
+  arc(\n3:\n2:\dbp at rradius pt)
+}
+
+\newcommand\dubinspath at lsl{% s, sa, t, ta, as, len, at, r
+  let
+  \p{tl}=([shift={(\dbp at angb+90:\dbp at radius pt)}]\dbp at b),
+  \n1={\dbp at anga-90},\n2={\n1+\dbp at firstangle},
+  \n3={\dbp at angb-90},\n4={\n3-\dbp at lastangle}
+  in
+  arc(\n1:\n2:\dbp at lradius pt)
+  -- ([shift={(\p{tl})}]\n4:\dbp at lradius pt)
+  arc(\n4:\n3:\dbp at lradius pt)
+}
+
+\newcommand\dubinspath at rsl{% s, sa, t, ta, as, len, at, r
+  let
+  \p{tl}=([shift={(\dbp at angb+90:\dbp at radius pt)}]\dbp at b),
+  \n1={\dbp at anga+90},\n2={\n1-\dbp at firstangle},
+  \n3={\dbp at angb-90},\n4={\n3-\dbp at lastangle}
+  in
+  arc(\n1:\n2:\dbp at rradius pt)
+  -- ([shift={(\p{tl})}]\n4:\dbp at lradius pt)
+  arc(\n4:\n3:\dbp at lradius pt)
+}
+
+\newcommand\dubinspath at lsr{% s, sa, t, ta, as, len, at, r
+  let
+  \p{tr}=([shift={(\dbp at angb-90:\dbp at radius pt)}]\dbp at b),
+  \n1={\dbp at anga-90},\n2={\n1+\dbp at firstangle},
+  \n3={\dbp at angb+90},\n4={\n3+\dbp at lastangle}
+  in
+  arc(\n1:\n2:\dbp at lradius pt)
+  -- ([shift={(\p{tr})}]\n4:\dbp at rradius pt)
+  arc(\n4:\n3:\dbp at rradius pt)
+}
+
+\newcommand\dubinspath at lrl{% s, sa, t, ta, as, ai, at, r
+  let
+  \n1={\dbp at anga-90},\n2={\n1+\dbp at firstangle},
+  \n3={\dbp at angb-90},\n4={\n3-\dbp at lastangle}
+  in
+  arc(\n1:\n2:\dbp at lradius pt)
+  arc(\n2+180:\n2+180-\dbp at midparam:\dbp at rradius pt)
+  arc(\n4:\n3:\dbp at lradius pt)
+}
+
+\newcommand\dubinspath at rlr{% s, sa, t, ta, as, ai, at, r
+  let
+  \n1={\dbp at anga+90},\n2={\n1-\dbp at firstangle},
+  \n3={\dbp at angb+90},\n4={\n3+\dbp at lastangle}
+  in
+  arc(\n1:\n2:\dbp at rradius pt)
+  arc(\n2+180:\n2+180+\dbp at midparam:\dbp at lradius pt)
+  arc(\n4:\n3:\dbp at rradius pt)
+}
+\newcommand\dubinspath at rev@lsl{\dubinspath at rsr}
+\newcommand\dubinspath at rev@rsr{\dubinspath at lsl}
+\newcommand\dubinspath at rev@lsr{\dubinspath at lsr}
+\newcommand\dubinspath at rev@rsl{\dubinspath at rsl}
+\newcommand\dubinspath at rev@lrl{\dubinspath at rlr}
+\newcommand\dubinspath at rev@rlr{\dubinspath at lrl}
+
+
+\newcommand\dubinspath[1]{%
+  \pgfextra{
+    \dubinspathset{#1}
+    \ifbool{dubinspathreverse}{
+      \edef\newa{\dbp at b}
+      \edef\newb{\dbp at a}
+      \pgfmathsetmacro\newanga{180+\dbp at angb}
+      \pgfmathsetmacro\newangb{180+\dbp at anga}
+      \edef\newfirstangle{\dbp at lastangle}
+      \edef\newlastangle{\dbp at firstangle}
+      \edef\newmethod{rev@\dbp at method}
+      \edef\newlradius{\dbp at rradius}
+      \edef\newrradius{\dbp at lradius}
+      \dubinspathset{
+        start point=\newa,
+        end point=\newb,
+        start angle=\newanga,
+        end angle=\newangb,
+        first angle=\newfirstangle,
+        last angle=\newlastangle,
+        left and right minimum radii=\newlradius pt and \newrradius pt,
+        method=\newmethod,
+      }
+    }{}
+    %\typeout{dbp at lradius:\dbp at lradius}
+    %\typeout{dbp at rradius:\dbp at rradius}
+  }
+  \csname dubinspath@\dbp at method\endcsname%
+}
+
+
+% solution
+% \xdef\dubinspathmethod{}     % type of dubins path
+% \xdef\dubinspathlength{}     % lenght (pt)
+% \xdef\dubinspathfirstangle{} % first angle
+% \xdef\dubinspathmiddleparam{} % intermediate angle or straight distance
+% \xdef\dubinspathlastangle{}  % last angle
+
+\def\dubinspathstore#1#2{%
+  \expandafter\xdef\csname dubinspath at store@#1@#2\endcsname%
+  {\csname dubinspath#2\endcsname}%
+}
+\def\dubinspathget#1#2{%
+  \csname dubinspath at store@#1@#2\endcsname%
+}
+
+%
+\def\dubinspathsetparams#1#2#3#4#5{% method, length, fisrt angle, middle param, last angle
+  \edef\dubinspathmethod{#1}
+  \edef\dubinspathlength{#2}
+  \edef\dubinspathfirstangle{#3}
+  \edef\dubinspathmiddleparam{#4}
+  \edef\dubinspathlastangle{#5}
+  \ifdef{\dbp at storename}{
+    \foreach \p in {method,length,firstangle,middleparam,lastangle}{
+      \dubinspathstore{\dbp at storename}{\p}
+    }
+  }{}
+}
+
+\def\dubinspathupdateparams#1#2#3#4#5{
+  \ifpgfmathcond{#2<\dubinspathlength}{
+    \dubinspathsetparams{#1}{#2}{#3}{#4}{#5}
+  }{}
+}
+
+\tikzset{
+  dubins path/.is family,
+  dubins path,
+  start point/.store in=\dbp at a,
+  start angle/.store in=\dbp at anga,
+  end point/.store in=\dbp at b,
+  end angle/.store in=\dbp at angb,
+  store/.store in=\dbp at storename,
+  use store/.style={
+    method=\dubinspathget{#1}{method},
+    first angle=\dubinspathget{#1}{firstangle},
+    last angle=\dubinspathget{#1}{lastangle},
+    middle param=\dubinspathget{#1}{middleparam},
+  },
+  minimum radius/.code={
+    \pgfmathsetmacro\dbp at radius{#1}
+    \pgfmathsetmacro\dbp at rradius{#1}
+    \pgfmathsetmacro\dbp at lradius{#1}
+  },
+  left and right minimum radii/.code args={#1 and #2}{
+    \pgfmathsetmacro\dbp at lradius{#1}
+    \pgfmathsetmacro\dbp at rradius{#2}
+    \pgfmathsetmacro\dbp at radius{(\dbp at lradius + \dbp at rradius)/2}
+  },
+  method/.store in=\dbp at method,
+  first angle/.store in=\dbp at firstangle,
+  last angle/.store in=\dbp at lastangle,
+  middle param/.store in=\dbp at midparam,
+  reverse/.is if=dubinspathreverse,
+}
+
+\newcommand\dubinspathset[1]{\tikzset{dubins path,#1}}
+
+\newcommand\dubinspathcalc[1]{%
+  \begingroup
+  \dubinspathset{#1}
+  \tikzset{
+    declare function={
+      angtodist(\a,\r)={abs(\a)*.01745329*\r};
+      modangr(\a,\b)={
+        (Mod(\a,360)<Mod(\b,360)?Mod(\a,360):Mod(\a,360)-360)+\b-Mod(\b,360)
+      };
+      modangl(\a,\b)={
+        (Mod(\a,360)<Mod(\b,360)?Mod(\a,360)+360:Mod(\a,360))+(\b)-Mod(\b,360)
+      };
+    },
+  }
+  
+  \pgfmathsetmacro\radius{\dbp at rradius}
+  \pgfmathsetmacro\anga{mod((\dbp at anga)+180,360)-180}
+  \pgfmathsetmacro\angb{mod((\dbp at angb)+180,360)-180}
+  %\typeout{radius:\radius,anga:\anga,angb:\angb}
+  \path
+  let
+  \p{a}=(\dbp at a),
+  \p{b}=(\dbp at b),
+  \p{ar}=($(\p{a}) + (\anga-90:\radius pt)$),
+  \p{al}=($(\p{a}) + (\anga+90:\radius pt)$),
+  \p{br}=($(\p{b}) + (\angb-90:\radius pt)$),
+  \p{bl}=($(\p{b}) + (\angb+90:\radius pt)$)
+  in \pgfextra{
+    \pgfinterruptpath
+
+    % RSR (ar et br)
+    %\typeout{RSR begin}
+    \anglebetween\rsrarbr{\p{ar}}{\p{br}}
+    \distancebetween\rsrdarbr{\p{ar}}{\p{br}}
+    \pgfmathsetmacro\rsrangone{Mod(\anga-\rsrarbr,360)}
+    \pgfmathsetmacro\rsrangtwo{Mod(\rsrarbr-\angb,360)}
+    \pgfmathsetmacro\rsrlen{\rsrdarbr}
+    \pgfmathsetmacro\rsrdist{
+      angtodist(\rsrangone,\radius)
+      +\rsrlen
+      +angtodist(\rsrangtwo,\radius)
+    }
+    \dubinspathsetparams{rsr}{\rsrdist}{\rsrangone}{\rsrlen}{\rsrangtwo}
+    
+    % LSL (al et bl)
+    %\typeout{LSL begin}
+    \anglebetween\lslalbl{\p{al}}{\p{bl}}
+    \distancebetween\lsldalbl{\p{al}}{\p{bl}}
+    \pgfmathsetmacro{\lslangone}{mod(\lslalbl-\anga+720,360)}
+    \pgfmathsetmacro{\lslangtwo}{mod(\angb-\lslalbl+720,360)}
+    \pgfmathsetmacro\lsllen{\lsldalbl}
+    \pgfmathsetmacro\lsldist{
+      angtodist(\lslangone,\radius)
+      +\lsllen
+      +angtodist(\lslangtwo,\radius)
+    }
+    \dubinspathupdateparams{lsl}{\lsldist}{\lslangone}{\lsllen}{\lslangtwo}
+    
+    % RSL (ar et bl)
+    %\typeout{RSL begin}
+    \distancebetween\rsldarbl{\p{ar}}{\p{bl}}
+    \pgfmathtruncatemacro\rslok{(\rsldarbl>=2*\radius)?1:0}
+    \ifnumequal{\rslok}{1}{
+      \anglebetween\rslarbl{\p{ar}}{\p{bl}}
+      \pgfmathsetmacro\rslanglesup{
+        asin(\radius/\rsldarbl*2)}
+      \pgfmathsetmacro\rslangone{Mod(\anga-\rslarbl+\rslanglesup,360)}
+      \pgfmathsetmacro\rslangtwo{Mod(\angb-\rslarbl+\rslanglesup,360)}
+      \pgfmathsetmacro\rsllen{veclen(\rsldarbl,\radius)}
+      \pgfmathsetmacro\rsldist{
+        angtodist(\rslangone,\radius)
+        +\rsllen
+        +angtodist(\rslangtwo,\radius)
+      }
+
+      \dubinspathupdateparams{rsl}{\rsldist}{\rslangone}{\rsllen}{\rslangtwo}
+    }{}
+
+    % LSR (al et br)
+    %\typeout{LSR begin}
+    \distancebetween\lsrdalbr{\p{al}}{\p{br}}
+    \pgfmathtruncatemacro\lsrok{(\lsrdalbr>=2*\radius)?1:0}
+    \ifnumequal{\lsrok}{1}{
+      \anglebetween\lsralbr{\p{al}}{\p{br}}
+      \pgfmathsetmacro\lsranglesup{
+        asin(\radius/\lsrdalbr*2)}
+      \pgfmathsetmacro\lsrangone{Mod(\lsralbr+\lsranglesup-\anga,360)}
+      \pgfmathsetmacro\lsrangtwo{Mod(\lsralbr+\lsranglesup-\angb,360)}
+      \pgfmathsetmacro\lsrlen{veclen(\lsrdalbr,\radius)}
+      \pgfmathsetmacro\lsrdist{
+        angtodist(\lsrangone,\radius)
+        +\lsrlen
+        +angtodist(\lsrangtwo,\radius)
+      }
+      \dubinspathupdateparams{lsr}{\lsrdist}{\lsrangone}{\lsrlen}{\lsrangtwo}
+    }{}
+    
+    % LRL (al et bl)
+    %\typeout{LRL begin}
+    \distancebetween\lrldalbl{\p{al}}{\p{bl}}
+    \pgfmathtruncatemacro\lrlok{(\lrldalbl<=4*\radius)?1:0}
+    \ifnumequal{\lrlok}{1}{
+      % \debug{LRL}
+      \anglebetween\lrlalbl{\p{al}}{\p{bl}}
+      \pgfmathsetmacro\lrlangsup{acos(\lrldalbl/\radius/4)}
+      \pgfmathsetmacro\lrlangone{
+        modangl(\lrlalbl+\lrlangsup,\anga-90)-(\anga-90)}
+      \pgfmathsetmacro\lrlangtwo{%
+        (\angb-90)-modangr(\lrlalbl+180-\lrlangsup,\angb-90)}
+      \pgfmathsetmacro\lrlangthree{360-2*(90-\lrlangsup)}
+      \pgfmathsetmacro\lrldist{
+        angtodist(\lrlangone,\radius)
+        +angtodist(\lrlangthree,\radius)
+        +angtodist(\lrlangtwo,\radius)
+      }
+      \dubinspathupdateparams{lrl}{\lrldist}{\lrlangone}{\lrlangthree}{\lrlangtwo}
+    }{}
+
+    % RLR (ar et br)
+    %\typeout{RLR begin}
+    \distancebetween\rlrdarbr{\p{ar}}{\p{br}}
+    \pgfmathtruncatemacro\rlrok{(\rlrdarbr<=4*\radius)?1:0}
+    \ifnumequal{\rlrok}{1}{
+      \anglebetween\rlrarbr{\p{ar}}{\p{br}}
+      \pgfmathsetmacro\rlrangsup{acos(\rlrdarbr/\radius/4)}
+      \pgfmathsetmacro\rlrangone{
+        (\anga+90)-modangr(\rlrarbr-\rlrangsup,\anga+90)}
+      \pgfmathsetmacro\rlrangtwo{%
+        modangl(\rlrarbr+180+\rlrangsup,\angb+90)-(\angb+90)}
+      \pgfmathsetmacro\rlrangthree{360-2*(90-\rlrangsup)}
+      \pgfmathsetmacro\rlrdist{
+        angtodist(\rlrangone,\radius)
+        +angtodist(\rlrangthree,\radius)
+        +angtodist(\rlrangtwo,\radius)
+      }
+      \dubinspathupdateparams{rlr}{\rlrdist}{\rlrangone}{\rlrangthree}{\rlrangtwo}
+    }{}
+
+    \endpgfinterruptpath
+  };
+  \endgroup
+}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: t
+%%% End: 


Property changes on: trunk/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/tlpkg/bin/tlpkg-ctan-check
===================================================================
--- trunk/Master/tlpkg/bin/tlpkg-ctan-check	2021-01-27 00:54:19 UTC (rev 57534)
+++ trunk/Master/tlpkg/bin/tlpkg-ctan-check	2021-01-27 22:04:47 UTC (rev 57535)
@@ -658,7 +658,7 @@
     rterface rtkinenc rtklage
     rubik ruhyphen ruler rulerbox rulercompass runcode russ rutitlepage
     rviewport rvwrite ryersonsgsthesis ryethesis
-  sa-tikz sageep sanitize-umlaut
+  sa-tikz sageep sanitize-umlaut sankey
     sanskrit sanskrit-t1 sansmath sansmathaccent sansmathfonts
     sapthesis sasnrdisplay sauerj
     sauter sauterfonts savefnmark savesym savetrees

Modified: trunk/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc
===================================================================
--- trunk/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc	2021-01-27 00:54:19 UTC (rev 57534)
+++ trunk/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc	2021-01-27 22:04:47 UTC (rev 57535)
@@ -170,6 +170,7 @@
 depend revquantum
 depend ribbonproofs
 depend rmathbr
+depend sankey
 depend sasnrdisplay
 depend sciposter
 depend sclang-prettifier

Added: trunk/Master/tlpkg/tlpsrc/sankey.tlpsrc
===================================================================


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