diff options
author | Karl Berry <karl@freefriends.org> | 2021-03-14 23:19:59 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-03-14 23:19:59 +0000 |
commit | ceca438fddde2040f41fc0723fc066a8345f5e2b (patch) | |
tree | 67b1de096b693347b60a6308446e3b2e02ff6c1e /Master/texmf-dist | |
parent | ce7d08a8d4a8e445cae634dce76820b4a81485d6 (diff) |
sankey (14mar21) (branch)
git-svn-id: svn://tug.org/texlive/branches/branch2020.0@58363 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist')
15 files changed, 6789 insertions, 2357 deletions
diff --git a/Master/texmf-dist/doc/latex/sankey/README b/Master/texmf-dist/doc/latex/sankey/README index ae6f9721be8..aa0a7f627ac 100644 --- a/Master/texmf-dist/doc/latex/sankey/README +++ b/Master/texmf-dist/doc/latex/sankey/README @@ -1,8 +1,11 @@ sankey ====== -LaTeX package to build Sankey diagram. +sankey – Draw Sankey diagrams with TikZ +This package provides macros and environment to build Sankey diagrams, +i.e. flow diagrams in which the width of the arrows is proportional to +the flow rate. license ======= @@ -11,6 +14,8 @@ Copyright (C) 2016-2021 by Paul Gaborit This file may be distributed and/or modified - 1. under the LaTeX Project Public License and/or + 1. under the LaTeX Project Public License v1.3 + + and/or 2. under the GNU Public License. diff --git a/Master/texmf-dist/doc/latex/sankey/sankey-doc.pdf b/Master/texmf-dist/doc/latex/sankey/sankey-doc.pdf Binary files differdeleted file mode 100644 index f8d77bd13b4..00000000000 --- a/Master/texmf-dist/doc/latex/sankey/sankey-doc.pdf +++ /dev/null diff --git a/Master/texmf-dist/doc/latex/sankey/sankey-doc.tex b/Master/texmf-dist/doc/latex/sankey/sankey-doc.tex deleted file mode 100644 index 768e2d0be10..00000000000 --- a/Master/texmf-dist/doc/latex/sankey/sankey-doc.tex +++ /dev/null @@ -1,1599 +0,0 @@ -% -*- coding: utf-8; -*- - -% Copyright (C) 2016-2021 by Paul Gaborit -% -% This file may be distributed and/or modified -% -% 1. under the LaTeX Project Public License and/or -% -% 2. under the GNU Public License. - -\documentclass[a4paper,onecolumn,10pt]{article} -%\usepackage[rgb]{xcolor} -\usepackage[paper=a4paper,vmargin=1.5cm,hmargin=4cm]{geometry} -\usepackage[utf8]{inputenc} -\usepackage[T1]{fontenc} -\usepackage{xcolor} -\usepackage[colorlinks]{hyperref} -\usepackage{fancyvrb} -\usepackage{listings} -\usepackage{enumitem} -\usepackage{pgfilecontents} -\usepackage{microtype} -\usepackage{bookmark} -\usepackage{cmap} -\usepackage{sankey} -\usepackage{siunitx} -\usepackage{mdframed} -\usepackage{footnote} -\usepackage{accsupp} -\usetikzlibrary{positioning,patterns.meta} -\usepackage[british]{babel} - -\colorlet{fondcode}{gray!5!white} -\colorlet{keyword}{blue!50!cyan!50!black} -\colorlet{comment}{red!75!black} - -\newcommand\emptyaccsupp[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}} - -\lstset{ - literate= - {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ú}{{\'u}}1 - {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1 - {à}{{\`a}}1 {è}{{\`e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1 - {À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1 - {ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1 - {Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1 - {â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1 - {Â}{{\^A}}1 {Ê}{{\^E}}1 {Î}{{\^I}}1 {Ô}{{\^O}}1 {Û}{{\^U}}1 - {œ}{{\oe}}1 {Œ}{{\OE}}1 {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1 - {ç}{{\c c}}1 {Ç}{{\c C}}1 {ø}{{\o}}1 {å}{{\r a}}1 {Å}{{\r A}}1 - {€}{{\texteuro}}1 {£}{{\pounds}}1 {°}{{\degres}}1 - {’}{{\textquoteright}}1 {‘}{{\textquoteleft}}1 - {«}{{<<}}1 {»}{{>>}}1 - {—}{{---}}1 {−}{{$-$}}1 -} - -\lstset{ - fancyvrb=true, - %fvcmdparams=samepage, - escapechar=`, % pour introduire du latex dans un environnement verbatim - extendedchars=true, - fontadjust=true, - columns=fullflexible, % pour pouvoir copier/coller les chaines de caractères - flexiblecolumns=true, - % frame=leftline, - inputencoding=utf8, - keepspaces=true, % keeps spaces in text, code indentation - backgroundcolor=\color{fondcode}, - basicstyle=\mdseries\ttfamily, - keywordstyle=\color{keyword}\bfseries,% - stringstyle=\ttfamily\color{green!50!black},% - commentstyle=\color{comment}\itshape,% - emphstyle=\bfseries\color{red}, - numbersep=5pt, - %numbers=left, - numberstyle=\tiny\emptyaccsupp, - showstringspaces=false, - upquote=true, % pour pouvoir copier/coller le code avec des quotes - aboveskip=\parskip, - belowskip=\parskip, - framexleftmargin=1pt, - framexrightmargin=1pt, -} - -\lstdefinestyle{textsmall}{basicstyle=\color{black}\small\mdseries\ttfamily} -\lstdefinestyle{textfootnotesize}{basicstyle=\color{black}\footnotesize\mdseries\ttfamily} -\lstdefinestyle{textscriptsize}{basicstyle=\color{black}\scriptsize\mdseries\ttfamily} -\lstdefinestyle{texttiny}{basicstyle=\color{black}\tiny\mdseries\ttfamily} - -\lstdefinestyle{LaTeX}{ - language=[LaTeX]TeX, - %backgroundcolor=\color{latexbg}, - moretexcs={ - coordinate, - definecolor, - draw, - fill, - foreach, - hashband, - node, - sankeyadvance, - sankeydubins, - sankeyend, - sankeyend, - sankeyfork, - sankeynode, - sankeynodealias, - sankeynodeend, - sankeynodestart, - sankeyoutin, - sankeyset, - sankeystart, - sankeyturn, - sisetup, - tikzset, - turnandstop, - usepackage, - } -} -\lstdefinestyle{LaTeXsmall}{style=LaTeX,style=textsmall} -\lstdefinestyle{LaTeXfootnotesize}{style=LaTeX,style=textfootnotesize} -\lstdefinestyle{LaTeXscriptsize}{style=LaTeX,style=textscriptsize} -\lstdefinestyle{LaTeXtiny}{style=LaTeX,style=texttiny} - -\def\code{\lstinline[basicstyle=\mdseries\ttfamily\color{red!50!black}]} - -\edef\samplecodename{\jobname-code.vrb} - -\newcommand\constant[1]{\textcolor{violet}{\texttt{#1}}} -\newcommand\ARG[1]{\texttt{\{#1\}}} -\newcommand\OPTARG[1]{\textcolor{green!50!black}{\texttt{[#1]}}} -\newcommand\VAR[1]{\textit{\texttt{<#1>}}} -\newcommand\NOTE[1]{\leavevmode\marginpar{#1}} - -\makeatletter -\def\mynobreakpar{\par\nobreak\@afterheading} -\makeatother -\def\docprefix#1{\texttt{\textcolor{gray}{#1}}} -\def\sankeykeysprefix{/sankey} - -\newenvironment{sankeyoption}[5][]{% [prefix] key, val, default, initially - % \begingroup - \bgroup% - % - \def\path{#1}% - \def\key{#2}% - \def\val{#3}% - \def\default{#4}% - \def\initially{#5}% - %\setlength\parindent{\dimexpr.5\parindent\relax}% - % \vspace{.25\baselineskip plus .25\baselineskip minus 0mm} - \parfillskip 0pt plus 1fil% - \leavevmode% - \ttfamily% - \hspace*{-1cm}\textcolor{red!75!black}{\texttt{\docprefix{\ifdefempty{\path}{\sankeykeysprefix/}{\path/}}\key}}% - \ifdefempty{\val}{}{=\textit{\val}}% - \hfill - \ifdefempty{\default}{\null}{(default:\,\constant{\default})}% - \ifdefempty{\initially}{\null}{(initially:\,\constant{\initially})}% - \mynobreakpar\egroup% - \parskip=.5\baselineskip plus .25\baselineskip minus .25\baselineskip - \parfillskip=30pt plus 1fil - \itemize[topsep=0pt,partopsep=0pt,itemsep=0pt]\item[] -}{% - \enditemize% -} - -\newcommand\MACRO{\hspace*{-1cm}} - -\newlist{sankeyconstantsdesc}{description}{1} -\setlist[sankeyconstantsdesc]{align=right,labelindent=1.5em,labelsep=.5em,leftmargin=!,font=\normalfont} - -\newlength{\myparskip} -\setlength{\myparskip}{.75\baselineskip plus 8\baselineskip minus .25\baselineskip} -\usepackage[skip=\myparskip]{parskip} -%\setlength{\parskip}{\myparskip} -\newenvironment{miniblock}{% - \vspace{.5\parskip}% - \csname minipage*\endcsname[t]{1.0\linewidth}% - \setlength{\parskip}{\myparskip}% -}{% - \csname endminipage*\endcsname% -} - - -\makeatletter -\title{How to use the \texttt{sankey} package\\ to build Sankey diagrams\footnote{This file described version v\sankey@version.}} -\date{Released \sankey@date} -\author{Paul Gaborit\footnote{\href{mailto:paul.gaborit@gmail.com}{\texttt{paul.gaborit@gmail.com}}}} - -\hypersetup{ - pdftitle=How to use the sankey package to buid Sankey diagrams (v\sankey@version), - pdfauthor=Paul Gaborit, -} -\makeatother - - -\begin{document} -\maketitle - -\begin{abstract} - The \texttt{sankey} package provides macros and environments to build - \emph{Sankey diagrams}% - \footnote{\url{https://en.wikipedia.org/wiki/Sankey_diagram}} (or - \emph{flow diagram} in which the width of the arrows is proportional - to the flow rate). The idea cames out from - \href{https://tex.stackexchange.com/q/40159/14500}{this question} on - \href{https://tex.stackexchange.com/}{TeX.StackExchange}. - % -\end{abstract} - -{ - \setlength{\parskip}{0pt} - \tableofcontents - \listoffigures -} - -% ------------------------------------------------------------ -\section{Preamble} -% ------------------------------------------------------------ - -To use the \code{sankey} package, insert the following line in your preamble: - -\begin{lstlisting}[style=LaTeXsmall] -\usepackage{sankey} -\end{lstlisting} - -% ------------------------------------------------------------ -\section{The \texttt{sankeydiagram} environment} -% ------------------------------------------------------------ - -A \code{sankeydiagram} environment nested in a \code{tikzpicture} -environment activates the sankey macros: - -\begin{lstlisting}[style=LaTeXsmall] -\begin{tikzpicture} - \begin{sankeydiagram}[... options ...] - ... sankey macros ... - \end{sankeydiagram} -\end{tikzpicture} -\end{lstlisting} - -% ------------------------------------------------------------ -\section{Sankey diagram options} -% ------------------------------------------------------------ - -The \code{sankey} package uses \code{pgfkeys} to define options via -\emph{key=value} pairs. - -The options can be defined via the optional argument of the -\code{sankeydiagram} environment: - -\begin{lstlisting}[style=LaTeXsmall] -\begin{sankeydiagram}[debug=true] - \sankeynode{name=a,quantity=1,angle=0,at={0,0}} -\end{sankeydiagram} -\end{lstlisting} - -The options can also be modified via the \code{\sankeyset} macro: - -\begin{lstlisting}[style=LaTeXsmall] -\begin{sankeydiagram} - \sankeyset{debug=true} - \sankeynode{name=a,quantity=1,angle=0,at={0,0}} -\end{sankeydiagram} -\end{lstlisting} - -The options can be temporarily modified for a single macro: -\begin{lstlisting}[style=LaTeXsmall] -\begin{sankeydiagram} - \sankeynode[debug=true]{name=a,quantity=1,angle=0,at={0,0}} -\end{sankeydiagram} -\end{lstlisting} -% ------------------------------------------------------------ -\subsection{Keys to choose the scale} -% ------------------------------------------------------------ - -The scale or ratio of the Sankey diagram is the ratio between the % -\code{ratio length} and the \code{ratio quantity}. - -\begin{sankeyoption}{ratio quantity}{\VAR{number}}{}{10} - Quantity (in units of flow) to define ratio. The \VAR{number} can be - any math expression. -\end{sankeyoption} - -\begin{sankeyoption}{ratio length}{\VAR{distance}}{}{1cm} - Distance (a graphical distance) to define scale. -\end{sankeyoption} - -\begin{sankeyoption}{ratio}{\VAR{distance}/\VAR{number}}{}{1cm/10} - Fix the ratio to \VAR{distance}/\VAR{number}. -\end{sankeyoption} - -The initial ratio is 1\,cm/10 units. - - -\textbf{Note:} the \code{sankey} package uses the \code{xfp} package to -evaluate all math expressions that use quantities (in units of -flow). You can therefore use quantities of a very large or very small -order of magnitude. In contrast, for graphic distances, the sankey -package uses the \code{pgfmath} package (all calculations must not -exceed $\pm 16383.99999$). - -% ------------------------------------------------------------ -\subsection{Keys to define drawing parameters} -% ------------------------------------------------------------ - -\begin{sankeyoption}{minimum radius}{\VAR{distance}}{}{5mm} - The minimum radius used by \code{\sankeyturn} and - \code{\sankeydubins}. -\end{sankeyoption} - -\begin{sankeyoption}{outin steps}{\VAR{integer}}{}{10} - Number of steps used by the \code{\sankeyoutin} macro to simulate flow - lanes with constant width. -\end{sankeyoption} - -% ------------------------------------------------------------ -\subsection{Keys to choose drawing styles} -% ------------------------------------------------------------ - -\begin{sankeyoption}{fill/.style}{\VAR{style}}{}{{line width=0pt,fill=white}} - This TikZ style is used to \emph{fill} all sankey paths. -\end{sankeyoption} - -\begin{sankeyoption}{draw/.style}{\VAR{style}}{}{draw=black,line width=.4pt} - This TikZ style is used to \emph{draw} all sankey paths. -\end{sankeyoption} - -\begin{sankeyoption}{start style}{\VAR{style name}}{}{none} - There are three predefined \emph{start} styles: \constant{none}, - \constant{simple}, \constant{arrow}. -\end{sankeyoption} - -\begin{sankeyoption}{end style}{\VAR{style name}}{}{none} - There are three predefined \emph{end} styles: \constant{none}, - \constant{simple}, \constant{arrow}. -\end{sankeyoption} - -% ------------------------------------------------------------ -\subsection{Keys to define new \emph{start} and \emph{end} styles} -% ------------------------------------------------------------ - -\begin{sankeyoption}{new start style}{\{\VAR{name}\}\{\VAR{fill - path}\}\{\VAR{draw path}\}}{}{} - Define the new start style named \VAR{name} with its \VAR{fill - path} and its \VAR{draw path}. -\end{sankeyoption} - -\begin{sankeyoption}{new end style}{\{\VAR{name}\}\{\VAR{fill - path}\}\{\VAR{draw path}\}}{}{} - Define the new end style named \VAR{name} with its \VAR{fill - path} and its \VAR{draw path}. -\end{sankeyoption} - -\emph{Fill} and \emph{draw} paths are composed in a TikZ scope where -the origin is the current Sankey node center (and its name is -\code{\name}) and the coordinate system is rotated by its orientation. - -% ------------------------------------------------------------ -\subsection{The \emph{debug} key} -% ------------------------------------------------------------ - -\begin{sankeyoption}{debug}{\VAR{boolean}}{true}{false} - To debug a sankey diagram. -\end{sankeyoption} - -% ------------------------------------------------------------ -\section{Sankey nodes and flows} -% ------------------------------------------------------------ - -% ------------------------------------------------------------ -\subsection{Create Sankey nodes} -% ------------------------------------------------------------ - -% ------------------------------------------------------------ - -\begin{miniblock} -\MACRO\code{\sankeynode}\OPTARG{\VAR{options}}\ARG{\VAR{node parameters}} - -The \code{\sankeynode} macro defines a Sankey node. The \VAR{options} -can be any Sankey diagram keys. To define a Sankey node, you must -provide a \emph{name}, a \emph{quantity}, an \emph{angle} and a -\emph{position} as \VAR{node parameters}. - -\begin{sankeyoption}[/sankey/node parameters]{name}{\VAR{name}}{}{} - The \VAR{name} of the new Sankey node (and the associated TikZ node). -\end{sankeyoption} - -\begin{sankeyoption}[/sankey/node parameters]{quantity}{\VAR{quantity}}{}{} - The quantity (in flow unit) of the new Sankey node. The \VAR{quantity} - can be any math expression. -\end{sankeyoption} - -\begin{sankeyoption}[/sankey/node parameters]{angle}{\VAR{angle}}{}{} - The orientation of the flow (0 points to the right) of the new Sankey - node. -\end{sankeyoption} - -\begin{sankeyoption}[/sankey/node parameters]{at}{\VAR{at}}{}{} - The position of the new Sankey node (a TikZ coordinate \emph{without} - round brackets or parentheses). -\end{sankeyoption} - -\begin{sankeyoption}[/sankey/node parameters]{anchor}{\VAR{anchor}}{center}{center} - Specify the anchor of the Sankey node. Possible values are - \constant{center}, \constant{left} or \constant{right}. -\end{sankeyoption} - -\begin{sankeyoption}[/sankey/node parameters]{as}{\VAR{name}}{}{} - Copy the \emph{name}, the \emph{quantity}, the \emph{angle} and the - \emph{position} of the Sankey node named \VAR{name}. -\end{sankeyoption} - -A Sankey node is also a Tikz node but with only three anchors: -\code{left}, \code{center} and \code{right}. - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram}[debug] - \draw[gray!30] (-1,-1) grid (8,2); - \sankeynode{name=a,quantity=10,angle=0,at={0,0}} - \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left} - \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right} - - \foreach \nodename/\pos in {a/left,b/below left,c/above}{ - \foreach \ancname in {left,center,right}{ - \node[node font=\ttfamily\footnotesize,\pos=1mm of \nodename.\ancname, - inner sep=0pt,rotate=\sankeygetnodeorient{\nodename},anchor=east] - {\ancname\vphantom{g}}; - \fill[black] (\nodename.\ancname) circle(1pt); - } - } - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} -% ------------------------------------------------------------ - -\begin{miniblock} -\MACRO\code{\sankeynodestart}\OPTARG{\VAR{options}}\ARG{\VAR{node parameters}} - -The \code{\sankeynodestart} creates and fills/draws a starting Sankey node: - - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}] - \draw[gray!30] (-1,-1) grid (8,2); - \sankeynodestart{name=a,quantity=10,angle=0,at={0,0}} - \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left} - \sankeynodestart{name=c,quantity=20,angle=-90,at={5,1},anchor=right} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} -% ------------------------------------------------------------ - - -\begin{miniblock} -\MACRO\code{\sankeynodeend}\OPTARG{\VAR{options}}\ARG{\VAR{node - parameters}} - -The \code{\sankeynodeend} creates -and fills/draws an ending Sankey node: - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram}[end style=simple,fill/.style={fill=orange!20}] - \draw[gray!30] (-1,-1) grid (8,2); - \sankeynodeend{name=a,quantity=10,angle=0,at={0,0}} - \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left} - \sankeynodeend{name=c,quantity=20,angle=-90,at={5,1},anchor=right} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} - -\subsection{Retrieve informations from a Sankey node} - -\MACRO\code{\sankeygetnodeqty}\ARG{\VAR{node name}} - -The expandable command \code{\sankeygetnodeqty} returns the quantity -assigned to the Sankey node named \VAR{node name}. - -\MACRO\code{\sankeygetnodeorient}\ARG{\VAR{node name}} - -The expandable command \code{\sankeygetnodeorient} returns the angle -(orientation) assigned to the Sankey node named \VAR{node name}. - -% ------------------------------------------------------------ -\newpage -\subsection{Move nodes} -% ------------------------------------------------------------ - -The \code{\sankeyadvance} and \code{\sankeyturn} commands move a Sankey -node (and fill/draw a portion of the Sankey flow). Then the previous -position of the Sankey node is accessible via the \code{-old} suffix (if -you move the \code{a} node, its previous position is the \code{a-old} -node). - -\subsubsection{forward commands} - -\begin{miniblock} -\MACRO\code{\sankeyadvance}\OPTARG{\VAR{options}}\ARG{\VAR{node - name}}\ARG{\VAR{distance}} - -The \code{\sankeyadvance} moves the sankey node straight ahead and -fills/draws this portion of the sankey path. - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}] - \draw[gray!30] (-1,-1) grid (8,2); - \sankeynodestart{name=a,quantity=10,angle=0,at={0,0}} - \sankeyadvance{a}{1cm} - \sankeynode[debug]{as=a} - \sankeynode[debug]{as=a-old} - \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left} - \sankeyadvance{b}{1cm} - \sankeynodestart{name=c,quantity=10,angle=-90,at={5,1},anchor=right} - \sankeyadvance{c}{5mm} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} - -\begin{miniblock} -\MACRO\code{\sankeyturn}\OPTARG{\VAR{options}}\ARG{\VAR{node - name}}\ARG{\VAR{angle}} - -The \code{\sankeyturn} macro moves the sankey node by turning to one -side or the other and fills/draws this portion of the sankey path. A -\emph{positive} \VAR{angle} turns left while a \emph{negative} -\VAR{angle} turns right. - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}] - \draw[gray!30] (-1,-1) grid (8,2); - \sankeynodestart{name=a,quantity=10,angle=0,at={0,0}} - \sankeyturn{a}{90} - \sankeynode[debug]{as=a} - \sankeynode[debug]{as=a-old} - \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left} - \sankeyturn[minimum radius=1cm]{b}{-45} - \sankeynodestart{name=c,quantity=10,angle=-90,at={5,1},anchor=right} - \sankeyturn{c}{180} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} - -\subsubsection{backward commands} - -\begin{miniblock} -\MACRO\code{\sankeyadvance*}\OPTARG{\VAR{options}}\ARG{\VAR{node - name}}\ARG{\VAR{distance}} - -The \code{\sankeyadvance*} moves the sankey node straight back and -fills/draws this portion of the sankey path. - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram}[end style=arrow,fill/.style={fill=orange!20}] - \draw[gray!30] (-1,-1) grid (8,2); - \sankeynodeend{name=a,quantity=10,angle=0,at={0,0}} - \sankeyadvance*{a}{1cm} - \sankeynode[debug]{as=a} - \sankeynode[debug]{as=a-old} - \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left} - \sankeyadvance*{b}{1cm} - \sankeynodeend{name=c,quantity=10,angle=-90,at={5,1},anchor=right} - \sankeyadvance*{c}{5mm} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} - -\begin{miniblock} -\MACRO\code{\sankeyturn*}\OPTARG{\VAR{options}}\ARG{\VAR{node - name}}\ARG{\VAR{angle}} - -The \code{\sankeyturn*} macro moves the sankey node backwards by turning -right or left and fills/draws this portion of the sankey path. A -\emph{positive} \VAR{angle} turns left while a \emph{negative} -\VAR{angle} turns right. - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram}[end style=simple,fill/.style={fill=orange!20}] - \draw[gray!30] (-1,-1) grid (8,2); - \sankeynodeend{name=a,quantity=10,angle=0,at={0,0}} - \sankeyturn*{a}{90} - \sankeynode[debug]{as=a} - \sankeynode[debug]{as=a-old} - \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left} - \sankeyturn*[minimum radius=1cm]{b}{-45} - \sankeynodeend{name=c,quantity=10,angle=-90,at={5,1},anchor=right} - \sankeyturn*{c}{180} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} - -\subsection{Links between nodes} - -\begin{miniblock} - \MACRO\code{\sankeyoutin}\OPTARG{\VAR{options}}\ARG{\VAR{node - A}}\ARG{\VAR{node B}} - - The \code{\sankeyoutin} macro fills/draws a lane between \VAR{node A} - and \VAR{node B} using a Bézier curve with regular steps (10 steps by - default) to simulate constant width lane. - - The constant width and the minimum curvature are \emph{not} guaranted! -\end{miniblock} - -\begin{miniblock} - \MACRO\code{\sankeydubins}\OPTARG{\VAR{options}}\ARG{\VAR{node - A}}\ARG{\VAR{node B}} - - The \code{\sankeydubins} macro fills/draws a lane between \VAR{node A} - and \VAR{node B} using a Dubins - path\footnote{\url{https://en.wikipedia.org/wiki/Dubins_path}}. - - The constant width and the minimum curvature are guaranted. -\end{miniblock} - -\subsubsection{Comparison betwen \texttt{outin} and \texttt{dubins} - paths} - -\begin{miniblock} -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram}[start style=simple,end style=arrow] - \draw[gray!30] (0,-1) grid (10,3.5); - % - \sankeyset{fill/.style={fill=orange!20}} - \sankeynodestart{name=a,at={1,0},angle=0,quantity=5} - \sankeynodeend{name=b,at={5,3},angle=0,quantity=5} - \sankeyoutin{a}{b} - % - \sankeyset{fill/.style={fill=red!20}} - \sankeynodestart{name=a,at={3,0},angle=0,quantity=5} - \sankeynodeend{name=b,at={7,3},angle=0,quantity=5} - \sankeyoutin[outin steps=2]{a}{b} - % - \sankeyset{fill/.style={fill=lime!40}} - \sankeynodestart{name=a,at={5,0},angle=0,quantity=5} - \sankeynodeend{name=b,at={(9,3},angle=0,quantity=5} - \sankeydubins[minimum radius=5mm]{a}{b} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} - -\begin{miniblock} -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram}[start style=simple,end style=arrow] - \draw[gray!30] (0,0) grid (8,4.5); - % - \sankeyset{fill/.style={fill=orange!20}} - \sankeynodestart{name=a,at={1,1},angle=0,quantity=5} - \sankeynodeend{name=b,at={3,4},angle=0,quantity=5} - \sankeyoutin{a}{b} - % - \sankeyset{fill/.style={fill=red!20}} - \sankeynodestart{name=a,at={3,1},angle=0,quantity=5} - \sankeynodeend{name=b,at={5,4},angle=0,quantity=5} - \sankeyoutin[outin steps=2]{a}{b} - % - \sankeyset{fill/.style={fill=lime!40}} - \sankeynodestart{name=a,at={5,1},angle=0,quantity=5} - \sankeynodeend{name=b,at={(7,4},angle=0,quantity=5} - \sankeydubins[minimum radius=5mm]{a}{b} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} - -\begin{miniblock} -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram}[start style=simple,end style=arrow] - \draw[gray!30] (0,0) grid ((6,4.5); - % - \sankeyset{fill/.style={fill=orange!20}} - \sankeynodestart{name=a,at={1,1},angle=0,quantity=5} - \sankeynodeend{name=b,at={1,4},angle=0,quantity=5} - \sankeyoutin{a}{b} - % - \sankeyset{fill/.style={fill=red!20}} - \sankeynodestart{name=a,at={3,1},angle=0,quantity=5} - \sankeynodeend{name=b,at={3,4},angle=0,quantity=5} - \sankeyoutin[outin steps=2]{a}{b} - % - \sankeyset{fill/.style={fill=lime!40}} - \sankeynodestart{name=a,at={5,1},angle=0,quantity=5} - \sankeynodeend{name=b,at={(5,4},angle=0,quantity=5} - \sankeydubins[minimum radius=5mm]{a}{b} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} - -\subsubsection{Examples of \texttt{dubins} paths} - -\begin{miniblock} -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram}[start style=simple,end style=arrow] - \draw[gray!30] (-1,-1) grid (10,2.5); - - \sankeyset{ - fill/.style={fill=lime!40}, - draw/.style={draw=green!50!black,line width=2pt}, - } - - \sankeynodestart{name=a,at={0,0},angle=0,quantity=5} - \sankeynodeend{name=b,at={0,2},angle=0,quantity=5} - \sankeydubins[minimum radius=2mm]{a}{b} - - \fill[green!50!black] (2,0) coordinate (c) circle(2pt); - \sankeynodestart{name=a,at={[shift={(c)}]90:5mm},angle=0,quantity=5} - \sankeynodeend{name=b,at={[shift={(c)}]150:5mm},angle=60,quantity=5} - \sankeydubins[minimum radius=2.5mm]{a}{b} - - \sankeynodestart{name=a,at={3.5,0},angle=0,quantity=5} - \sankeynodeend{name=b,at={3.5,.75},angle=-180,quantity=5} - \sankeydubins[minimum radius=5mm]{a}{b} - - \sankeynodestart{name=a,at={7,1},angle=0,quantity=5} - \sankeynodeend{name=b,at={7,1.75},angle=0,quantity=5} - \sankeydubins[minimum radius=2.5mm]{a}{b} - - \sankeynodestart{name=a,at={9,0},angle=0,quantity=5} - \sankeynodeend{name=b,at={9,2},angle=180,quantity=5} - \sankeydubins[minimum radius=2.5mm]{a}{b} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} - -\subsection{Pure filling/drawing macros} - -\begin{miniblock} -\MACRO\code{\sankeystart}\OPTARG{\VAR{options}}\ARG{\VAR{name}} - -The \code{\sankeystart} fills/draws a starting extremity attached to the -preexistent Sankey node \VAR{name}: - - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram} - [start style=arrow,fill/.style={fill=cyan!20},draw/.style={draw=blue}] - \draw[gray!30] (-1,-1) grid (8,2); - \sankeynode{name=a,quantity=10,angle=0,at={0,0}} - \sankeystart{a} - \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left} - \sankeystart{b} - \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right} - \sankeystart{c} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} -% ------------------------------------------------------------ - - -\begin{miniblock} - \MACRO\code{\sankeyend}\OPTARG{\VAR{options}}\ARG{\VAR{name}} - - The \code{\sankeyend} fills/draws an ending extremity attached to the - preexistent Sankey node \VAR{name}: - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram} - [end style=simple,fill/.style={fill=cyan!20},draw/.style={draw=blue}] - \draw[gray!30] (-1,-1) grid (8,2); - \sankeynode{name=a,quantity=10,angle=0,at={0,0}} - \sankeyend{a} - \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left} - \sankeyend{b} - \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right} - \sankeyend{c} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} - -\subsection{Forked node} - -\begin{miniblock} - \MACRO\code{\sankeyfork}\OPTARG{\VAR{options}}\ARG{\VAR{node}}\ARG{\VAR{quantity/name pairs}} - - The \code{\sankeyfork} macro splits a Sankey node in a list of new - Sankey nodes. The \VAR{quantity/name pairs} is a comma separated list - of \emph{quantity/name} pairs. The sum of all quantities \emph{must} - be equal to the quantity of the node to fork. - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram}[debug] - \draw[gray!30] (-3,-2) grid (3,1); - \sankeynode{name=a,quantity=50,angle=-80,at={0,0}} - \sankeyfork{a}{30/b,10/c,10/d} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \begin{sankeydiagram} - \sankeyset{ - start style=arrow,end style=arrow, - fill/.style={fill=yellow!10,line width=0pt,draw=yellow!10}, - } - \draw[gray!30] (-4,-3) grid (4,4); - \sankeynode{name=a,quantity=40,angle=-90,at={0,0}} - \sankeyfork{a}{25/b,10/c,5/d} - \sankeyturn*{b}{90} - \sankeyturn*[minimum radius=2cm]{c}{-45} - \sankeyturn*[minimum radius=2cm]{c}{45} - \sankeyturn*[minimum radius=5mm]{d}{-90} - \sankeyadvance{a}{2cm} - \foreach \nodename in {b,c,d}{ - \sankeystart{\nodename} - } - \sankeyend{a} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -{\centering\input{\samplecodename}\par} -\end{miniblock} - -\section{Miscellaneous} - -\subsection{The \texttt{debug} layer} - -The \code{debug} option key uses the \code{sankeydebug} layer to draw -above the \code{main} TikZ layer (via \code{\pgfsetlayers}, the -\code{sankey} package installs four layers: \code{background}, -\code{main}, \code{foreground}, \code{sankeydebug}). - -The four following styles define how to display debug informations: - - -\begin{lstlisting}[style=LaTeXsmall] -\sankeyset{ - % debug color used by all debug macros - debug color/.style={/utils/exec={\colorlet{debug color}{#1}}}, - debug color=red!75!black, - % debug line between left and right anchors - debug line/.style={draw=debug color,|-|}, - % debug line between center and label - debug normal/.style={draw=debug color}, - % debug node label - debug label/.style={ - draw, - font=\ttfamily\tiny, - text=debug color,text opacity=1, - inner sep=.1em, - fill=white,fill opacity=1, - rounded corners=.1em, - }, -} -\end{lstlisting} - -\subsection{The \texttt{dubins} TikZ library} - -The \code{sankey} package uses the \code{dubins} TikZ library (the -\code{tikzlibrarydubins.code.tex} file) to compute Dubins paths. The -documentation for this library does not yet exist. - -\subsection{How to duplicate a Sankey node} - -\MACRO\code{\sankeynodealias}\ARG{\VAR{origname}}\ARG{\VAR{clonename}} - -The \code{\sankeynodealias} macro clones the Sankey node named -\VAR{origname} into the Sankey node named \VAR{clonename}. - -So, you can clone a Sankey node via two methods: - -\begin{lstlisting}[style=LaTeXsmall] -\sankeynode{name=a,quantity=10,angle=0,at={0,0}} -\sankeynode{as=a,name=b} -\end{lstlisting} - -\begin{lstlisting}[style=LaTeXsmall] -\sankeynode{name=a,quantity=10,angle=0,at={0,0}} -\sankeynodealias{a}{b} -\end{lstlisting} - -\subsection{How to define new start and end styles} - -Here are the definitions of the \code{arrow} styles: - -\begin{lstlisting}[style=LaTeXsmall] -\sankeyset{ - % arrow style - new start style={arrow}{ - (\name.left) -- ++(-10pt,0) - -- ([xshift=-10pt/6]\name.center) - -- ([xshift=-10pt]\name.right) - -- (\name.right) -- cycle - }{ - (\name.left) -- ++(-10pt,0) - -- ([xshift=-10pt/6]\name.center) - -- ([xshift=-10pt]\name.right) - -- (\name.right) - }, - new end style={arrow}{ - (\name.left) -- ([yshift=1mm]\name.left) - -- ([xshift=10pt]\name.center) - -- ([yshift=-1mm]\name.right) -- (\name.right) -- cycle - }{ - (\name.left) -- ([yshift=1mm]\name.left) - -- ([xshift=10pt]\name.center) - -- ([yshift=-1mm]\name.right) -- (\name.right) - }, -} -\end{lstlisting} - -\section{History} - -\begin{itemize} -\item[v2.0] (2021/01/27) - \begin{itemize} - \item First public version (on CTAN). - \end{itemize} -\item[v1.0] (2016/03/06) - \begin{itemize} - \item First version. - \end{itemize} -\end{itemize} - -\clearpage -\section{Examples} - -\subsection{Simple example} - -See figure~\ref{fig:simple-example}. - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \colorlet{cold}[rgb]{cyan!75!blue!50!white} - \colorlet{hot}[rgb]{red!50!orange!75!white} - \begin{sankeydiagram} - \sankeyset{ - ratio=90pt/6, - minimum radius=15pt, - start style=simple, - end style=simple, - % debug, - draw/.style={ - draw=blue!50!cyan, - line width=1pt, - line cap=round,line join=round, - }, - cold/.style={ - fill/.style={ - draw=cold, - line width=0pt, - fill=cold, - }, - }, - cold to hot/.style={ - fill/.style={ - fill=none, - top color=cold, - bottom color=hot, - middle color=yellow, - }, - }, - hot/.style={ - fill/.style={ - draw=hot, - line width=0pt, - fill=hot, - }, - }, - } - - \sankeyset{cold} - \sankeynodestart{name=p0,at={0,100},angle=-90,quantity=6} - \sankeyadvance{p0}{50pt} - - \sankeyfork{p0}{3/p1,3/p2} - - \sankeyturn{p1}{90} - \sankeyadvance{p1}{20pt} - - \sankeyadvance{p2}{60pt} - - \sankeyfork{p2}{2/p3,1/p4} - - \sankeyturn{p3}{90} - \sankeyadvance{p3}{50pt} - - \sankeyfork{p3}{1/p5,1/p6} - - \sankeyadvance{p5}{70pt} - - \sankeyfork{p1}{1/p7,1/p8,1/p9} - \sankeyadvance{p7}{50pt} - \sankeyadvance{p9}{50pt} - - \sankeyadvance{p4}{40pt} - \sankeyturn{p4}{90} - \sankeyadvance{p4}{65pt} - - \sankeyadvance{p7}{40pt} - - \sankeynode{name=p11,at={[shift={(50pt,-15pt)}]p7},angle=0,quantity=3} - \sankeyfork{p11}{1/p7a,1/p9a,1/p5a} - \sankeyoutin{p7}{p7a} - \sankeyoutin{p9}{p9a} - \sankeyoutin{p5}{p5a} - \sankeyadvance{p11}{30pt} - \sankeyend{p11} - - \sankeyturn{p8}{-90} - \sankeyturn{p6}{-90} - \sankeyturn{p4}{-90} - - \sankeyset{hot} - - \sankeyadvance[cold to hot]{p8}{40pt} - - \sankeynode{name=p10,at={[shift={(-15pt,-60pt)}]p8},angle=-90,quantity=3} - \sankeyfork{p10}{1/p8a,1/p6a,1/p4a} - \sankeyoutin[cold to hot]{p4}{p4a} - \sankeyoutin[cold to hot]{p6}{p6a} - \sankeyoutin{p8}{p8a} - \sankeyadvance{p10}{30pt} - \sankeyend{p10} - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -\begin{figure}[b!] - \centering - \input{\samplecodename} - \caption{Simple example} - \label{fig:simple-example} -\end{figure} -\clearpage -\subsection{Example from question on TeX.se} - -This example cames from -\href{https://tex.stackexchange.com/q/40159/14500}{this question} on -\href{https://tex.stackexchange.com/}{TeX.StackExchange}. - -See figure~\ref{fig:texse-example}. - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - \renewcommand*\sfdefault{txss} - - \begin{sankeydiagram} - - \sankeyset{ - ratio=4cm/524.3, - minimum radius=3mm, - start style=arrow, - end style=arrow, - % debug, - fill/.style={ - line width=0pt, - fill=cyan!50!blue!50!black, - draw=cyan!50!blue!50!black, - }, - draw/.style={draw=none}, - } - - \sankeynodestart{name=B,at={-.5,0},angle=-90,quantity=7.2} - \coordinate[below=1mm of B.center] (B label); - \sankeyadvance{B}{5mm} - \sankeynodestart{name=GI,at={1,0},angle=-90,quantity=137.3} - \coordinate[below=1mm of GI.center] (GI label); - \sankeyadvance{GI}{5mm} - \sankeynodestart{name=I,at={4,0},angle=-90,quantity=397.8} - \coordinate[below=1mm of I.center] (I label); - \sankeynode{name=EI,at={2.86,-3},angle=-90,quantity=542.3} - \sankeyfork{EI}{397.8/Ia,137.3/GIa,7.2/Ba} - \sankeydubins[minimum radius=1.2cm]{I}{Ia} - \sankeyoutin{GI}{GIa} - \sankeyoutin{B}{Ba} - \sankeyadvance{EI}{5mm} - \coordinate (EI label) at (EI); - \sankeyadvance{EI}{5mm} - \sankeyfork{EI}{63.1/EB,479.2/P} - - \sankeyturn{EB}{90} - \sankeyadvance{EB}{4cm} - \coordinate (EB label) at ($(EB)!.5!(EB-old)$); - \sankeyend{EB} - - \sankeyadvance{P}{10mm} - \coordinate (P label) at (P); - \sankeyadvance{P}{5mm} - - \sankeyfork{P}{33.5/NV,445.7/P} - - { - \colorlet{NV color}{cyan!80!lime!50!gray} - \sankeyset{fill/.append style={fill=NV color,draw=NV color}} - \sankeyturn{NV}{90} - \sankeynode{as=NV,name=NV2,at=NV -| EB} - \sankeyoutin{NV}{NV2} - \coordinate (NV label) at (NV -| EB label); - \sankeyend{NV2} - } - - \sankeyadvance{P}{10mm} - \sankeyfork{P}{118.1/U,327.6/P} - - { - \sankeyset{ - fill/.style={fill=orange!70!gray!50,draw=orange!70!gray!50} - } - \sankeyturn{U}{90} - \sankeynode{as=U,name=U2,at=U -| EB} - \sankeyoutin{U}{U2} - \coordinate (U label) at (U -| EB label); - \sankeyend{U2} - } - - \sankeyadvance{P}{10mm} - - \sankeyfork{P}{327.2/P,0.4/SD} - - { - \sankeyturn{SD}{-90} - \sankeyadvance{SD}{15mm} - \coordinate (SD label) at (SD); - \sankeyadvance{SD}{15mm} - \sankeyend{SD} - } - - \sankeyadvance{P}{8mm} - \sankeyfork{P}{18.8/VE,308.4/E} - - { - \sankeyset{fill/.append style={orange!70!gray!30}} - \sankeyturn{VE}{90} - \sankeynode{as=VE,name=VE2,at=VE -| EB} - \sankeyoutin{VE}{VE2} - \coordinate (VE label) at (VE -| EB label); - \sankeyend{VE2} - } - - \sankeyadvance{E}{8mm} - \coordinate (E label) at (E); - \sankeyadvance{E}{20mm} - - \sankeyfork{E}{135.1/H+GHD,87.2/V,86.1/In} - - \sankeyturn{In}{-90} - \sankeyadvance{In}{10mm} - \sankeyturn{In}{90} - \sankeyadvance{In}{5mm} - \coordinate (In label) at (In); - \sankeyadvance{In}{10mm} - \sankeyend{In} - - \sankeynode{as=V,name=V2,at=V|-In label} - \sankeyoutin{V}{V2} - \coordinate (V label) at (V2); - \sankeyadvance{V2}{10mm} - \sankeyend{V2} - - \sankeyturn{H+GHD}{90} - \sankeyadvance{H+GHD}{5mm} - \sankeyfork{H+GHD}{47.0/GHD,88.1/H} - - \sankeyturn{H}{-90} - \sankeynode{as=H,name=H2,at=H|-In label} - \sankeyoutin{H}{H2} - \coordinate (H label) at (H2); - \sankeyadvance{H2}{10mm} - \sankeyend{H2} - - \sankeyadvance{GHD}{30mm} - \sankeyturn{GHD}{-90} - \sankeynode{as=GHD,name=GHD2,at=GHD|-In label} - \sankeyoutin{GHD}{GHD2} - \coordinate (GHD label) at (GHD2); - \sankeyadvance{GHD2}{10mm} - \sankeyend{GHD2} - \end{sankeydiagram} - - % labels - \tikzset{ - label/.style={ - fill=white,fill opacity=.8,text opacity=1, - inner sep=1mm, - text=cyan!50!blue!50!black, - inner xsep=2mm, - font=\sffamily\bfseries\footnotesize, - align=center, - }, - } - \node[label,anchor=north] (B label) at (B label) {7.2}; - \node[label,left=1mm of B label] {Bestands-\\entnahme}; - \node[label,anchor=north] at (GI label) {137.3}; - \node[label,above=5mm of GI label] {Gewinnung\\im Inland}; - \node[label,anchor=north] at (I label) {397.8}; - \node[label,above=5mm of I label] {Import}; - - \node[label] at (EI label) {542.3\\Energieaufkommen im Inland}; - - \node[label,anchor=center] (EB label) at (EB label) {63.1}; - \node[label,above=1mm of EB label] {Export und\\Bunkerung}; - - \node[label] at (P label) {479.2\\Primärenergieverbrauch}; - - \node[label,anchor=center] (NV label) at (NV label) {33.5}; - \node[label,above=0mm of NV label] {Nichtenergetischer Verbrauch}; - - \node[label,anchor=center] (U label) at (U label) {118.1}; - \node[label,below=3mm of U label] {Umwandlungsverluste}; - - \node[label,anchor=center] (SD label) at (SD label) {0.4}; - \node[label,above=0mm of SD label] {Statistische\\Differenzen}; - - \node[label,anchor=center] (VE label) at (VE label) {18.8}; - \node[label,below=0mm of VE label] {Verbrauch in den\\Energiesktoren}; - - \node[label,anchor=north] (E label) at (E label) - {308.4\\Endenergieverbrauch}; - - \node[label,anchor=north] (In label) at (In label) {86.1}; - \node[label,anchor=north,below=1cm of In label] {Industrie}; - - \node[label,anchor=north] (V label) at (V label) {87.2}; - \node[label,anchor=north,below=1cm of V label] {Verkehr}; - - \node[label,anchor=north] (H label) at (H label) {88.1}; - \node[label,anchor=north,below=1cm of H label] {Haushalte}; - - \node[label,anchor=north] (GHD label) at (GHD label) {47.0}; - \node[label,anchor=north,below=1cm of GHD label] - {Gewerbe, Handel\\Diensleistungen}; -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[style=LaTeXsmall]{\samplecodename} -% -\begin{figure} - \centering - %\rule{\linewidth}{1pt}\\ - \input{\samplecodename} - \caption{Example from TeX.se question} - \label{fig:texse-example} -\end{figure} - -\clearpage -\subsection{Very nice example -- Nadieh Bremer creation} - -Graphic designer Nadieh Bremer created this very nice Sankey -diagram\footnote{\url{https://www.visualcinnamon.com/portfolio/adyen-report-2019/}} -for Adyen's second half 2018 report to shareholders. It is coded here -with her kind permission. - -You can change the data values between lines 28 and 53. - -See figure~\ref{fig:nice-example}. - -\begin{filecontents*}{\samplecodename} -\begin{tikzpicture} - % - \renewcommand*\sfdefault{txss} - \sffamily - \sisetup{ - detect-all=true, - group-separator={,}, - group-minimum-digits=4, - } - % storage of labels - \newcommand\LabSet[2]{% none name, label - \expandafter\edef\csname #1Lab\endcsname{#2}} - \newcommand\Lab[1]{% node name - \csname #1Lab\endcsname} - % storage of quantities - \newcommand\QtySet[2]{% node name, quantity - \expandafter\edef\csname #1Qty\endcsname{\fpeval{#2}}} - \newcommand\Qty[1]{% node name - \csname #1Qty\endcsname} - % all nodes with their name, label and quantity - \sankeyset{ - def data/.code args={#1/#2/#3}{% node name/label/values - \LabSet{#1}{#2} - \QtySet{#1}{#3} - \typeout{#1: \Qty{#1}€ (\Lab{#1})} - }, - def data/.list={ - {Pf/Processing\\fees/71713}, - {Sog/Sales of\\good/4547}, - {Sf/Settlement\\fees/842075}, - {Os/Other\\services/37532}, - {R/Revenues/\Qty{Pf}+\Qty{Sog}+\Qty{Sf}+\Qty{Os}}, - {Coi/Cost of Inventory/5151}, - {Ciffi/Cost insecure from financial institutions/758234}, - {Nr/Net revenue/\Qty{R}-\Qty{Coi}-\Qty{Ciffi}}, - {Aadotaifa/Amortization and\\depreciation of tangible and\\% - intangible fixed assets/4688}, - {Ssapc/Social securities and\\pension costs/7860}, - {Was/Wages and salaries/35627}, - {Ooe/Other operating expenses/37346}, - {Nr2/-/\Qty{Nr}-\Qty{Aadotaifa}-\Qty{Ssapc}-\Qty{Was}-\Qty{Ooe}}, - {Oi/Other income/47}, - {Ibiiieait/Income before interest income,\\interest expense and % - income taxes/\Qty{Nr2}+\Qty{Oi}}, - {Fe/Finance expense/561}, - {Ofr/Other financial results/2533}, - {Ibiiieait2/-/\Qty{Ibiiieait}-\Qty{Fe}-\Qty{Ofr}}, - {Fi/Finance income/204}, - {Ibit/Income before income taxes/\Qty{Ibiiieait2}+\Qty{Fi}}, - {It/Income taxes/21134}, - {Niftp/Net income for the period/\Qty{Ibit}-\Qty{It}}, - {Octa/Other currency\\translation adjustments/785}, - {Tci/Total comprehensive income/\Qty{Niftp}+\Qty{Octa}} - }, - } - - \definecolor{mygreen}{RGB}{9,192,82} - \tikzset{ - cost node/.style 2 args={ - overlay, - align=flush center, - node font=\footnotesize\sffamily\bfseries, - inner sep=0, - node contents={% - {\mdseries€\,\num{#1}}\\% - #2\vphantom{g}% - }, - }, - white hash/.style={ - draw=none,fill=none, - pattern={Lines[angle=60,line width=2pt,distance=4pt]}, - pattern color=white, - }, - line sep/.style={draw=white,line width=1pt}, - left label/.style={left=#1,align=flush right,anchor=north east}, - right label/.style={right=#1,align=flush left}, - right label hashed/.style={ - right=1mm of $(#1.left)!.5!(#1-old.left)$,align=flush left, - }, - left label hashed/.style={ - left=1mm of $(#1.right)!.5!(#1-old.right)$,align=flush right, - }, - } - - \newcommand\turnandstop[1]{ - \sankeyturn[green to greenwhite]{#1}{-90} - \sankeynode{as=#1,name=#1-e,at={#1 -| Coi}} - \sankeyoutin[greenwhite to white]{#1}{#1-e} - \node[cost node={\Qty{#1}}{\Lab{#1}},left label={1mm of #1-e.right}]; - } - - \begin{sankeydiagram} - \sankeyset{ - ratio=28em/1000000, - minimum radius=2cm, - start style=none, - % default fill and draw styles - fill/.style={ - line width=0pt, - fill=mygreen, - }, - draw/.style={draw=none}, - % specific fill and draw styles - green to greenwhite/.style={ - fill/.style={ - line width=0pt, - right color=mygreen, - left color=mygreen!20!white, - } - }, - greenwhite to white/.style={ - fill/.style={ - line width=0pt, - right color=mygreen!20!white, - left color=mygreen!5!white, - } - }, - dashed/.style={draw/.style={draw=mygreen,dashed}}, - % debug, - } - - \coordinate (top) at (0,2em); - - \sankeynodestart{name=Pf,quantity=\Qty{Pf}, - at={0,0},angle=-90} - \node[cost node={\Qty{Pf}}{\Lab{Pf}},above=.5em of Pf.center]; - - \sankeynodestart{name=Sog,quantity=\Qty{Sog}, - at={[xshift=4em]Pf.left},angle=-90,anchor=right} - \node[cost node={\Qty{Sog}}{\Lab{Sog}},above=.5em of Sog.center]; - - \sankeynodestart{name=Sf,quantity=\Qty{Sf}, - at={[xshift=2em]Sog.left},angle=-90,anchor=right} - \node[cost node={\Qty{Sf}}{\Lab{Sf}},above=.5em of Sf.center]; - - \sankeynodestart{name=Os,quantity=\Qty{Os}, - at={[xshift=2em]Sf.left},angle=-90,anchor=right} - \node[cost node={\Qty{Os}}{\Lab{Os}},above=.5em of Os.center]; - - \sankeynode{name=R,quantity=\Qty{R}, - at={[yshift=-10em]Sf.center},angle=-90} - \sankeyfork{R}{\Qty{Os}/Os-a,\Qty{Sf}/Sf-a,\Qty{Sog}/Sog-a,\Qty{Pf}/Pf-a} - - \foreach \nodename in {Pf,Sog,Sf,Os}{ - \sankeyoutin[fill/.style={top color=white,bottom color=mygreen}] - {\nodename}{\nodename-a} - } - - \sankeyadvance{R}{1em} - \node[cost node={\Qty{R}}{\Lab{R}},right label hashed=R]; - - \sankeyfork{R}{\Qty{Ciffi}/Ciffi,\Qty{Nr}/Nr,\Qty{Coi}/Coi} - - \sankeyturn[minimum radius=1.cm]{Ciffi}{90} - \node[cost node={\Qty{Ciffi}}{\Lab{Ciffi}}, - at={([shift={(1mm,0)}]Ciffi.center)},rotate=-90, - anchor=south,align=flush left,node font=\scriptsize\sffamily\bfseries]; - - \sankeyturn[green to greenwhite]{Coi}{-90} - \sankeyadvance[greenwhite to white]{Coi}{1em} - \node[cost node={\Qty{Coi}}{\Lab{Coi}}, - left={1mm of [yshift=.75ex]Coi.left}, - align=flush right,anchor=north east,overlay]; - - \sankeyadvance{Nr}{9em} - \sankeyadvance{Nr}{1em} - \node[cost node={\Qty{Nr}}{\Lab{Nr}}, - left label hashed=Nr,node font=\large\sffamily\bfseries]; - - \sankeyfork{Nr}{\Qty{Nr2}/Nr2,\Qty{Ooe}/Ooe, - \Qty{Was}/Was,\Qty{Ssapc}/Ssapc,\Qty{Aadotaifa}/Aadotaifa} - - \turnandstop{Aadotaifa} - - \sankeyadvance{Ssapc}{5em} - \turnandstop{Ssapc} - - \sankeyadvance{Was}{9em} - \turnandstop{Was} - - \sankeyadvance{Ooe}{12em} - \turnandstop{Ooe} - - \sankeyadvance{Nr2}{15em} - \sankeynode{name=Ibiiieait,quantity=\Qty{Ibiiieait}, - angle=-90,anchor=right,at={Nr2.right}} - \sankeyfork{Ibiiieait}{\Qty{Oi}/Oi,\Qty{Nr2}/Nr2-e} - - \sankeyturn*[minimum radius=1cm,dashed]{Oi}{90} - \node[cost node={\Qty{Oi}}{\Lab{Oi}},right label=1mm of Oi.left]; - - \sankeyadvance{Ibiiieait}{1em} - \node[cost node={\Qty{Ibiiieait}}{\Lab{Ibiiieait}}, - right label hashed=Ibiiieait]; - - \sankeyfork{Ibiiieait} - {\Qty{Ibiiieait2}/Ibiiieait2,\Qty{Ofr}/Ofr,\Qty{Fe}/Fe} - - \turnandstop{Fe} - - \sankeyadvance{Ofr}{3em} - \turnandstop{Ofr} - - \sankeyadvance{Ibiiieait2}{6em} - \sankeynode{name=Ibit,quantity={\Qty{Ibiiieait2}+\Qty{Fi}}, - angle=-90,anchor=right,at={Ibiiieait2.right}} - \sankeyfork{Ibit}{\Qty{Fi}/Fi,\Qty{Ibiiieait2}/Ibiiieait2-e} - - \sankeyturn*[minimum radius=1cm,dashed]{Fi}{90} - \node[cost node={\Qty{Fi}}{\Lab{Fi}},right label=1mm of Fi.left]; - - \sankeyadvance{Ibit}{1em} - \node[cost node={\Qty{Ibit}}{\Lab{Ibit}},right label hashed=Ibit]; - - \sankeyfork{Ibit}{\Qty{Niftp}/Niftp,\Qty{It}/It} - - \turnandstop{It} - - \sankeyadvance{Niftp}{6em} - - \sankeyadvance{Niftp}{1em} - \node[cost node={\Qty{Niftp}}{\Lab{Niftp}},right label hashed=Niftp]; - - \sankeynode{name=Tci,quantity=\Qty{Niftp}+\Qty{Octa}, - angle=-90,anchor=right,at={[yshift=-6em]Niftp.right}} - \sankeyfork{Tci}{\Qty{Octa}/Octa,\Qty{Niftp}/Niftp-e} - \sankeyoutin{Niftp}{Niftp-e} - - \sankeyturn*[minimum radius=1cm]{Octa}{90} - \node[cost node={\Qty{Octa}}{\Lab{Octa}},right label=1mm of Octa.left]; - - \sankeyadvance{Tci}{1em} - \node[cost node={\Qty{Tci}}{\Lab{Tci}},right label hashed=Tci]; - - \newcommand\hashband[1]{ - \draw[line sep] (#1-old.right) -- (#1-old.left); - \draw[line sep] (#1.right) -- (#1.left); - \path[white hash] (#1-old.right) rectangle (#1.left); - } - - \foreach \nodename in {R,Nr,Nr,Ibiiieait,Ibit,Niftp,Tci}{ - \hashband{\nodename} - } - - \end{sankeydiagram} -\end{tikzpicture} -\end{filecontents*} -% -\lstinputlisting[numbers=left,style=LaTeXsmall]{\samplecodename} -% -\begin{figure} - \centering - \input{\samplecodename} - \caption{Very nice example -- Nadieh Bremer's creation} - (from - \href{https://www.visualcinnamon.com/portfolio/adyen-report-2019/}{Adyen's - Shareholder Report}) - \label{fig:nice-example} -\end{figure} -\end{document} - -%%% Local Variables: -%%% mode: latex -%%% TeX-master: t -%%% End: diff --git a/Master/texmf-dist/doc/latex/sankey/sankey-example-energy.tex b/Master/texmf-dist/doc/latex/sankey/sankey-example-energy.tex new file mode 100644 index 00000000000..2e500b10d93 --- /dev/null +++ b/Master/texmf-dist/doc/latex/sankey/sankey-example-energy.tex @@ -0,0 +1,129 @@ +\begin{tikzpicture} + % font choice + \renewcommand\rmdefault{txr}\rmfamily\footnotesize + \sisetup{ + round-mode=places, + round-precision=1, + add-decimal-zero, + round-integer-to-decimal, + } + \begin{sankeydiagram} + \colorlet{energy}{blue!30!cyan!80!black} + \colorlet{lost energy}{red!50!orange!90!black} + \sankeyset{ + ratio=13em/100, + minimum radius=1em, + start style=simple,end style=simple, + draw/.style={draw=none,line width=0}, + energy/.style={ + fill/.style={ + draw=energy, + line width=0, + fill=energy, + } + }, + lost energy/.style={ + fill/.style={ + draw=lost energy, + line width=0, + fill=lost energy, + } + } + } + + \newcommand\abovelabel[2]{ % valname, label + \node[anchor=south east,align=center,inner xsep=0] at (#1.left) {#2}; + } + + \newcommand\energylabel[1]{ % valname + \node[anchor=north east,text=energy,inner xsep=0] at (#1.right) + {\num{\sankeygetnodeqty{#1}}}; + } + + \newcommand\lostenergylabel[2]{ % valname, label + \node[anchor=north,text=lost energy] at ([yshift=-2.5mm]#1.center) + (value) + {\num{\sankeygetnodeqty{#1}}}; + \node[anchor=north,inner sep=0,align=center] at (value.south) {#2}; + } + + \newcommand\lostenergylabelbottom[2]{ % valname, label + \draw[draw=lost energy,dashed,thick] + ([yshift=-3mm]#1.center) coordinate (#1) -- ([yshift=-3mm]#1.center); + \lostenergylabel{#1}{#2} + } + + \sankeynode{name=Co,quantity=100.0} + \path (Co.right) ++(0,-7mm) coordinate (c); + + \newcommand\turnandstop[2]{ % valname, label + \begingroup + \sankeyset{lost energy} + \sankeyturnright{#1}{90} + \sankeynode{as=#1,name=#1-stop,at={#1 |- c}} + \sankeyoutin{#1}{#1-stop} + \sankeynode{as=#1-stop,name=#1} + \sankeyend{#1} + \lostenergylabel{#1}{#2} + \endgroup + } + + \newcommand\turnandstopbottom[2]{ % valname, label + \begingroup + \sankeyset{lost energy} + \sankeyturnright{#1}{90} + \sankeynode{as=#1,name=#1-stop,at={#1 |- c}} + \sankeyoutin{#1}{#1-stop} + \sankeynode{as=#1-stop,name=#1} + \sankeyend{#1} + \lostenergylabelbottom{#1}{#2} + \endgroup + } + + \def\hshift{6.25em} + + \sankeyadvance[energy]{Co}{1.2*\hshift} + \abovelabel{Co}{\textbf{Coal}\\(Primary energy)} + \energylabel{Co} + \sankeyfork{Co}{35/El1,65/Pg} + \turnandstop{Pg}{Power generation} + + \sankeyadvance[energy]{El1}{1.8*\hshift} + \abovelabel{El1}{\textbf{Electricity}\\(Secondary energy)} + \energylabel{El1} + \sankeyfork{El1}{33.5/El2,1.5/Tr} + \turnandstopbottom{Tr}{Transmission} + + \sankeyadvance[energy]{El2}{.65*\hshift} + \energylabel{El2} + \sankeyfork{El2}{31.5/El3,2.0/Di} + \turnandstop{Di}{Distribution} + + \sankeyadvance[energy]{El3}{.65*\hshift} + \energylabel{El3} + \sankeyfork{El3}{31.0/El4,0.5/Wi} + \turnandstopbottom{Wi}{Wiring} + + \sankeyadvance[energy]{El4}{.65*\hshift} + \abovelabel{El4}{\textbf{Electricity}\\(Final energy)} + \energylabel{El4} + \sankeyfork{El4}{3.0/Lr1,28.0/Lb} + \turnandstop{Lb}{Lightbulb} + + \sankeyadvance[energy]{Lr1}{1.1*\hshift} + \abovelabel{Lr1}{\textbf{Light radiation}\\(Useful energy)} + \energylabel{Lr1} + \sankeyfork{Lr1}{2.0/Lr2,1.0/Ls} + \turnandstopbottom{Ls}{Lampshade} + + \sankeyadvance[energy]{Lr2}{.6*\hshift} + \energylabel{Lr2} + \sankeyfork{Lr2}{1.0/Il,1.0/Id} + \turnandstop{Id}{Idle} + + \sankeyadvance[energy]{Il}{.6*\hshift} + \abovelabel{Il}{\textbf{Illumination}\\(Energy services)} + \energylabel{Il} + \sankeyend[energy]{Il} + \end{sankeydiagram} +\end{tikzpicture} diff --git a/Master/texmf-dist/doc/latex/sankey/sankey-example1.tex b/Master/texmf-dist/doc/latex/sankey/sankey-example1.tex new file mode 100644 index 00000000000..bdeebbb876a --- /dev/null +++ b/Master/texmf-dist/doc/latex/sankey/sankey-example1.tex @@ -0,0 +1,73 @@ +\begin{tikzpicture} + \begin{sankeydiagram}%[debug] + \colorlet{cold}[rgb]{cyan!75!blue!50!white} + \colorlet{hot}[rgb]{red!50!orange!75!white} + \sankeyset{ + ratio=90pt/6,minimum radius=15pt, + start style=simple,end style=simple, + draw/.style={ + draw=blue!50!cyan, + line width=1pt,line cap=round,line join=round, + }, + cold/.style={ + fill/.style={ + draw=cold,line width=0pt,fill=cold, + }, + }, + cold to hot/.style={ + fill/.style={ + fill=none,top color=cold, + bottom color=hot,middle color=yellow, + }, + }, + hot/.style={ + fill/.style={ + draw=hot,line width=0pt,fill=hot, + }, + }, + } + + \sankeyset{cold} + \sankeynodestart{name=p0,at={100,0},angle=-90,quantity=6} + \sankeyadvance{p0}{50pt} + \sankeyfork{p0}{3/p1,3/p2} + \sankeyturnleft{p1}{90} + \sankeyadvance{p1}{20pt} + \sankeyadvance{p2}{60pt} + \sankeyfork{p2}{2/p3,1/p4} + \sankeyturnleft{p3}{90} + \sankeyadvance{p3}{50pt} + \sankeyfork{p3}{1/p5,1/p6} + \sankeyadvance{p5}{70pt} + \sankeyfork{p1}{1/p7,1/p8,1/p9} + \sankeyadvance{p7}{50pt} + \sankeyadvance{p9}{50pt} + \sankeyadvance{p4}{40pt} + \sankeyturnleft{p4}{90} + \sankeyadvance{p4}{65pt} + \sankeyadvance{p7}{40pt} + \sankeynode{ + name=p11,at={[shift={(50pt,-15pt)}]p7},quantity=3, + forked={1/p7a,1/p9a,1/p5a}, + } + \sankeyoutin{p7}{p7a} + \sankeyoutin{p9}{p9a} + \sankeyoutin{p5}{p5a} + \sankeyadvance{p11}{30pt} + \sankeyend{p11} + \sankeyturnright{p8}{90} + \sankeyturnright{p6}{90} + \sankeyturnright{p4}{90} + \sankeyset{hot} + \sankeyadvance[cold to hot]{p8}{40pt} + \sankeynode{ + name=p10,at={[shift={(-15pt,-60pt)}]p8},angle=-90,quantity=3, + forked={1/p8a,1/p6a,1/p4a}, + } + \sankeyoutin[cold to hot]{p4}{p4a} + \sankeyoutin[cold to hot]{p6}{p6a} + \sankeyoutin{p8}{p8a} + \sankeyadvance{p10}{30pt} + \sankeyend{p10} + \end{sankeydiagram} +\end{tikzpicture} diff --git a/Master/texmf-dist/doc/latex/sankey/sankey-example2.tex b/Master/texmf-dist/doc/latex/sankey/sankey-example2.tex new file mode 100644 index 00000000000..b0d06b73a93 --- /dev/null +++ b/Master/texmf-dist/doc/latex/sankey/sankey-example2.tex @@ -0,0 +1,188 @@ +\begin{tikzpicture} + \renewcommand*\sfdefault{txss} + + \begin{sankeydiagram}%[debug] + \sankeyset{ + ratio=4cm/524.3, + minimum radius=3mm, + start style=arrow, + end style=arrow, + fill/.style={ + line width=0pt, + fill=cyan!50!blue!50!black, + draw=cyan!50!blue!50!black, + }, + draw/.style={draw=none}, + every node/.style={angle=-90}, + } + + \sankeynodestart{name=B,at={-.5,0},quantity=7.2} + \coordinate[below=1mm of B.center] (B label); + \sankeyadvance{B}{5mm} + \sankeynodestart{name=GI,at={1,0},quantity=137.3} + \coordinate[below=1mm of GI.center] (GI label); + \sankeyadvance{GI}{5mm} + \sankeynodestart{name=I,at={4,0},quantity=397.8} + \coordinate[below=1mm of I.center] (I label); + \sankeynode{ + name=EI,at={2.86,-3},quantity=542.3, + forked={397.8/Ia,137.3/GIa,7.2/Ba} + } + \sankeydubins[minimum radius=1.2cm]{I}{Ia} + \sankeyoutin{GI}{GIa} + \sankeyoutin{B}{Ba} + \sankeyadvance{EI}{5mm} + \coordinate (EI label) at (EI); + \sankeyadvance{EI}{5mm} + \sankeyfork{EI}{63.1/EB,479.2/P} + + \sankeyturnleft{EB}{90} + \sankeyadvance{EB}{4cm} + \coordinate (EB label) at ($(EB)!.5!(EB-old)$); + \sankeyend{EB} + + \sankeyadvance{P}{10mm} + \coordinate (P label) at (P); + \sankeyadvance{P}{5mm} + + \sankeyfork{P}{33.5/NV,445.7/P-NV} + + { + \colorlet{NV color}{cyan!80!lime!50!gray} + \sankeyset{fill/.append style={fill=NV color,draw=NV color}} + \sankeyturnleft{NV}{90} + \sankeynode{as=NV,name=NV2,at=NV -| EB} + \sankeyoutin{NV}{NV2} + \coordinate (NV label) at (NV -| EB label); + \sankeyend{NV2} + } + + \sankeyadvance{P-NV}{10mm} + \sankeyfork{P-NV}{118.1/U,327.6/P-NV-U} + + { + \sankeyset{ + fill/.style={fill=orange!70!gray!50,draw=orange!70!gray!50} + } + \sankeyturnleft{U}{90} + \sankeynode{as=U,name=U2,at=U -| EB} + \sankeyoutin{U}{U2} + \coordinate (U label) at (U -| EB label); + \sankeyend{U2} + } + + \sankeyadvance{P-NV-U}{10mm} + \sankeyfork{P-NV-U}{327.2/P-NV-U-SD,0.4/SD} + + { + \sankeyturnright{SD}{90} + \sankeyadvance{SD}{15mm} + \coordinate (SD label) at (SD); + \sankeyadvance{SD}{15mm} + \sankeyend{SD} + } + + \sankeyadvance{P-NV-U-SD}{8mm} + \sankeyfork{P-NV-U-SD}{18.8/VE,308.4/E} + + { + \sankeyset{fill/.append style={orange!70!gray!30}} + \sankeyturnleft{VE}{90} + \sankeynode{as=VE,name=VE2,at=VE -| EB} + \sankeyoutin{VE}{VE2} + \coordinate (VE label) at (VE -| EB label); + \sankeyend{VE2} + } + + \sankeyadvance{E}{8mm} + \coordinate (E label) at (E); + \sankeyadvance{E}{20mm} + \sankeyfork{E}{135.1/H+GHD,87.2/V,86.1/In} + + \sankeyturnright{In}{90} + \sankeyadvance{In}{10mm} + \sankeyturnleft{In}{90} + \sankeyadvance{In}{5mm} + \coordinate (In label) at (In); + \sankeyadvance{In}{10mm} + \sankeyend{In} + + \sankeynode{as=V,name=V2,at=V|-In label} + \sankeyoutin{V}{V2} + \coordinate (V label) at (V2); + \sankeyadvance{V2}{10mm} + \sankeyend{V2} + + \sankeyturnleft{H+GHD}{90} + \sankeyadvance{H+GHD}{5mm} + \sankeyfork{H+GHD}{47.0/GHD,88.1/H} + + \sankeyturnright{H}{90} + \sankeynode{as=H,name=H2,at=H|-In label} + \sankeyoutin{H}{H2} + \coordinate (H label) at (H2); + \sankeyadvance{H2}{10mm} + \sankeyend{H2} + + \sankeyadvance{GHD}{30mm} + \sankeyturnright{GHD}{90} + \sankeynode{as=GHD,name=GHD2,at=GHD|-In label} + \sankeyoutin{GHD}{GHD2} + \coordinate (GHD label) at (GHD2); + \sankeyadvance{GHD2}{10mm} + \sankeyend{GHD2} + \end{sankeydiagram} + + % labels + \tikzset{ + label/.style={ + fill=white,fill opacity=.8,text opacity=1, + inner sep=1mm, + text=cyan!50!blue!50!black, + inner xsep=2mm, + font=\sffamily\bfseries\footnotesize, + align=center, + }, + } + \node[label,anchor=north] (B label) at (B label) {7.2}; + \node[label,left=1mm of B label] {Bestands-\\entnahme}; + \node[label,anchor=north] at (GI label) {137.3}; + \node[label,above=5mm of GI label] {Gewinnung\\im Inland}; + \node[label,anchor=north] at (I label) {397.8}; + \node[label,above=5mm of I label] {Import}; + + \node[label] at (EI label) {542.3\\Energieaufkommen im Inland}; + + \node[label,anchor=center] (EB label) at (EB label) {63.1}; + \node[label,above=1mm of EB label] {Export und\\Bunkerung}; + + \node[label] at (P label) {479.2\\Primärenergieverbrauch}; + + \node[label,anchor=center] (NV label) at (NV label) {33.5}; + \node[label,above=0mm of NV label] {Nichtenergetischer Verbrauch}; + + \node[label,anchor=center] (U label) at (U label) {118.1}; + \node[label,below=3mm of U label] {Umwandlungsverluste}; + + \node[label,anchor=center] (SD label) at (SD label) {0.4}; + \node[label,above=0mm of SD label] {Statistische\\Differenzen}; + + \node[label,anchor=center] (VE label) at (VE label) {18.8}; + \node[label,below=0mm of VE label] {Verbrauch in den\\Energiesktoren}; + + \node[label,anchor=north] (E label) at (E label) + {308.4\\Endenergieverbrauch}; + + \node[label,anchor=north] (In label) at (In label) {86.1}; + \node[label,anchor=north,below=1cm of In label] {Industrie}; + + \node[label,anchor=north] (V label) at (V label) {87.2}; + \node[label,anchor=north,below=1cm of V label] {Verkehr}; + + \node[label,anchor=north] (H label) at (H label) {88.1}; + \node[label,anchor=north,below=1cm of H label] {Haushalte}; + + \node[label,anchor=north] (GHD label) at (GHD label) {47.0}; + \node[label,anchor=north,below=1cm of GHD label] + {Gewerbe, Handel\\Diensleistungen}; +\end{tikzpicture} diff --git a/Master/texmf-dist/doc/latex/sankey/sankey-example3-variation.tex b/Master/texmf-dist/doc/latex/sankey/sankey-example3-variation.tex new file mode 100644 index 00000000000..b1f8c3d99d0 --- /dev/null +++ b/Master/texmf-dist/doc/latex/sankey/sankey-example3-variation.tex @@ -0,0 +1,149 @@ +\begin{tikzpicture}[rotate=-90] + \begin{sankeydiagram}[rotate=-90] + \sffamily + \sankeyset{ + ratio=1.7cm/10, + outin steps=2, + start style=arrow, + end style=simple, + draw/.style={draw=white,line width=.4pt}, + color/.style={fill/.style={fill=#1,fill opacity=.75}}, + shade/.style 2 args={fill/.style={ + fill=none,line width=0, + top color=#1,bottom color=#2, + middle color=#1!50!#2!50!white, + fill opacity=.75}}, + % colors + @define HTML color/.code args={#1/#2}{\definecolor{#1}{HTML}{#2}}, + @define HTML color/.list={ + cyan/a6cee3,lime/b2df8a,red/fb9a99,orange/fdbf6f, + violet/cab2d6,yellow/ffff99,blue/1f78b4,green/33a02c + }, + % colors of countries + @let country color/.code args={#1/#2}{\colorlet{#1}[rgb]{#2}}, + @let country color/.list={ + CA/red,US/orange,MX/lime,BR/violet,FR/yellow,GB/blue, + SP/green,PT/cyan,ML/cyan,SN/red,MA/orange, + AO/violet,ZA/lime,IN/blue,JP/yellow,CN/green + }, + } + \def\vdist{5mm} + \def\hwidth{1em} + \def\hdist{6cm} + + \sankeynode{name=CA,quantity=7} + \sankeynode{name=US,quantity=8,at={[yshift=\vdist]CA.left},anchor=right} + \sankeynode{name=MX,quantity=8,at={[yshift=\vdist]US.left},anchor=right} + \sankeynode{name=BR,quantity=8,at={[yshift=\vdist]MX.left},anchor=right} + + \foreach \country in {CA,US,MX,BR}{ + \sankeystart[color=\country]{\country} + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \sankeyfork{CA}{1/CA-to-PT,1/CA-to-GB,5/CA-to-FR} + \sankeyfork{US}{1/US-to-PT,1/US-to-SP,5/US-to-GB,1/US-to-FR} + \sankeyfork{MX}{1/MX-to-PT,5/MX-to-SP,1/MX-to-GB,1/MX-to-FR} + \sankeyfork{BR}{5/BR-to-PT,1/BR-to-SP,1/BR-to-GB,1/BR-to-FR} + + \sankeynode{name=FR,quantity=11, + at={[xshift=\hdist]CA.right},anchor=right} + \sankeynode{name=GB,quantity=11, + at={[yshift=\vdist]FR.left},anchor=right} + \sankeynode{name=SP,quantity=7, + at={[yshift=\vdist]GB.left},anchor=right} + \sankeynode{name=PT,quantity=8, + at={[yshift=\vdist]SP.left},anchor=right} + + \sankeyfork{FR} + {1/FR-from-BR,1/FR-from-MX,1/FR-from-US,5/FR-from-CA,3/FR-from-00} + \sankeyfork{GB} + {1/GB-from-BR,1/GB-from-MX,5/GB-from-US,1/GB-from-CA,3/GB-from-00} + \sankeyfork{SP}{1/SP-from-BR,5/SP-from-MX,1/SP-from-US} + \sankeyfork{PT}{5/PT-from-BR,1/PT-from-MX,1/PT-from-US,1/PT-from-CA} + + \foreach \country in {FR,GB,SP,PT}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \sankeyfork{FR}{1/FR-to-ZA,1/FR-to-AO,3/FR-to-MA,3/FR-to-SN,3/FR-to-ML} + \sankeyfork{GB}{7/GB-to-ZA,1/GB-to-AO,2/GB-to-MA,1/GB-to-SN} + \sankeyfork{SP}{1/SP-to-ZA,3/SP-to-MA,1/SP-to-SN,2/SP-to-00} + \sankeyfork{PT}{3/PT-to-ZA,2/PT-to-AO,1/PT-to-MA,1/PT-to-SN,1/PT-to-00} + + \sankeynode{name=ML,quantity=9, + at={[xshift=\hdist]FR.right},anchor=right} + \sankeynode{name=SN,quantity=9, + at={[yshift=\vdist]ML.left},anchor=right} + \sankeynode{name=MA,quantity=9, + at={[yshift=\vdist]SN.left},anchor=right} + \sankeynode{name=AO,quantity=9, + at={[yshift=\vdist]MA.left},anchor=right} + \sankeynode{name=ZA,quantity=12, + at={[yshift=\vdist]AO.left},anchor=right} + + \sankeyfork{ML}{3/ML-from-FR,6/Mail-from-00} + \sankeyfork{SN} + {1/SN-from-PT,1/SN-from-SP,1/SN-from-GB,3/SN-from-FR,3/SN-from-00} + \sankeyfork{MA}{1/MA-from-PT,3/MA-from-SP,2/MA-from-GB,3/MA-from-FR} + \sankeyfork{AO}{2/AO-from-PT,1/AO-from-GB,1/AO-from-FR,5/AO-from-00} + \sankeyfork{ZA}{3/ZA-from-PT,1/ZA-from-SP,7/ZA-from-GB,1/ZA-from-FR} + + \foreach \country in {ML,SN,MA,AO,ZA}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \sankeyfork{ML}{5/ML-to-CN,3/ML-to-JP,1/ML-to-IN} + \sankeyfork{SN}{5/SN-to-CN,3/SN-to-JP,1/SN-to-IN} + \sankeyfork{MA}{5/MA-to-CN,3/MA-to-JP,1/MA-to-IN} + \sankeyfork{AO}{5/AO-to-CN,3/AO-to-JP,1/AO-to-IN} + \sankeyfork{ZA}{5/ZA-to-CN,3/ZA-to-JP,1/ZA-to-IN,3/ZA-to-00} + + \sankeynode{name=IN,quantity=5, + at={[xshift=\hdist]ML.right},anchor=right} + \sankeynode{name=JP,quantity=15, + at={[yshift=\vdist]IN.left},anchor=right} + \sankeynode{name=CN,quantity=25, + at={[yshift=\vdist]JP.left},anchor=right} + + \sankeyfork{IN} + {1/IN-from-ZA,1/IN-from-AO,1/IN-from-MA,1/IN-from-SN,1/IN-from-ML} + \sankeyfork{JP} + {3/JP-from-ZA,3/JP-from-AO,3/JP-from-MA,3/JP-from-SN,3/JP-from-ML} + \sankeyfork{CN} + {5/CN-from-ZA,5/CN-from-AO,5/CN-from-MA,5/CN-from-SN,5/CN-from-ML} + + \foreach \country in {IN,JP,CN}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + \sankeyend[color=\country]{\country} + } + + \foreach \startcountry/\countries in { + CA/{PT,GB,FR}, US/{PT,SP,GB,FR}, MX/{PT,SP,GB,FR}, + BR/{PT,SP,GB,FR}, FR/{ML,SN,MA,AO,ZA}, GB/{SN,MA,AO,ZA}, + SP/{SN,MA,ZA}, PT/{SN,MA,AO,ZA}, ML/{IN,JP,CN}, + SN/{IN,JP,CN}, MA/{IN,JP,CN}, AO/{IN,JP,CN}, + ZA/{IN,JP,CN}} + { + \foreach \endcountry in \countries { + \sankeyoutin[shade={\startcountry}{\endcountry}] + {\startcountry-to-\endcountry}{\endcountry-from-\startcountry} + } + } + + \foreach \country/\countryname in {CA/Canada, US/USA, MX/Mexico, + BR/Brazil, FR/France, GB/England, SP/Spain, PT/Portugal} + { + \node[anchor=south,inner sep=.1em,font=\small] + at (\country) {\countryname\vphantom{Ag}}; + } + + \foreach \country/\countryname in { + ML/Mali, SN/Senegal, MA/Morocco, AO/Angola, + ZA/South Africa, IN/India, JP/Japan, CN/China} + { + \node[anchor=south,inner sep=.1em,font=\small] + at (\country) {\countryname\vphantom{Ag}}; + } + \end{sankeydiagram} +\end{tikzpicture} diff --git a/Master/texmf-dist/doc/latex/sankey/sankey-example3.tex b/Master/texmf-dist/doc/latex/sankey/sankey-example3.tex new file mode 100644 index 00000000000..06ea9b59cac --- /dev/null +++ b/Master/texmf-dist/doc/latex/sankey/sankey-example3.tex @@ -0,0 +1,142 @@ +\begin{tikzpicture} + \begin{sankeydiagram}%[debug] + \sffamily + \sankeyset{ + ratio=1cm/10, + outin steps=2, + draw/.style={draw=none,line width=0pt}, + color/.style={fill/.style={fill=#1,fill opacity=.75}}, + shade/.style 2 args={fill/.style={left color=#1, + right color=#2,fill opacity=.5}}, + % colors + @define HTML color/.code args={#1/#2}{\definecolor{#1}{HTML}{#2}}, + @define HTML color/.list={ + cyan/a6cee3,lime/b2df8a,red/fb9a99,orange/fdbf6f, + violet/cab2d6,yellow/ffff99,blue/1f78b4,green/33a02c + }, + % colors of countries + @let country color/.code args={#1/#2}{\colorlet{#1}[rgb]{#2}}, + @let country color/.list={ + CA/red,US/orange,MX/orange,BR/cyan,FR/lime,GB/red, + SP/lime,PT/cyan,ML/blue,SN/violet,MA/yellow, + AO/violet,ZA/yellow,IN/green,JP/green,CN/blue + }, + } + \def\vdist{5mm} + \def\hwidth{.5em} + \def\hdist{4.1cm} + + \sankeynode{name=CA,quantity=7} + \sankeynode{name=US,quantity=8,at={[yshift=\vdist]CA.left},anchor=right} + \sankeynode{name=MX,quantity=8,at={[yshift=\vdist]US.left},anchor=right} + \sankeynode{name=BR,quantity=8,at={[yshift=\vdist]MX.left},anchor=right} + + \foreach \country in {CA,US,MX,BR}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \sankeyfork{CA}{1/CA-to-PT,1/CA-to-GB,5/CA-to-FR} + \sankeyfork{US}{1/US-to-PT,1/US-to-SP,5/US-to-GB,1/US-to-FR} + \sankeyfork{MX}{1/MX-to-PT,5/MX-to-SP,1/MX-to-GB,1/MX-to-FR} + \sankeyfork{BR}{5/BR-to-PT,1/BR-to-SP,1/BR-to-GB,1/BR-to-FR} + + \sankeynode{name=FR,quantity=11, + at={[xshift=\hdist]CA.right},anchor=right} + \sankeynode{name=GB,quantity=11, + at={[yshift=\vdist]FR.left},anchor=right} + \sankeynode{name=SP,quantity=7, + at={[yshift=\vdist]GB.left},anchor=right} + \sankeynode{name=PT,quantity=8, + at={[yshift=\vdist]SP.left},anchor=right} + + \sankeyfork{FR} + {1/FR-from-BR,1/FR-from-MX,1/FR-from-US,5/FR-from-CA,3/FR-from-00} + \sankeyfork{GB} + {1/GB-from-BR,1/GB-from-MX,5/GB-from-US,1/GB-from-CA,3/GB-from-00} + \sankeyfork{SP}{1/SP-from-BR,5/SP-from-MX,1/SP-from-US} + \sankeyfork{PT}{5/PT-from-BR,1/PT-from-MX,1/PT-from-US,1/PT-from-CA} + + \foreach \country in {FR,GB,SP,PT}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \sankeyfork{FR}{1/FR-to-ZA,1/FR-to-AO,3/FR-to-MA,3/FR-to-SN,3/FR-to-ML} + \sankeyfork{GB}{7/GB-to-ZA,1/GB-to-AO,2/GB-to-MA,1/GB-to-SN} + \sankeyfork{SP}{1/SP-to-ZA,3/SP-to-MA,1/SP-to-SN,2/SP-to-00} + \sankeyfork{PT}{3/PT-to-ZA,2/PT-to-AO,1/PT-to-MA,1/PT-to-SN,1/PT-to-00} + + \sankeynode{name=ML,quantity=9, + at={[xshift=\hdist]FR.right},anchor=right} + \sankeynode{name=SN,quantity=9, + at={[yshift=\vdist]ML.left},anchor=right} + \sankeynode{name=MA,quantity=9, + at={[yshift=\vdist]SN.left},anchor=right} + \sankeynode{name=AO,quantity=9, + at={[yshift=\vdist]MA.left},anchor=right} + \sankeynode{name=ZA,quantity=12, + at={[yshift=\vdist]AO.left},anchor=right} + + \sankeyfork{ML}{3/ML-from-FR,6/Mail-from-00} + \sankeyfork{SN} + {1/SN-from-PT,1/SN-from-SP,1/SN-from-GB,3/SN-from-FR,3/SN-from-00} + \sankeyfork{MA}{1/MA-from-PT,3/MA-from-SP,2/MA-from-GB,3/MA-from-FR} + \sankeyfork{AO}{2/AO-from-PT,1/AO-from-GB,1/AO-from-FR,5/AO-from-00} + \sankeyfork{ZA}{3/ZA-from-PT,1/ZA-from-SP,7/ZA-from-GB,1/ZA-from-FR} + + \foreach \country in {ML,SN,MA,AO,ZA}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \sankeyfork{ML}{5/ML-to-CN,3/ML-to-JP,1/ML-to-IN} + \sankeyfork{SN}{5/SN-to-CN,3/SN-to-JP,1/SN-to-IN} + \sankeyfork{MA}{5/MA-to-CN,3/MA-to-JP,1/MA-to-IN} + \sankeyfork{AO}{5/AO-to-CN,3/AO-to-JP,1/AO-to-IN} + \sankeyfork{ZA}{5/ZA-to-CN,3/ZA-to-JP,1/ZA-to-IN,3/ZA-to-00} + + \sankeynode{name=IN,quantity=5, + at={[xshift=\hdist]ML.right},anchor=right} + \sankeynode{name=JP,quantity=15, + at={[yshift=\vdist]IN.left},anchor=right} + \sankeynode{name=CN,quantity=25, + at={[yshift=\vdist]JP.left},anchor=right} + + \sankeyfork{IN} + {1/IN-from-ZA,1/IN-from-AO,1/IN-from-MA,1/IN-from-SN,1/IN-from-ML} + \sankeyfork{JP} + {3/JP-from-ZA,3/JP-from-AO,3/JP-from-MA,3/JP-from-SN,3/JP-from-ML} + \sankeyfork{CN} + {5/CN-from-ZA,5/CN-from-AO,5/CN-from-MA,5/CN-from-SN,5/CN-from-ML} + + \foreach \country in {IN,JP,CN}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \foreach \startcountry/\countries in { + CA/{PT,GB,FR}, US/{PT,SP,GB,FR}, MX/{PT,SP,GB,FR}, + BR/{PT,SP,GB,FR}, FR/{ML,SN,MA,AO,ZA}, GB/{SN,MA,AO,ZA}, + SP/{SN,MA,ZA}, PT/{SN,MA,AO,ZA}, ML/{IN,JP,CN}, + SN/{IN,JP,CN}, MA/{IN,JP,CN}, AO/{IN,JP,CN}, + ZA/{IN,JP,CN}} + { + \foreach \endcountry in \countries { + \sankeyoutin[shade={\startcountry}{\endcountry}] + {\startcountry-to-\endcountry}{\endcountry-from-\startcountry} + } + } + + \foreach \country/\countryname in {CA/Canada, US/USA, MX/Mexico, + BR/Brazil, FR/France, GB/England, SP/Spain, PT/Portugal} + { + \node[anchor=west,inner sep=.1em,font=\small] + at (\country) {\countryname\vphantom{Ag}}; + } + + \foreach \country/\countryname in { + ML/Mali, SN/Senegal, MA/Morocco, AO/Angola, + ZA/South Africa, IN/India, JP/Japan, CN/China} + { + \node[anchor=east,inner sep=.1em,font=\small] + at (\country-old) {\countryname\vphantom{Ag}}; + } + \end{sankeydiagram} +\end{tikzpicture} diff --git a/Master/texmf-dist/doc/latex/sankey/sankey-example4.tex b/Master/texmf-dist/doc/latex/sankey/sankey-example4.tex new file mode 100644 index 00000000000..7b5e17e20fa --- /dev/null +++ b/Master/texmf-dist/doc/latex/sankey/sankey-example4.tex @@ -0,0 +1,242 @@ +\begin{tikzpicture} + \renewcommand*\sfdefault{txss} + \sffamily + \sisetup{ + detect-all=true, + group-separator={,}, + group-minimum-digits=4, + } + % storage of labels + \newcommand\LabSet[2]{% node name, label + \expandafter\edef\csname#1@Lab\endcsname{#2}} + \newcommand\Lab[1]{% node name + \csname#1@Lab\endcsname} + % storage of quantities + \newcommand\QtySet[2]{% node name, quantity + \expandafter\edef\csname#1@Qty\endcsname{\fpeval{#2}}} + \newcommand\Qty[1]{% node name + \csname#1@Qty\endcsname} + % all nodes with their name, label and quantity + \sankeyset{ + def data/.code args={#1/#2/#3}{% node name/label/values + \LabSet{#1}{#2} + \QtySet{#1}{#3} + \typeout{#1: \Qty{#1}€ (\Lab{#1})} + }, + def data/.list={ + {Pf/Processing\\fees/71713}, + {Sog/Sales of\\good/4547}, + {Sf/Settlement\\fees/842075}, + {Os/Other\\services/37532}, + {R/Revenues/\Qty{Pf}+\Qty{Sog}+\Qty{Sf}+\Qty{Os}}, + {Coi/Cost of Inventory/5151}, + {Ciffi/Cost insecure from financial institutions/758234}, + {Nr/Net revenue/\Qty{R}-\Qty{Coi}-\Qty{Ciffi}}, + {Aadotaifa/Amortization and\\depreciation of tangible and\\ + intangible fixed assets/4688}, + {Ssapc/Social securities and\\pension costs/7860}, + {Was/Wages and salaries/35627}, + {Ooe/Other operating expenses/37346}, + {Nr2/-/\Qty{Nr}-\Qty{Aadotaifa}-\Qty{Ssapc}-\Qty{Was}-\Qty{Ooe}}, + {Oi/Other income/47}, + {Ibiiieait/Income before interest income,\\interest expense and + income taxes/\Qty{Nr2}+\Qty{Oi}}, + {Fe/Finance expense/561}, + {Ofr/Other financial results/2533}, + {Ibiiieait2/-/\Qty{Ibiiieait}-\Qty{Fe}-\Qty{Ofr}}, + {Fi/Finance income/204}, + {Ibit/Income before income taxes/\Qty{Ibiiieait2}+\Qty{Fi}}, + {It/Income taxes/21134}, + {Niftp/Net income for the period/\Qty{Ibit}-\Qty{It}}, + {Octa/Other currency\\translation adjustments/785}, + {Tci/Total comprehensive income/\Qty{Niftp}+\Qty{Octa}} + }, + } + + \definecolor{mygreen}{RGB}{9,192,82} + \tikzset{ + cost node/.style={ + overlay, + align=flush center, + node font=\footnotesize\sffamily\bfseries, + inner sep=0, + node contents={% + {\mdseries€\,\num{\Qty{#1}}}\\ + \Lab{#1}\vphantom{g}% + }, + }, + white hash/.style={ + draw=none,fill=none, + pattern={Lines[angle=60,line width=2pt,distance=4pt]}, + pattern color=white, + }, + line sep/.style={draw=white,line width=1pt}, + left label/.style={left=#1,align=flush right,anchor=north east}, + right label/.style={right=#1,align=flush left}, + right label hashed/.style={ + right=1mm of $(#1.left)!.5!(#1-old.left)$,align=flush left, + }, + left label hashed/.style={ + left=1mm of $(#1.right)!.5!(#1-old.right)$,align=flush right, + }, + } + + \newcommand\turnandstop[1]{ + \sankeyturn[green to greenwhite]{#1}{-90} + \sankeynode{as=#1,name=#1-e,at={#1 -| Coi}} + \sankeyoutin[greenwhite to white]{#1}{#1-e} + \node[cost node=#1,left label={1mm of #1-e.right}]; + } + + \begin{sankeydiagram}%[debug] + \sankeyset{ + ratio=28em/1000000, + minimum radius=2cm, + start style=none, + every node/.style={angle=-90}, + % default fill and draw styles + fill/.style={ + line width=0pt, + fill=mygreen, + }, + draw/.style={draw=none}, + % specific fill and draw styles + green to greenwhite/.style={ + fill/.style={ + line width=0pt, + right color=mygreen, + left color=mygreen!20!white, + } + }, + greenwhite to white/.style={ + fill/.style={ + line width=0pt, + right color=mygreen!20!white, + left color=mygreen!5!white, + } + }, + dashed/.style={draw/.style={draw=mygreen,dashed}}, + } + + \coordinate (top) at (0,2em); + + \sankeynodestart{name=Pf,quantity=\Qty{Pf}} + \node[cost node=Pf,above=.5em of Pf.center]; + + \sankeynodestart{name=Sog,quantity=\Qty{Sog}, + at={[xshift=4em]Pf.left},anchor=right} + \node[cost node=Sog,above=.5em of Sog.center]; + + \sankeynodestart{name=Sf,quantity=\Qty{Sf}, + at={[xshift=2em]Sog.left},anchor=right} + \node[cost node=Sf,above=.5em of Sf.center]; + + \sankeynodestart{name=Os,quantity=\Qty{Os}, + at={[xshift=2em]Sf.left},anchor=right} + \node[cost node=Os,above=.5em of Os.center]; + + \sankeynode{ + name=R,quantity=\Qty{R},at={[yshift=-10em]Sf.center}, + forked={\Qty{Os}/Os-a,\Qty{Sf}/Sf-a,\Qty{Sog}/Sog-a,\Qty{Pf}/Pf-a}, + } + + \foreach \nodename in {Pf,Sog,Sf,Os}{ + \sankeyoutin[fill/.style={top color=white,bottom color=mygreen}] + {\nodename}{\nodename-a} + } + + \sankeyadvance{R}{1em} + \node[cost node=R,right label hashed=R]; + + \sankeyfork{R}{\Qty{Ciffi}/Ciffi,\Qty{Nr}/Nr,\Qty{Coi}/Coi} + + \sankeyturnleft[minimum radius=1.cm]{Ciffi}{90} + \node[cost node=Ciffi,at={([shift={(1mm,0)}]Ciffi.center)},rotate=-90, + anchor=south,align=flush left,node font=\scriptsize\sffamily\bfseries]; + + \sankeyturnright[green to greenwhite]{Coi}{90} + \sankeyadvance[greenwhite to white]{Coi}{1em} + \node[cost node=Coi,left={1mm of [yshift=.75ex]Coi.left}, + align=flush right,anchor=north east,overlay]; + + \sankeyadvance{Nr}{9em} + \sankeyadvance{Nr}{1em} + \node[cost node=Nr,left label hashed=Nr, + node font=\large\sffamily\bfseries]; + + \sankeyfork{Nr}{\Qty{Nr2}/Nr2,\Qty{Ooe}/Ooe, + \Qty{Was}/Was,\Qty{Ssapc}/Ssapc,\Qty{Aadotaifa}/Aadotaifa} + + \turnandstop{Aadotaifa} + + \sankeyadvance{Ssapc}{5em} + \turnandstop{Ssapc} + + \sankeyadvance{Was}{9em} + \turnandstop{Was} + + \sankeyadvance{Ooe}{12em} + \turnandstop{Ooe} + + \sankeyadvance{Nr2}{15em} + \sankeynode{name=Ibiiieait,quantity=\Qty{Ibiiieait}, + anchor=right,at={Nr2.right}, + forked={\Qty{Oi}/Oi,\Qty{Nr2}/Nr2-e}} + + \sankeyturnleftbackward[minimum radius=1cm,dashed]{Oi}{90} + \node[cost node=Oi,right label=1mm of Oi.left]; + + \sankeyadvance{Ibiiieait}{1em} + \node[cost node=Ibiiieait,right label hashed=Ibiiieait]; + + \sankeyfork{Ibiiieait} + {\Qty{Ibiiieait2}/Ibiiieait2,\Qty{Ofr}/Ofr,\Qty{Fe}/Fe} + + \turnandstop{Fe} + + \sankeyadvance{Ofr}{3em} + \turnandstop{Ofr} + + \sankeyadvance{Ibiiieait2}{6em} + \sankeynode{name=Ibit,quantity={\Qty{Ibiiieait2}+\Qty{Fi}}, + anchor=right,at={Ibiiieait2.right}, + forked={\Qty{Fi}/Fi,\Qty{Ibiiieait2}/Ibiiieait2-e}} + + \sankeyturnleftbackward[minimum radius=1cm,dashed]{Fi}{90} + \node[cost node=Fi,right label=1mm of Fi.left]; + + \sankeyadvance{Ibit}{1em} + \node[cost node=Ibit,right label hashed=Ibit]; + + \sankeyfork{Ibit}{\Qty{Niftp}/Niftp,\Qty{It}/It} + + \turnandstop{It} + + \sankeyadvance{Niftp}{6em} + + \sankeyadvance{Niftp}{1em} + \node[cost node=Niftp,right label hashed=Niftp]; + + \sankeynode{name=Tci,quantity=\Qty{Niftp}+\Qty{Octa}, + anchor=right,at={[yshift=-6em]Niftp.right}, + forked={\Qty{Octa}/Octa,\Qty{Niftp}/Niftp-e}} + \sankeyoutin{Niftp}{Niftp-e} + + \sankeyturnleftbackward[minimum radius=1cm]{Octa}{90} + \node[cost node=Octa,right label=1mm of Octa.left]; + + \sankeyadvance{Tci}{1em} + \node[cost node=Tci,right label hashed=Tci]; + + \newcommand\hashband[1]{ + \draw[line sep] (#1-old.right) -- (#1-old.left); + \draw[line sep] (#1.right) -- (#1.left); + \path[white hash] (#1-old.right) rectangle (#1.left); + } + + \foreach \nodename in {R,Nr,Nr,Ibiiieait,Ibit,Niftp,Tci}{ + \hashband{\nodename} + } + + \end{sankeydiagram} +\end{tikzpicture} diff --git a/Master/texmf-dist/doc/latex/sankey/sankey.pdf b/Master/texmf-dist/doc/latex/sankey/sankey.pdf Binary files differnew file mode 100644 index 00000000000..f1b0fbf2dfd --- /dev/null +++ b/Master/texmf-dist/doc/latex/sankey/sankey.pdf diff --git a/Master/texmf-dist/source/latex/sankey/sankey.dtx b/Master/texmf-dist/source/latex/sankey/sankey.dtx new file mode 100644 index 00000000000..451472c5b27 --- /dev/null +++ b/Master/texmf-dist/source/latex/sankey/sankey.dtx @@ -0,0 +1,4678 @@ +% \iffalse meta-comment +% +% Copyright (C) 2016, 2021 by Paul Gaborit +% ----------------------------------- +% +% This work may be distributed and/or modified under the conditions of +% the LaTeX Project Public License, either version 1.3 of this license +% or (at your option) any later version. The latest version of this +% license is in +% +% <http://www.latex-project.org/lppl.txt> +% +% and version 1.3 or later is part of all distributions of LaTeX version +% 2005/12/01 or later. +% +% This work has the LPPL maintenance status “maintained”. +% +% The Current Maintainer of this work is Paul Gaborit. +% +% This work consists of the files sankey.dtx, sankey.ins and the derived +% files sankey.sty, tikzlibrarydubins.code.tex, sankey-doc-preamble.sty, +% sankey-example1.tex, sankey-example2.tex, sankey-example3.tex, +% sankey-example3-variation.tex, sankey-example4.tex, +% sankey-example-energy.tex +% +% +% \fi +% +% \iffalse +% +%<*driver> +\documentclass[a4paper,10pt,draft]{ltxdoc} +\usepackage{sankey-doc-preamble} +\EnableCrossrefs +\CodelineIndex +\RecordChanges +\begin{document} +\DocInput{sankey.dtx} +\end{document} +%</driver> +% \fi +% +% \CharacterTable +% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +% Digits \0\1\2\3\4\5\6\7\8\9 +% Exclamation \! Double quote \" Hash (number) \# +% Dollar \$ Percent \% Ampersand \& +% Acute accent \' Left paren \( Right paren \) +% Asterisk \* Plus \+ Comma \, +% Minus \- Point \. Solidus \/ +% Colon \: Semicolon \; Less than \< +% Equals \= Greater than \> Question mark \? +% Commercial at \@ Left bracket \[ Backslash \\ +% Right bracket \] Circumflex \^ Underscore \_ +% Grave accent \` Left brace \{ Vertical bar \| +% Right brace \} Tilde \~} +% +% +% \CheckSum{1718} +% +% +% \GetFileInfo{\jobname.dtx} +% +% \DoNotIndex{\newcommand,\newenvironment} +% \DoNotIndex{\#,\$,\%,\&,\@,\\,\{,\},\^,\_,\~,\ } +% \DoNotIndex{\begingroup,\endgroup,\begin,\end} +% \DoNotIndex{\def,\edef,\gdef,\xdef,\ifx,\else,\string,\relax} +% \DoNotIndex{\csname,\endcsname,\ifcsdef,\expandafter,\ifnumgreater} +% \DoNotIndex{\NewDocumentCommand,\NewDocumentEnvironment,\IfBooleanTF} +% \DoNotIndex{\NeedsTeXFormat,\ProvidesPackage,\RequirePackage,\PackageError,\PackageWarning} +% \DoNotIndex{\newtoggle,\toggletrue,\togglefalse,\iftoggle,\ifdefempty,\ifundef,\ifdefstrequal} +% \DoNotIndex{\ifbool,\ifdef,\ifnumequal,\ifpgfmathcond,\colorlet,\fpeval,\inteval,\newbool} +% \DoNotIndex{\pgfmathsetmacro,\pgfdeclarelayer,\pgfdeclareshape,\pgfkeys,\pgfset,\usetikzlibrary} +% \DoNotIndex{\the,\pgf@x,\pgf@y,\tikz@scan@one@point,\pgfutil@firstofone} +% \DoNotIndex{\pgfsetlayers,\inheritsavedanchors,\inheritanchor,\inheritanchorborder,\anchor,\pgf@process,\northeast,\southwest} +% \DoNotIndex{\pgfmathresult,\pgfinterruptpath,\endpgfinterruptpath,\pgfkeysvalueof,\pgfmathtruncatemacro,\pgfmathparse} +% \DoNotIndex{\tikzset,\pgfextra,\pgflinewidth,\foreach,\coordinate} +% \DoNotIndex{\path,\node,\pgfmathprintnumber,\n,\p,\x,\y} +% \DoNotIndex{\tiny,\ttfamily,\space} +% +% \title{The \textsf{sankey} package\\ +% Draw Sankey diagrams via TikZ} +% +% \author{Paul Gaborit +% (\href{mailto:paul.gaborit@gmail.com}{\texttt{paul.gaborit@gmail.com}})} +% \date{\fileversion{} -- \filedate{}} +% +% \GetFileInfo{sankey.sty} +% +% \def\manualparts{ +% \begin{quote} +% This manual contains three parts: +% \nameref{usermanual} (p.\pageref{usermanual}), +% \nameref{examples} (p.\pageref{examples}) +% and \nameref{implementation} (p.\pageref{implementation}). +% \end{quote} +% } +% +% \maketitle +% +% \hypersetup{ +% pdftitle=How to use the sankey package to build Sankey diagrams (\fileversion), +% pdfauthor=Paul Gaborit, +% } +% +% +% +% \begin{abstract} +% The \texttt{sankey} package provides macros and environments to +% build \emph{Sankey +% diagrams}\footnote{\url{https://en.wikipedia.org/wiki/Sankey_diagram}}, +% i.e. \emph{flow diagrams} in which the width of the arrows is +% proportional to the flow rate. The initial idea for the first +% implementation came out from +% \href{https://tex.stackexchange.com/q/40159/14500}{this question} on +% \href{https://tex.stackexchange.com/}{TeX.StackExchange}. +% +% +% \end{abstract} +% +% \manualparts +% +% \begin{quote} +% {\footnotesize Note: the \code{sankey.dtx} and \code{sankey.ins} +% files are attachments of the current PDF document.\par} +% \end{quote} +% +%^^A % ------------------------------------------------------------ +% \part{User manual} +% \label{usermanual} +%^^A % ------------------------------------------------------------ +% +% { +% \setlength{\parskip}{0pt} +% \localtableofcontents +% } +% +%^^A % ------------------------------------------------------------ +% \section{Preamble} +%^^A % ------------------------------------------------------------ +% +% To use the \code{sankey} package, insert the following line in your preamble: +% +% \begin{lstlisting}[style=LaTeXsmall] +% \usepackage{sankey} +% \end{lstlisting} +% +% {\small Note: the +% \code{sankey} package requires automatically the +% \code{xparse}, \code{etoolbox}, \code{xfp} and +% \code{tikz} packages, and the \code{calc}, +% \code{decorations.markings} and +% \code{dubins} (cf. \vref{sec:dubins}) TikZ libraries.\par} +% +% +%^^A % ------------------------------------------------------------ +% \section{The \texttt{sankeydiagram} environment} +%^^A % ------------------------------------------------------------ +% +% \DescribeEnv{sankeydiagram} % +% A \code{sankeydiagram} environment nested in a \code{tikzpicture} +% environment activates the sankey macros: +% +% \begin{lstlisting}[style=LaTeXsmall] +% \begin{tikzpicture} +% \begin{sankeydiagram}[... options ...] +% ... sankey macros ... +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{lstlisting} +% +%^^A % ------------------------------------------------------------ +% \section{Sankey diagram options} +%^^A % ------------------------------------------------------------ +% +% The \code{sankey} package uses \code{pgfkeys} to set options via +% \emph{key=value} pairs with default path \texttt{/sankey} (and +% \texttt{/sankey/node parameters} for Sankey node parameters). +% +% The options can be defined via the optional argument of the +% \code{sankeydiagram} environment: +% +% \begin{lstlisting}[style=LaTeXsmall] +% \begin{sankeydiagram}[debug=true] +% \sankeynode{name=a,quantity=1,angle=0,at={0,0}} +% \end{sankeydiagram} +% \end{lstlisting} +% +% \DescribeMacro{\sankeyset} % +% The options can also be modified via the \code{\sankeyset} macro: +% +% \begin{lstlisting}[style=LaTeXsmall] +% \begin{sankeydiagram} +% \sankeyset{debug=true} +% \sankeynode{name=a,quantity=1,angle=0,at={0,0}} +% \end{sankeydiagram} +% \end{lstlisting} +% +% The options can be temporarily modified for a single macro: +% \begin{lstlisting}[style=LaTeXsmall] +% \begin{sankeydiagram} +% \sankeynode[debug=true]{name=a,quantity=1,angle=0,at={0,0}} +% \end{sankeydiagram} +% \end{lstlisting} +% +% At the begining of each Sankey diagram, all options are initialized +% with initial values then the \code{every diagram} style is applied. +% +% \begin{sankeyoption}{every diagram}{}{}{empty} +% This style is installed at beginning of each Sankey diagram. +% \end{sankeyoption} +% +% For instance, to use a ratio of 5mm/10 by default (instead of 1cm/10) +% for all Sankey diagrams, add the following line: +% +% \begin{lstlisting}[style=LaTeXsmall] +% \sankeyset{every diagram/.style={ratio=5mm/10}} +% \end{lstlisting} +% +%^^A % ------------------------------------------------------------ +% \subsection{Keys to choose the scale} +%^^A % ------------------------------------------------------------ +% +% The scale or ratio of the Sankey diagram is the ratio between the % +% \code{ratio length} and the \code{ratio quantity}. +% +% \begin{sankeyoption}{ratio quantity}{\VAR{number}}{}{10} +% Quantity (in units of flow) to define ratio. The \VAR{number} can be +% any math expression. +% \end{sankeyoption} +% +% \begin{sankeyoption}{ratio length}{\VAR{distance}}{}{1cm} +% Distance (a graphical distance) to define scale. +% \end{sankeyoption} +% +% \begin{sankeyoption}{ratio}{\VAR{distance}/\VAR{number}}{}{1cm/10} +% Fix the ratio to \VAR{distance}\texttt{/}\VAR{number}. +% \end{sankeyoption} +% +% The initial ratio is 1\,cm/10 units. +% +% +% \textbf{Note:} the \code{sankey} package uses the \code{xfp} package to +% evaluate all math expressions that use quantities (in units of +% flow). You can therefore use quantities of a very large or very small +% order of magnitude. In contrast, for graphic distances, the sankey +% package uses the \code{pgfmath} package (all calculations must not +% exceed $\pm 16383.99999$). +% +%^^A % ------------------------------------------------------------ +% \subsection{Keys to define rotate offset} +%^^A % ------------------------------------------------------------ +% +% \begin{sankeyoption}{rotate}{\VAR{angle}}{}{0} +% +% The \code{rotate} key stores an offset angle applied to all Sankey +% nodes. This is useful when using the \code{rotate} option within a +% \code{tikzpicture} or a \code{scope}. This TikZ option is only +% applied to coordinates and not to TikZ nodes (remember that Sankey +% nodes are TikZ nodes). It's up to the author to keep the +% \code{rotate} option of the \code{tikzpicture} and that of the +% \code{sankeydiagram} synchronous. +% +% \end{sankeyoption} +% +%^^A % ------------------------------------------------------------ +% \subsection{Keys to define drawing parameters} +%^^A % ------------------------------------------------------------ +% +% \begin{sankeyoption}{minimum radius}{\VAR{distance}}{}{5mm} +% The minimum radius used by \code{\sankeyturn} and +% \code{\sankeydubins}. +% \end{sankeyoption} +% +% \begin{sankeyoption}{outin steps}{\VAR{integer}}{}{10} +% Number of steps used by the \code{\sankeyoutin} macro to simulate flow +% lanes with constant width. +% \end{sankeyoption} +% +%^^A % ------------------------------------------------------------ +% \subsection{Keys to choose drawing styles} +%^^A % ------------------------------------------------------------ +% +% \begin{sankeyoption}{fill/.style}{\VAR{style}}{}{{line width=0pt,fill=white}} +% This TikZ style is used to \emph{fill} all sankey paths. +% \end{sankeyoption} +% +% \begin{sankeyoption}{draw/.style}{\VAR{style}}{}{draw=black,line width=.4pt} +% This TikZ style is used to \emph{draw} all sankey paths. +% \end{sankeyoption} +% +% \begin{sankeyoption}{start style}{\VAR{style name}}{}{none} +% There are three predefined \emph{start} styles: \constant{none}, +% \constant{simple}, \constant{arrow}. +% \end{sankeyoption} +% +% \begin{sankeyoption}{end style}{\VAR{style name}}{}{none} +% There are three predefined \emph{end} styles: \constant{none}, +% \constant{simple}, \constant{arrow}. +% \end{sankeyoption} +% +%^^A % ------------------------------------------------------------ +% \subsection{Keys to define new \emph{start} and \emph{end} styles} +%^^A % ------------------------------------------------------------ +% +% \begin{sankeyoption}{new start style}{\{\VAR{name}\}\{\VAR{fill +% path}\}\{\VAR{draw path}\}}{}{} +% Define the new start style named \VAR{name} with its \VAR{fill +% path} and its \VAR{draw path}. +% \end{sankeyoption} +% +% \begin{sankeyoption}{new end style}{\{\VAR{name}\}\{\VAR{fill +% path}\}\{\VAR{draw path}\}}{}{} +% Define the new end style named \VAR{name} with its \VAR{fill +% path} and its \VAR{draw path}. +% \end{sankeyoption} +% +% \emph{Fill} and \emph{draw} paths are build in a TikZ scope where the +% origin is the center of the current Sankey node (its name is accessible +% via \code{\name}) and the coordinate system is rotated by its +% orientation. +% +%^^A % ------------------------------------------------------------ +% \subsection{The \emph{debug} key} +%^^A % ------------------------------------------------------------ +% +% \begin{sankeyoption}{debug}{\VAR{boolean}}{true}{false} +% To debug a sankey diagram. +% \end{sankeyoption} +% +%^^A % ------------------------------------------------------------ +% \section{Sankey nodes and flows} +%^^A % ------------------------------------------------------------ +% +%^^A % ------------------------------------------------------------ +% \subsection{Create Sankey nodes} +%^^A % ------------------------------------------------------------ +% +%^^A % ------------------------------------------------------------ +% +% \begin{miniblock} +% \MACRO\code{\sankeynode}\OPTARG{\VAR{options}}\ARG{\VAR{node parameters}} +% +% \DescribeMacro{\sankeynode} % +% The \code{\sankeynode} macro defines a Sankey node. The \VAR{options} +% can be any Sankey diagram keys. To define a Sankey node, you must +% provide a \emph{name}, a \emph{quantity} and an \emph{angle} as +% \VAR{node parameters}. +% +% \begin{sankeyoption}[/sankey/node parameters]{name}{\VAR{name}}{}{} +% The \VAR{name} of the new Sankey node (and the associated TikZ node). +% \end{sankeyoption} +% +% \begin{sankeyoption}[/sankey/node parameters]{quantity}{\VAR{quantity}}{}{} +% The quantity (in flow unit) of the new Sankey node. The \VAR{quantity} +% can be any math expression. +% \end{sankeyoption} +% +% \begin{sankeyoption}[/sankey/node parameters]{angle}{\VAR{angle}}{}{} +% The orientation of the flow (0 points to the right) of the new Sankey +% node. +% \end{sankeyoption} +% +% \begin{sankeyoption}[/sankey/node parameters]{at}{\VAR{at}}{}{0,0} +% The position of the new Sankey node (a TikZ coordinate \emph{without} +% round brackets or parentheses). +% \end{sankeyoption} +% +% \begin{sankeyoption}[/sankey/node parameters]{anchor}{\VAR{anchor}}{}{center} +% Specify the anchor of the Sankey node. Possible values are +% \constant{center}, \constant{left} or \constant{right}. +% \end{sankeyoption} +% +% \begin{sankeyoption}[/sankey/node parameters]{as}{\VAR{name}}{}{} +% Copy the \emph{name}, the \emph{quantity}, the \emph{angle} and the +% \emph{position} of the Sankey node named \VAR{name}. +% \end{sankeyoption} +% +% A Sankey node is also a Tikz node but with only three anchors: +% \code{left}, \code{center} and \code{right}\footnote{In fact, to be +% able to use the TikZ \code{fit} library, the % +% \code{north}, \code{north east} and \code{north west} anchors exist +% and are equal to \code{left}, % +% the \code{east} and \code{west} anchors exist and are equal to +% \code{center} and % +% the \code{south}, \code{south east} and \code{south west} anchors +% exist and are equal to \code{right}.}: +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[debug] +% \sankeynode{name=a,quantity=10} +% \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left} +% \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right} +% +% \foreach \nodename/\pos in {a/left,b/below left,c/above}{ +% \foreach \ancname in {left,center,right}{ +% \node[node font=\ttfamily\footnotesize,\pos=1mm of \nodename.\ancname, +% inner sep=0pt,rotate=\sankeygetnodeorient{\nodename},anchor=east] +% {\ancname\vphantom{g}}; +% \fill[black] (\nodename.\ancname) circle(1pt); +% } +% } +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +%^^A % ------------------------------------------------------------ +% \subsubsection{Choose default parameters} +%^^A % ------------------------------------------------------------ +% +% \begin{sankeyoption}{every node/.style}{\{\VAR{node parameters}\}}{}{empty} +% The \VAR{node parameters} defined by the +% \code{every node} style is installed at the creation of every Sankey node. +% \end{sankeyoption} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Create starting and ending nodes via macros} +%^^A % ------------------------------------------------------------ +% +% \begin{miniblock} +% \MACRO\code{\sankeynodestart}\OPTARG{\VAR{options}}\ARG{\VAR{node parameters}} +% +% \DescribeMacro{\sankeynodestart} % +% The \code{\sankeynodestart} creates and fills/draws a starting Sankey +% node: +% +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}] +% \sankeynodestart{name=a,quantity=10} +% \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left} +% \sankeynodestart{name=c,quantity=20,angle=-90,at={5,1},anchor=right} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +%^^A % ------------------------------------------------------------ +% +% +% \begin{miniblock} +% \MACRO\code{\sankeynodeend}\OPTARG{\VAR{options}}\ARG{\VAR{node +% parameters}} +% +% \DescribeMacro{\sankeynodeend} % +% The \code{\sankeynodeend} creates and fills/draws an ending Sankey +% node: +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[end style=simple,fill/.style={fill=orange!20}] +% \sankeynodeend{name=a,quantity=10} +% \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left} +% \sankeynodeend{name=c,quantity=20,angle=-90,at={5,1},anchor=right} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Create starting and ending nodes via options} +%^^A % ------------------------------------------------------------ +% +% \begin{miniblock} +% \begin{sankeyoption}[/sankey/node parameters]{start}{\VAR{boolean}}{true}{false} +% The \code{\sankeynode} macro acts as the +% \code{\sankeynodestart} macro if you add the +% \code{start} option to its options. +% \end{sankeyoption} +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}] +% \sankeynode{name=a,quantity=10,start} +% \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left,start} +% \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right,start} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% \begin{miniblock} +% \begin{sankeyoption}[/sankey/node parameters]{end}{\VAR{boolean}}{true}{false} +% The \code{\sankeynode} macro acts as the \code{\sankeynodeend} +% macro if you add the \code{end} option to its options. +% \end{sankeyoption} +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[end style=simple,fill/.style={fill=orange!20}] +% \sankeynode{name=a,quantity=10,end} +% \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left,end} +% \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right,end} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% +% \begin{miniblock} +% Although rarely necessary, you can mix these two parameters: +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram} +% \sankeyset{ +% end style=arrow, +% start style=arrow, +% fill/.style={fill=orange!20} +% } +% \sankeynode{name=a,quantity=10,start,end} +% \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left,start,end} +% \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right,start,end} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% +% \end{miniblock} +% +%^^A % ------------------------------------------------------------ +% \subsection{Retrieve information from Sankey nodes} +%^^A % ------------------------------------------------------------ +% +% \MACRO\code{\sankeygetnodeqty}\ARG{\VAR{node name}} +% +% \DescribeMacro{\sankeygetnodeqty} % +% The expandable command \code{\sankeygetnodeqty} returns the quantity +% assigned to the Sankey node named \VAR{node name}. +% +% \MACRO\code{\sankeyqtytolen}\ARG{\VAR{quantity}} +% +% \DescribeMacro{\sankeyqtytolen} % +% The expandable \code{\sankeyqtytolen} macro converts \VAR{quantity} to +% graphical length using the current ratio. +% +% \MACRO\code{\sankeygetnodeorient}\ARG{\VAR{node name}} +% +% \DescribeMacro{\sankeygetnodeorient} % +% The expandable command \code{\sankeygetnodeorient} returns the angle +% (orientation) assigned to the Sankey node named \VAR{node name}. +% +%^^A % ------------------------------------------------------------ +% \subsection{Move nodes} +%^^A % ------------------------------------------------------------ +% +% All the macros of this section move a Sankey node and fill/draw a +% portion of the Sankey flow. Then the previous position of the Sankey +% node is accessible via the \code{-old} suffix (i.e. if you move the +% \code{a} node, its previous position is the \code{a-old} node). +% +% The starred version of each of these macros moves in the opposite +% direction to their non-starred version. +% +% Except for the \code{\sankeyturn} macro, a negative value (distance or +% angle) moves in the opposite direction (the \code{\sankeyturn} macro +% is an exception: a negative angle turns right while a positive value +% turns left). +% +% {\centering +% \begin{tikzpicture} +% \begin{sankeydiagram} +% \tikzset{com/.style={node font=\ttfamily\scriptsize, +% fill=bgcode,fill opacity=1,text opacity=1}} +% \sankeyset{end style=simple,start style=simple} +% \sankeynode{name=ac,quantity=5} +% \sankeynode{name=al,quantity=5,at={[yshift=2mm]ac.left},anchor=right} +% \sankeynode{name=ar,quantity=5,at={[yshift=-2mm]ac.right},anchor=left} +% \sankeyturnleft{al}{60} +% \sankeyadvance{ac}{1cm} +% \sankeyturnright{ar}{60} +% \sankeyturnleft*{al-old}{60} +% \sankeyadvance*{ac-old}{1cm} +% \sankeyturnright*{ar-old}{60} +% \sankeystart{al-old} +% \sankeystart{ac-old} +% \sankeystart{ar-old} +% \sankeyend{al} +% \sankeyend{ac} +% \sankeyend{ar} +% \draw[red,very thick] +% (al-old-old.left) -- node[com]{n} (al-old-old.right) +% (ac-old-old.left) -- node[com]{n} (ac-old-old.right) +% (ar-old-old.left) -- node[com]{n} (ar-old-old.right); +% \path +% (al) ++(2mm,2mm) node[com,anchor=south west,align=left] { +% \string\sankeyturnleft\{n\}\{angle>0\}\\ +% \string\sankeyturnleftbackward\{n\}\{angle<0\}\\ +% \string\sankeyturnleft*\{n\}\{angle<0\}\\ +% \string\sankeyturnleftbackward*\{n\}\{angle>0\}\\ +% \string\sankeyturn\{n\}\{angle>0\} +% }; +% \path +% (al-old) ++(-2mm,2mm) node[com,anchor=south east,align=right] { +% \string\sankeyturnleftbackward\{n\}\{angle>0\}\\ +% \string\sankeyturnleft\{n\}\{angle<0\}\\ +% \string\sankeyturnleft*\{n\}\{angle>0\}\\ +% \string\sankeyturnleftbackward*\{n\}\{angle<0\}\\ +% \string\sankeyturn*\{n\}\{angle>0\} +% }; +% \path +% (ac) ++(2mm,0) node[com,anchor=west,align=left] { +% \string\sankeyadvance\{n\}\{distance>0\}\\ +% \string\sankeyadvance*\{n\}\{distance<0\} +% }; +% \path +% (ac-old) ++(-2mm,0) node[com,anchor=east,align=right] { +% \string\sankeyadvance\{n\}\{distance<0\}\\ +% \string\sankeyadvance*\{n\}\{distance>0\} +% }; +% \path +% (ar) ++(2mm,-2mm) node[com,anchor=north west,align=left] { +% \string\sankeyturnright\{n\}\{angle>0\}\\ +% \string\sankeyturnrightbackward\{n\}\{angle<0\}\\ +% \string\sankeyturnright*\{n\}\{angle<0\}\\ +% \string\sankeyturnrightbackward*\{n\}\{angle>0\}\\ +% \string\sankeyturn\{n\}\{angle<0\} +% }; +% \path +% (ar-old) ++(-2mm,-2mm) node[com,anchor=north east,align=right] { +% \string\sankeyturnrightbackward\{n\}\{angle>0\}\\ +% \string\sankeyturnright\{n\}\{angle<0\}\\ +% \string\sankeyturnright*\{n\}\{angle>0\}\\ +% \string\sankeyturnrightbackward*\{n\}\{angle<0\}\\ +% \string\sankeyturn*\{n\}\{angle<0\} +% }; +% \end{sankeydiagram} +% \end{tikzpicture} +% \par} +%^^A % ------------------------------------------------------------ +% \subsubsection{Macro to move straight (forward or backward)} +%^^A % ------------------------------------------------------------ +% +% +% \begin{miniblock} +% \MACRO\code{\sankeyadvance}\OPTARG{\VAR{options}}\ARG{\VAR{node +% name}}\ARG{\VAR{distance}} +% +% \DescribeMacro{\sankeyadvance} The \code{\sankeyadvance} moves the +% sankey node straight ahead and fills/draws this portion of the +% sankey path. A positive \VAR{distance} moves forward while a +% negative \VAR{distance} moves backward. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}] +% \sankeynodestart{name=a,quantity=10} +% \sankeyadvance{a}{1cm} +% \sankeynode[debug]{as=a} +% \sankeynode[debug]{as=a-old} +% \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left} +% \sankeyadvance{b}{1cm} +% \sankeynodestart{name=c,quantity=10,angle=-90,at={5,1},anchor=right} +% \sankeyadvance{c}{5mm} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% \begin{miniblock} +% \MACRO\code{\sankeyadvance*}\OPTARG{\VAR{options}}\ARG{\VAR{node +% name}}\ARG{\VAR{distance}} +% +% \DescribeMacro{\sankeyadvance*} The \code{\sankeyadvance*} moves +% the sankey node straight back and fills/draws this portion of the +% sankey path. A positive \VAR{distance} moves backward while a +% negative \VAR{distance} moves forward. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[end style=arrow,fill/.style={fill=orange!20}] +% \sankeynodeend{name=a,quantity=10} +% \sankeyadvance*{a}{1cm} +% \sankeynode[debug]{as=a} +% \sankeynode[debug]{as=a-old} +% \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left} +% \sankeyadvance*{b}{1cm} +% \sankeynodeend{name=c,quantity=10,angle=-90,at={5,1},anchor=right} +% \sankeyadvance*{c}{5mm} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Macro to turn forward or backward} +%^^A % ------------------------------------------------------------ +% +%\begin{miniblock} +% \MACRO\code{\sankeyturn}\OPTARG{\VAR{options}}\ARG{\VAR{node +% name}}\ARG{\VAR{angle}} +% +% \DescribeMacro{\sankeyturn} The \code{\sankeyturn} macro moves the +% sankey node by turning to one side or the other and fills/draws +% this portion of the sankey path. A \emph{positive} \VAR{angle} +% turns left while a \emph{negative} \VAR{angle} turns right. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=arrow,fill/.style={fill=orange!20}] +% \sankeynodestart{name=a,quantity=10} +% \sankeyturn{a}{90} +% \sankeynode[debug]{as=a} +% \sankeynode[debug]{as=a-old} +% \sankeynodestart{name=b,quantity=5,angle=45,at={2,1},anchor=left} +% \sankeyturn[minimum radius=1cm]{b}{-45} +% \sankeynodestart{name=c,quantity=10,angle=-90,at={5,1},anchor=right} +% \sankeyturn{c}{180} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% \begin{miniblock} +% \MACRO\code{\sankeyturn*}\OPTARG{\VAR{options}}\ARG{\VAR{node +% name}}\ARG{\VAR{angle}} +% +% \DescribeMacro{\sankeyturn*} The \code{\sankeyturn*} macro moves the +% sankey node backward by turning right or left and fills/draws this +% portion of the sankey path. A \emph{positive} \VAR{angle} turns left +% while a \emph{negative} \VAR{angle} turns right. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[end style=simple,fill/.style={fill=orange!20}] +% \sankeynodeend{name=a,quantity=10} +% \sankeyturn*{a}{90} +% \sankeynode[debug]{as=a} +% \sankeynode[debug]{as=a-old} +% \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left} +% \sankeyturn*[minimum radius=1cm]{b}{-45} +% \sankeynodeend{name=c,quantity=10,angle=-90,at={3,1},anchor=right} +% \sankeyturn*{c}{180} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Macros to turn left (forward or backward)} +%^^A % ------------------------------------------------------------ +% +% \begin{miniblock} +% \MACRO\code{\sankeyturnleft}\OPTARG{\VAR{options}}\ARG{\VAR{node +% name}}\ARG{\VAR{angle}} +% +% \DescribeMacro{\sankeyturnleft} The +% \code{\sankeyturnleft} macro moves the sankey node by turning left +% and fills/draws this portion of the sankey path. A \emph{positive} +% \VAR{angle} turns forward while a \emph{negative} \VAR{angle} turns backward. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=arrow,end style=arrow] +% \sankeyset{fill/.style={fill=orange!20}} +% \sankeynodestart{name=a,quantity=10} +% \sankeyturnleft{a}{90} +% \sankeynode[debug]{as=a} +% \sankeynode[debug]{as=a-old} +% \sankeyset{fill/.style={fill=lime!20}} +% \sankeynodeend{name=b,quantity=5,angle=-135,at={1,2},anchor=left} +% \sankeyturnleft[minimum radius=1cm]{b}{-225} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% \begin{miniblock} +% \MACRO\code{\sankeyturnleft*}\OPTARG{\VAR{options}}\ARG{\VAR{node +% name}}\ARG{\VAR{angle}} +% +% \DescribeMacro{\sankeyturnleft*} The +% \code{\sankeyturnleft*} macro moves the sankey node backward +% by turning left and fills/draws this portion of the sankey path. +% A \emph{positive} \VAR{angle} turns backward while a +% \emph{negative} \VAR{angle} turns forward. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=arrow,end style=arrow] +% \sankeyset{fill/.style={fill=orange!20}} +% \sankeynodeend{name=a,quantity=10} +% \sankeyturnleft*{a}{90} +% \sankeynode[debug]{as=a} +% \sankeynode[debug]{as=a-old} +% \sankeyset{fill/.style={fill=lime!20}} +% \sankeynodestart{name=b,quantity=5,angle=-135,at={1,2},anchor=left} +% \sankeyturnleft*[minimum radius=.75cm]{b}{-225} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% \begin{miniblock} +% \MACRO\code{\sankeyturnleftbackward}\OPTARG{\VAR{options}}\ARG{\VAR{node +% name}}\ARG{\VAR{angle}} +% +% \DescribeMacro{\sankeyturnleftbackward} The +% \code{\sankeyturnleftbackward} macro moves the sankey node backward +% by turning left and fills/draws this portion of the sankey path. +% A \emph{positive} \VAR{angle} turns backward while a +% \emph{negative} \VAR{angle} turns forward. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=arrow,end style=arrow] +% \sankeyset{fill/.style={fill=orange!20}} +% \sankeynodeend{name=a,quantity=10} +% \sankeyturnleftbackward{a}{90} +% \sankeynode[debug]{as=a} +% \sankeynode[debug]{as=a-old} +% \sankeyset{fill/.style={fill=lime!20}} +% \sankeynodestart{name=b,quantity=5,angle=-135,at={1,2},anchor=left} +% \sankeyturnleftbackward[minimum radius=.75cm]{b}{-225} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% \begin{miniblock} +% \MACRO\code{\sankeyturnleftbackward*}\OPTARG{\VAR{options}}\ARG{\VAR{node +% name}}\ARG{\VAR{angle}} +% +% \DescribeMacro{\sankeyturnleftbackward*} The +% \code{\sankeyturnleftbackward*} macro moves the sankey node by turning left +% and fills/draws this portion of the sankey path. A \emph{positive} +% \VAR{angle} turns forward while a \emph{negative} \VAR{angle} turns backward. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=arrow,end style=arrow] +% \sankeyset{fill/.style={fill=orange!20}} +% \sankeynodestart{name=a,quantity=10} +% \sankeyturnleftbackward*{a}{90} +% \sankeynode[debug]{as=a} +% \sankeynode[debug]{as=a-old} +% \sankeyset{fill/.style={fill=lime!20}} +% \sankeynodeend{name=b,quantity=5,angle=-135,at={1,2},anchor=left} +% \sankeyturnleftbackward*[minimum radius=1cm]{b}{-225} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Macros to turn right (forward or backward)} +%^^A % ------------------------------------------------------------ +% +% \begin{miniblock} +% \MACRO\code{\sankeyturnright}\OPTARG{\VAR{options}}\ARG{\VAR{node +% name}}\ARG{\VAR{angle}} +% +% \DescribeMacro{\sankeyturnright} The \code{\sankeyturnright} macro +% moves the sankey node by turning right and fills/draws this portion +% of the sankey path. A \emph{positive} \VAR{angle} turns forward +% while a \emph{negative} \VAR{angle} turns backward. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=arrow,end style=arrow] +% \sankeyset{fill/.style={fill=orange!20}} +% \sankeynodestart{name=a,quantity=10} +% \sankeyturnright[fill/.style={fill=orange!20}]{a}{90} +% \sankeynode[debug]{as=a} +% \sankeynode[debug]{as=a-old} +% \sankeyset{fill/.style={fill=lime!20}} +% \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left} +% \sankeyturnright[minimum radius=.75cm]{b}{-225} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% \begin{miniblock} +% \MACRO\code{\sankeyturnright*}\OPTARG{\VAR{options}}\ARG{\VAR{node +% name}}\ARG{\VAR{angle}} +% +% \DescribeMacro{\sankeyturnright*} The \code{\sankeyturnright*} macro +% moves the sankey node backward by turning right and fills/draws +% this portion of the sankey path. A \emph{positive} \VAR{angle} turns +% backward while a \emph{negative} \VAR{angle} turns forward. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=arrow,end style=arrow] +% \sankeyset{fill/.style={fill=orange!20}} +% \sankeynodeend{name=a,quantity=10} +% \sankeyturnright*[fill/.style={fill=orange!20}]{a}{90} +% \sankeynode[debug]{as=a} +% \sankeynode[debug]{as=a-old} +% \sankeyset{fill/.style={fill=lime!20}} +% \sankeynodestart{name=b,quantity=5,angle=45,at={1,1},anchor=left} +% \sankeyturnright*[minimum radius=.75cm]{b}{-225} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% \begin{miniblock} +% \MACRO\code{\sankeyturnrightbackward}\OPTARG{\VAR{options}}\ARG{\VAR{node +% name}}\ARG{\VAR{angle}} +% +% \DescribeMacro{\sankeyturnrightbackward} +% The \code{\sankeyturnrightbackward} macro +% moves the sankey node backward by turning right and fills/draws +% this portion of the sankey path. A \emph{positive} \VAR{angle} turns +% backward while a \emph{negative} \VAR{angle} turns forward. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=arrow,end style=arrow] +% \sankeyset{fill/.style={fill=orange!20}} +% \sankeynodeend{name=a,quantity=10} +% \sankeyturnrightbackward[fill/.style={fill=orange!20}]{a}{90} +% \sankeynode[debug]{as=a} +% \sankeynode[debug]{as=a-old} +% \sankeyset{fill/.style={fill=lime!20}} +% \sankeynodestart{name=b,quantity=5,angle=45,at={1,1},anchor=left} +% \sankeyturnrightbackward[minimum radius=.75cm]{b}{-225} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% \begin{miniblock} +% \MACRO\code{\sankeyturnrightbackward*}\OPTARG{\VAR{options}}\ARG{\VAR{node +% name}}\ARG{\VAR{angle}} +% +% \DescribeMacro{\sankeyturnrightbackward*} The +% \code{\sankeyturnrightbackward*} macro moves the sankey +% node forward by turning right and fills/draws this portion +% of the sankey path. A \emph{positive} \VAR{angle} turns forward +% while a \emph{negative} \VAR{angle} turns backward. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=arrow,end style=arrow] +% \sankeyset{fill/.style={fill=orange!20}} +% \sankeynodestart{name=a,quantity=10} +% \sankeyturnrightbackward*[fill/.style={fill=orange!20}]{a}{90} +% \sankeynode[debug]{as=a} +% \sankeynode[debug]{as=a-old} +% \sankeyset{fill/.style={fill=lime!20}} +% \sankeynodeend{name=b,quantity=5,angle=45,at={2,1},anchor=left} +% \sankeyturnrightbackward*[minimum radius=.75cm]{b}{-225} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% +%^^A % ------------------------------------------------------------ +% \subsection{Links between nodes} +%^^A % ------------------------------------------------------------ +% +% The macros described in this section fill/draw a lane between two +% Sankey nodes. +% +% Note: since Sankey nodes are oriented, linking \code{A} node to +% \code{B} node does not produce the same result as linking \code{B} +% node to \code{A} node! +% +% \begin{miniblock} +% \MACRO\code{\sankeyoutin}\OPTARG{\VAR{options}}\ARG{\VAR{node +% A}}\ARG{\VAR{node B}} +% +% \DescribeMacro{\sankeyoutin} The \code{\sankeyoutin} macro +% fills/draws a lane from \VAR{node A} to \VAR{node B} using a +% Bézier curve with regular steps (10 steps by default) to +% simulate constant width lane. +% +% The constant width and the minimum curvature are \emph{not} guaranteed! +% \end{miniblock} +% +% \begin{miniblock} +% \MACRO\code{\sankeydubins}\OPTARG{\VAR{options}}\ARG{\VAR{node +% A}}\ARG{\VAR{node B}} +% +% \DescribeMacro{\sankeydubins} % +% The \code{\sankeydubins} macro fills/draws a lane between +% \VAR{node A} and \VAR{node B} using a Dubins +% path\footnote{\url{https://en.wikipedia.org/wiki/Dubins_path}}. +% +% The constant width and the minimum curvature are guaranteed. +% \end{miniblock} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Comparison between \texttt{outin} and \texttt{dubins} +% paths} +%^^A % ------------------------------------------------------------ +% +% The following diagrams compare \texttt{outin} path with +% 10 steps (orange), \texttt{outin} path with 2 steps (red) +% and \texttt{dubins} path (lime) in various positions. +% +% \begin{miniblock} +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=simple,end style=arrow] +% \sankeyset{fill/.style={fill=orange!20}} +% \sankeynodestart{name=a,quantity=5} +% \sankeynodeend{name=b,at={4,3},quantity=5} +% \sankeyoutin{a}{b} +% +% \sankeyset{fill/.style={fill=red!20}} +% \sankeynodestart{name=a,at={2,0},quantity=5} +% \sankeynodeend{name=b,at={6,3},quantity=5} +% \sankeyoutin[outin steps=2]{a}{b} +% +% \sankeyset{fill/.style={fill=lime!40}} +% \sankeynodestart{name=a,at={4,0},quantity=5} +% \sankeynodeend{name=b,at={(8,3},quantity=5} +% \sankeydubins[minimum radius=5mm]{a}{b} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% \begin{miniblock} +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=simple,end style=arrow] +% \sankeyset{fill/.style={fill=orange!20}} +% \sankeynodestart{name=a,quantity=5} +% \sankeynodeend{name=b,at={2,3},quantity=5} +% \sankeyoutin{a}{b} +% +% \sankeyset{fill/.style={fill=red!20}} +% \sankeynodestart{name=a,at={2,0},quantity=5} +% \sankeynodeend{name=b,at={4,3},quantity=5} +% \sankeyoutin[outin steps=2]{a}{b} +% +% \sankeyset{fill/.style={fill=lime!40}} +% \sankeynodestart{name=a,at={4,0},quantity=5} +% \sankeynodeend{name=b,at={(6,3},quantity=5} +% \sankeydubins[minimum radius=5mm]{a}{b} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% \begin{miniblock} +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=simple,end style=arrow] +% \sankeyset{fill/.style={fill=orange!20}} +% \sankeynodestart{name=a,quantity=5} +% \sankeynodeend{name=b,at={0,3},quantity=5} +% \sankeyoutin{a}{b} +% +% \sankeyset{fill/.style={fill=red!20}} +% \sankeynodestart{name=a,at={2,0},quantity=5} +% \sankeynodeend{name=b,at={2,3},quantity=5} +% \sankeyoutin[outin steps=2]{a}{b} +% +% \sankeyset{fill/.style={fill=lime!40}} +% \sankeynodestart{name=a,at={4,0},quantity=5} +% \sankeynodeend{name=b,at={(4,3},quantity=5} +% \sankeydubins[minimum radius=5mm]{a}{b} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Examples of \texttt{dubins} paths} +%^^A % ------------------------------------------------------------ +% +% \begin{miniblock} +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram}[start style=simple,end style=arrow] +% \sankeyset{ +% fill/.style={fill=lime!40}, +% draw/.style={draw=green!50!black,line width=2pt}, +% } +% +% \sankeynodestart{name=a,quantity=5} +% \sankeynodeend{name=b,at={0,2},quantity=5} +% \sankeydubins[minimum radius=2mm]{a}{b} +% +% \fill[green!50!black] (2,0) coordinate (c) circle(2pt); +% \sankeynodestart{name=a,at={[shift={(c)}]90:5mm},quantity=5} +% \sankeynodeend{name=b,at={[shift={(c)}]150:5mm},angle=60,quantity=5} +% \sankeydubins[minimum radius=2.5mm]{a}{b} +% +% \sankeynodestart{name=a,at={3.5,0},quantity=5} +% \sankeynodeend{name=b,at={3.5,.75},angle=-180,quantity=5} +% \sankeydubins[minimum radius=5mm]{a}{b} +% +% \sankeynodestart{name=a,at={7,1},quantity=5} +% \sankeynodeend{name=b,at={7,1.75},quantity=5} +% \sankeydubins[minimum radius=2.5mm]{a}{b} +% +% \sankeynodestart{name=a,at={9,0},quantity=5} +% \sankeynodeend{name=b,at={9,2},angle=180,quantity=5} +% \sankeydubins[minimum radius=2.5mm]{a}{b} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +%^^A % ------------------------------------------------------------ +% \subsection{Pure filling/drawing macros} +%^^A % ------------------------------------------------------------ +% +% \begin{miniblock} +% \MACRO\code{\sankeystart}\OPTARG{\VAR{options}}\ARG{\VAR{name}} +% +% \DescribeMacro{\sankeystart} % +% The \code{\sankeystart} fills/draws a starting extremity attached to +% the preexisting Sankey node \VAR{name}: +% +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram} +% [start style=arrow,fill/.style={fill=cyan!20},draw/.style={draw=blue}] +% \sankeynode{name=a,quantity=10} +% \sankeystart{a} +% \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left} +% \sankeystart{b} +% \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right} +% \sankeystart{c} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +%^^A % ------------------------------------------------------------ +% +% +% \begin{miniblock} +% \MACRO\code{\sankeyend}\OPTARG{\VAR{options}}\ARG{\VAR{name}} +% +% \DescribeMacro{\sankeyend} % +% The \code{\sankeyend} fills/draws an ending extremity attached to +% the preexisting Sankey node \VAR{name}: +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram} +% [end style=simple,fill/.style={fill=cyan!20},draw/.style={draw=blue}] +% \sankeynode{name=a,quantity=10} +% \sankeyend{a} +% \sankeynode{name=b,quantity=5,angle=45,at={2,1},anchor=left} +% \sankeyend{b} +% \sankeynode{name=c,quantity=20,angle=-90,at={5,1},anchor=right} +% \sankeyend{c} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% % +% {\centering\input{\samplecodename}\par} +% \end{miniblock} +% +%^^A % ------------------------------------------------------------ +% \subsection{Forked node} +%^^A % ------------------------------------------------------------ +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Create and fork a Sankey node} +%^^A % ------------------------------------------------------------ +% +% \changes{v3.0}{2021/03/14}{add keys to fork a Sankey node during its +% creation} +% +% \begin{miniblock} +% When creating a new Sankey node, the \code{forked} and % +% \code{fork anchor} keys allow to fork the node directly \emph{and} to +% anchor it on an anchor of a forked subnode. +% +% \begin{sankeyoption}[/sankey/node parameters]{forked}{\{\VAR{quantity/name pairs}\}}{}{} +% The \VAR{quantity/name pairs} is a comma separated list of +% \emph{quantity/name} pairs (one for each subnode, from left to +% right). The sum of all quantities \emph{must} be equal to the quantity +% of the new node to fork. +% \end{sankeyoption} +% +% \begin{sankeyoption}[/sankey/node parameters]{fork anchor}{\VAR{node.anchor}}{}{} +% An anchor belonging to the new node \emph{or} belonging to a subnode +% (the anchor name must be prefixed by the name of the +% node). \emph{Note:} when a \code{fork anchor} key is supplied, the +% \code{anchor} key is ignored (with a \emph{warning} message). +% \end{sankeyoption} +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram} +% \sankeyset{ +% start style=arrow,end style=arrow, +% fill/.style={fill=yellow!10,line width=0pt,draw=yellow!10} +% } +% +% \sankeynode[debug]{ +% name=a,quantity=40,angle=-80, +% forked={25/b,10/c,5/d}, +% fork anchor=c.right, +% } +% +% \sankeyadvance*{b}{1cm} +% \sankeyturn*[minimum radius=2cm]{c}{-30} +% \sankeyturn*[minimum radius=2cm]{c}{30} +% \sankeyturn*[minimum radius=5mm]{d}{-90} +% \sankeyadvance{a}{1.5cm} +% \foreach \nodename in {b,c,d}{ \sankeystart{\nodename} } +% \sankeyend{a} +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Fork a Sankey node} +%^^A % ------------------------------------------------------------ +% \begin{miniblock} +% \MACRO\code{\sankeyfork}\OPTARG{\VAR{options}}\ARG{\VAR{name}}\ARG{\VAR{quantity/name pairs}} +% +% \DescribeMacro{\sankeyfork} % +% The \code{\sankeyfork} macro splits the preexisting Sankey node +% named \VAR{name} in a list of new Sankey subnodes. The +% \VAR{quantity/name pairs} is a comma separated list of +% \emph{quantity/name} pairs, one for each subnode from left to +% right. The sum of all quantities \emph{must} be equal to the +% quantity of the node to fork. +% +% \begin{VerbatimOut}[gobble=2]{\samplecodename} +% \begin{tikzpicture} +% \begin{sankeydiagram} +% \sankeynode{name=a,quantity=40,angle=-45} +% \sankeyfork[debug]{a}{25/b,10/c,5/d} +% \path (a.left) rectangle (a.right); %^^A create a bounding box +% \end{sankeydiagram} +% \end{tikzpicture} +% \end{VerbatimOut} +% % +% {\centering\input{\samplecodename}\par} +% % +% \lstinputlisting[style=LaTeXsmall]{\samplecodename} +% \end{miniblock} +% +%^^A % ------------------------------------------------------------ +% \section{Miscellaneous} +%^^A % ------------------------------------------------------------ +% +%^^A % ------------------------------------------------------------ +% \subsection{The \texttt{debug} layer} +%^^A % ------------------------------------------------------------ +% +% The options \code{debug} key uses the \code{sankeydebug} layer to draw +% above the \code{main} TikZ layer (via \code{\pgfsetlayers}, the +% \code{sankey} package installs four layers: \code{background}, +% \code{main}, \code{foreground}, \code{sankeydebug}). +% +% The four following styles define how to display debug information: +% +% \begin{lstlisting}[style=LaTeXsmall] +% \sankeyset{ +% debug color/.style={/utils/exec={\colorlet{debug color}{#1}}}, +% % debug color used by all debug macros +% debug color=red!75!black, +% % debug line between left and right anchors +% debug line/.style={overlay,draw=debug color,|-|}, +% % debug line between center and label +% debug normal/.style={overlay,draw=debug color}, +% % debug node label +% debug label/.style={ +% overlay, +% draw, +% font=\ttfamily\tiny, +% text=debug color,text opacity=1, +% inner sep=.1em, +% fill=white,fill opacity=1, +% rounded corners=.1em, +% node contents={\name}, +% }, +% } +% \end{lstlisting} +% +%^^A % ------------------------------------------------------------ +% \subsection{The \texttt{dubins} TikZ library} +% \label{sec:dubins} +%^^A % ------------------------------------------------------------ +% +% The \code{sankey} package uses the \code{dubins} TikZ library (the +% \code{tikzlibrarydubins.code.tex} file) to compute Dubins paths. The +% documentation for this library does not yet exist. +% +%^^A % ------------------------------------------------------------ +% \subsection{How to duplicate a Sankey node} +%^^A % ------------------------------------------------------------ +% +% \MACRO\code{\sankeynodealias}\ARG{\VAR{origname}}\ARG{\VAR{clonename}} +% +% \DescribeMacro{\sankeynodealias} % +% The \code{\sankeynodealias} macro clones the Sankey node named +% \VAR{origname} into the Sankey node named \VAR{clonename}. +% +% So, you can clone a Sankey node via two methods: +% +% \begin{lstlisting}[style=LaTeXsmall] +% \sankeynode{name=a,quantity=10} +% \sankeynode{as=a,name=b} +% \end{lstlisting} +% +% \begin{lstlisting}[style=LaTeXsmall] +% \sankeynode{name=a,quantity=10} +% \sankeynodealias{a}{b} +% \end{lstlisting} +% +%^^A % ------------------------------------------------------------ +% \subsection{How to define new start and end styles} +%^^A % ------------------------------------------------------------ +% +% Here are the definitions of the \code{arrow} styles: +% +% \begin{lstlisting}[style=LaTeXsmall] +% \sankeyset{ +% %% arrow style +% new start style={arrow}{ +% (\name.left) -- ++(-10pt,0) +% -- ([xshift=-10pt/6]\name.center) +% -- ([xshift=-10pt]\name.right) +% -- (\name.right) -- cycle +% }{ +% (\name.left) -- ++(-10pt,0) +% -- ([xshift=-10pt/6]\name.center) +% -- ([xshift=-10pt]\name.right) +% -- (\name.right) +% }, +% new end style={arrow}{ +% (\name.left) -- ([yshift=1mm]\name.left) +% -- ([xshift=10pt]\name.center) +% -- ([yshift=-1mm]\name.right) -- (\name.right) -- cycle +% }{ +% (\name.left) -- ([yshift=1mm]\name.left) +% -- ([xshift=10pt]\name.center) +% -- ([yshift=-1mm]\name.right) -- (\name.right) +% }, +% } +% \end{lstlisting} +% +%^^A % ------------------------------------------------------------ +% \section{Todo} +%^^A % ------------------------------------------------------------ +% +% \begin{itemize} +% \item Document the \code{dubins} TikZ library. +% \item Add a tutorial. +% \item Add examples with cycle(s). +% \end{itemize} +% +% ^^A % ------------------------------------------------------------ +% \clearpage +% +% \manualparts +% +% \part{Examples} +% \label{examples} +%^^A % ------------------------------------------------------------ +% { +% \setlength{\parskip}{0pt} +% \localtableofcontents +% \listoffigures +% } +% +% \tikzset{every picture/.style={}} +%^^A % ------------------------------------------------------------ +% +%^^A % ------------------------------------------------------------ +% \clearpage +% \section{Simple example} +%^^A % ------------------------------------------------------------ +% +% \embedfile[mimetype=text/plain]{sankey-example1.tex} +% +% \begin{figure} +% \centering +% {\MakePercentComment\input{sankey-example1.tex}} +% \caption{Simple example} +% \label{fig:simple-example} +% \end{figure} +% +% See figure~\vref{fig:simple-example}. The \code{sankey-example1.tex} +% file contains the following code and is an attachement of the current +% PDF document. +% +% \lstinputlisting[style=LaTeXsmall]{sankey-example1.tex} +% +% \iffalse +%<*example1> +\begin{tikzpicture} + \begin{sankeydiagram}%[debug] + \colorlet{cold}[rgb]{cyan!75!blue!50!white} + \colorlet{hot}[rgb]{red!50!orange!75!white} + \sankeyset{ + ratio=90pt/6,minimum radius=15pt, + start style=simple,end style=simple, + draw/.style={ + draw=blue!50!cyan, + line width=1pt,line cap=round,line join=round, + }, + cold/.style={ + fill/.style={ + draw=cold,line width=0pt,fill=cold, + }, + }, + cold to hot/.style={ + fill/.style={ + fill=none,top color=cold, + bottom color=hot,middle color=yellow, + }, + }, + hot/.style={ + fill/.style={ + draw=hot,line width=0pt,fill=hot, + }, + }, + } + + \sankeyset{cold} + \sankeynodestart{name=p0,at={100,0},angle=-90,quantity=6} + \sankeyadvance{p0}{50pt} + \sankeyfork{p0}{3/p1,3/p2} + \sankeyturnleft{p1}{90} + \sankeyadvance{p1}{20pt} + \sankeyadvance{p2}{60pt} + \sankeyfork{p2}{2/p3,1/p4} + \sankeyturnleft{p3}{90} + \sankeyadvance{p3}{50pt} + \sankeyfork{p3}{1/p5,1/p6} + \sankeyadvance{p5}{70pt} + \sankeyfork{p1}{1/p7,1/p8,1/p9} + \sankeyadvance{p7}{50pt} + \sankeyadvance{p9}{50pt} + \sankeyadvance{p4}{40pt} + \sankeyturnleft{p4}{90} + \sankeyadvance{p4}{65pt} + \sankeyadvance{p7}{40pt} + \sankeynode{ + name=p11,at={[shift={(50pt,-15pt)}]p7},quantity=3, + forked={1/p7a,1/p9a,1/p5a}, + } + \sankeyoutin{p7}{p7a} + \sankeyoutin{p9}{p9a} + \sankeyoutin{p5}{p5a} + \sankeyadvance{p11}{30pt} + \sankeyend{p11} + \sankeyturnright{p8}{90} + \sankeyturnright{p6}{90} + \sankeyturnright{p4}{90} + \sankeyset{hot} + \sankeyadvance[cold to hot]{p8}{40pt} + \sankeynode{ + name=p10,at={[shift={(-15pt,-60pt)}]p8},angle=-90,quantity=3, + forked={1/p8a,1/p6a,1/p4a}, + } + \sankeyoutin[cold to hot]{p4}{p4a} + \sankeyoutin[cold to hot]{p6}{p6a} + \sankeyoutin{p8}{p8a} + \sankeyadvance{p10}{30pt} + \sankeyend{p10} + \end{sankeydiagram} +\end{tikzpicture} +%</example1> +% \fi +% +%^^A % ------------------------------------------------------------ +% \clearpage +% \section{Energy diagram} +%^^A % ------------------------------------------------------------ +% +% \embedfile[mimetype=text/plain]{sankey-example-energy.tex} +% +% \begin{figure} +% \centering +% {\MakePercentComment\input{sankey-example-energy.tex}} +% \caption{Energy diagram} +% \label{fig:very-simple-example} +% \end{figure} +% +% This example comes from +% \href{https://ibphysicsblog.wordpress.com/2015/10/23/sankey-diagrams/}{IB +% Pysics Blog} by Kyu Won Shim. +% +% See figure~\vref{fig:very-simple-example}. The \code{sankey-example-energy.tex} +% file contains the following code and is an attachement of the current +% PDF document. +% +% \lstinputlisting[style=LaTeXsmall]{sankey-example-energy.tex} +% +% \iffalse +%<*example-energy> +\begin{tikzpicture} + % font choice + \renewcommand\rmdefault{txr}\rmfamily\footnotesize + \sisetup{ + round-mode=places, + round-precision=1, + add-decimal-zero, + round-integer-to-decimal, + } + \begin{sankeydiagram} + \colorlet{energy}{blue!30!cyan!80!black} + \colorlet{lost energy}{red!50!orange!90!black} + \sankeyset{ + ratio=13em/100, + minimum radius=1em, + start style=simple,end style=simple, + draw/.style={draw=none,line width=0}, + energy/.style={ + fill/.style={ + draw=energy, + line width=0, + fill=energy, + } + }, + lost energy/.style={ + fill/.style={ + draw=lost energy, + line width=0, + fill=lost energy, + } + } + } + + \newcommand\abovelabel[2]{ % valname, label + \node[anchor=south east,align=center,inner xsep=0] at (#1.left) {#2}; + } + + \newcommand\energylabel[1]{ % valname + \node[anchor=north east,text=energy,inner xsep=0] at (#1.right) + {\num{\sankeygetnodeqty{#1}}}; + } + + \newcommand\lostenergylabel[2]{ % valname, label + \node[anchor=north,text=lost energy] at ([yshift=-2.5mm]#1.center) + (value) + {\num{\sankeygetnodeqty{#1}}}; + \node[anchor=north,inner sep=0,align=center] at (value.south) {#2}; + } + + \newcommand\lostenergylabelbottom[2]{ % valname, label + \draw[draw=lost energy,dashed,thick] + ([yshift=-3mm]#1.center) coordinate (#1) -- ([yshift=-3mm]#1.center); + \lostenergylabel{#1}{#2} + } + + \sankeynode{name=Co,quantity=100.0} + \path (Co.right) ++(0,-7mm) coordinate (c); + + \newcommand\turnandstop[2]{ % valname, label + \begingroup + \sankeyset{lost energy} + \sankeyturnright{#1}{90} + \sankeynode{as=#1,name=#1-stop,at={#1 |- c}} + \sankeyoutin{#1}{#1-stop} + \sankeynode{as=#1-stop,name=#1} + \sankeyend{#1} + \lostenergylabel{#1}{#2} + \endgroup + } + + \newcommand\turnandstopbottom[2]{ % valname, label + \begingroup + \sankeyset{lost energy} + \sankeyturnright{#1}{90} + \sankeynode{as=#1,name=#1-stop,at={#1 |- c}} + \sankeyoutin{#1}{#1-stop} + \sankeynode{as=#1-stop,name=#1} + \sankeyend{#1} + \lostenergylabelbottom{#1}{#2} + \endgroup + } + + \def\hshift{6.25em} + + \sankeyadvance[energy]{Co}{1.2*\hshift} + \abovelabel{Co}{\textbf{Coal}\\(Primary energy)} + \energylabel{Co} + \sankeyfork{Co}{35/El1,65/Pg} + \turnandstop{Pg}{Power generation} + + \sankeyadvance[energy]{El1}{1.8*\hshift} + \abovelabel{El1}{\textbf{Electricity}\\(Secondary energy)} + \energylabel{El1} + \sankeyfork{El1}{33.5/El2,1.5/Tr} + \turnandstopbottom{Tr}{Transmission} + + \sankeyadvance[energy]{El2}{.65*\hshift} + \energylabel{El2} + \sankeyfork{El2}{31.5/El3,2.0/Di} + \turnandstop{Di}{Distribution} + + \sankeyadvance[energy]{El3}{.65*\hshift} + \energylabel{El3} + \sankeyfork{El3}{31.0/El4,0.5/Wi} + \turnandstopbottom{Wi}{Wiring} + + \sankeyadvance[energy]{El4}{.65*\hshift} + \abovelabel{El4}{\textbf{Electricity}\\(Final energy)} + \energylabel{El4} + \sankeyfork{El4}{3.0/Lr1,28.0/Lb} + \turnandstop{Lb}{Lightbulb} + + \sankeyadvance[energy]{Lr1}{1.1*\hshift} + \abovelabel{Lr1}{\textbf{Light radiation}\\(Useful energy)} + \energylabel{Lr1} + \sankeyfork{Lr1}{2.0/Lr2,1.0/Ls} + \turnandstopbottom{Ls}{Lampshade} + + \sankeyadvance[energy]{Lr2}{.6*\hshift} + \energylabel{Lr2} + \sankeyfork{Lr2}{1.0/Il,1.0/Id} + \turnandstop{Id}{Idle} + + \sankeyadvance[energy]{Il}{.6*\hshift} + \abovelabel{Il}{\textbf{Illumination}\\(Energy services)} + \energylabel{Il} + \sankeyend[energy]{Il} + \end{sankeydiagram} +\end{tikzpicture} +%</example-energy> +% \fi +%^^A % ------------------------------------------------------------ +% \clearpage +% \section{Example from question on TeX.se} +%^^A % ------------------------------------------------------------ +% +% \changes{v3.0}{2021/03/14}{fix bad names in second example} +% +% \embedfile[mimetype=text/plain]{sankey-example2.tex} +% +% \begin{figure} +% \centering +% {\MakePercentComment\input{sankey-example2}} +% \caption{Example from TeX.se question} +% \label{fig:texse-example} +% \end{figure} +% +% This example came from +% \href{https://tex.stackexchange.com/q/40159/14500}{this question} on +% \href{https://tex.stackexchange.com/}{TeX.StackExchange}. +% +% See figure~\vref{fig:texse-example}. The \code{sankey-example2.tex} +% file contains the following code and is an attachement of the current +% PDF document. +% +% \lstinputlisting[style=LaTeXsmall]{sankey-example2} +% +% \iffalse +%<*example2> +\begin{tikzpicture} + \renewcommand*\sfdefault{txss} + + \begin{sankeydiagram}%[debug] + \sankeyset{ + ratio=4cm/524.3, + minimum radius=3mm, + start style=arrow, + end style=arrow, + fill/.style={ + line width=0pt, + fill=cyan!50!blue!50!black, + draw=cyan!50!blue!50!black, + }, + draw/.style={draw=none}, + every node/.style={angle=-90}, + } + + \sankeynodestart{name=B,at={-.5,0},quantity=7.2} + \coordinate[below=1mm of B.center] (B label); + \sankeyadvance{B}{5mm} + \sankeynodestart{name=GI,at={1,0},quantity=137.3} + \coordinate[below=1mm of GI.center] (GI label); + \sankeyadvance{GI}{5mm} + \sankeynodestart{name=I,at={4,0},quantity=397.8} + \coordinate[below=1mm of I.center] (I label); + \sankeynode{ + name=EI,at={2.86,-3},quantity=542.3, + forked={397.8/Ia,137.3/GIa,7.2/Ba} + } + \sankeydubins[minimum radius=1.2cm]{I}{Ia} + \sankeyoutin{GI}{GIa} + \sankeyoutin{B}{Ba} + \sankeyadvance{EI}{5mm} + \coordinate (EI label) at (EI); + \sankeyadvance{EI}{5mm} + \sankeyfork{EI}{63.1/EB,479.2/P} + + \sankeyturnleft{EB}{90} + \sankeyadvance{EB}{4cm} + \coordinate (EB label) at ($(EB)!.5!(EB-old)$); + \sankeyend{EB} + + \sankeyadvance{P}{10mm} + \coordinate (P label) at (P); + \sankeyadvance{P}{5mm} + + \sankeyfork{P}{33.5/NV,445.7/P-NV} + + { + \colorlet{NV color}{cyan!80!lime!50!gray} + \sankeyset{fill/.append style={fill=NV color,draw=NV color}} + \sankeyturnleft{NV}{90} + \sankeynode{as=NV,name=NV2,at=NV -| EB} + \sankeyoutin{NV}{NV2} + \coordinate (NV label) at (NV -| EB label); + \sankeyend{NV2} + } + + \sankeyadvance{P-NV}{10mm} + \sankeyfork{P-NV}{118.1/U,327.6/P-NV-U} + + { + \sankeyset{ + fill/.style={fill=orange!70!gray!50,draw=orange!70!gray!50} + } + \sankeyturnleft{U}{90} + \sankeynode{as=U,name=U2,at=U -| EB} + \sankeyoutin{U}{U2} + \coordinate (U label) at (U -| EB label); + \sankeyend{U2} + } + + \sankeyadvance{P-NV-U}{10mm} + \sankeyfork{P-NV-U}{327.2/P-NV-U-SD,0.4/SD} + + { + \sankeyturnright{SD}{90} + \sankeyadvance{SD}{15mm} + \coordinate (SD label) at (SD); + \sankeyadvance{SD}{15mm} + \sankeyend{SD} + } + + \sankeyadvance{P-NV-U-SD}{8mm} + \sankeyfork{P-NV-U-SD}{18.8/VE,308.4/E} + + { + \sankeyset{fill/.append style={orange!70!gray!30}} + \sankeyturnleft{VE}{90} + \sankeynode{as=VE,name=VE2,at=VE -| EB} + \sankeyoutin{VE}{VE2} + \coordinate (VE label) at (VE -| EB label); + \sankeyend{VE2} + } + + \sankeyadvance{E}{8mm} + \coordinate (E label) at (E); + \sankeyadvance{E}{20mm} + \sankeyfork{E}{135.1/H+GHD,87.2/V,86.1/In} + + \sankeyturnright{In}{90} + \sankeyadvance{In}{10mm} + \sankeyturnleft{In}{90} + \sankeyadvance{In}{5mm} + \coordinate (In label) at (In); + \sankeyadvance{In}{10mm} + \sankeyend{In} + + \sankeynode{as=V,name=V2,at=V|-In label} + \sankeyoutin{V}{V2} + \coordinate (V label) at (V2); + \sankeyadvance{V2}{10mm} + \sankeyend{V2} + + \sankeyturnleft{H+GHD}{90} + \sankeyadvance{H+GHD}{5mm} + \sankeyfork{H+GHD}{47.0/GHD,88.1/H} + + \sankeyturnright{H}{90} + \sankeynode{as=H,name=H2,at=H|-In label} + \sankeyoutin{H}{H2} + \coordinate (H label) at (H2); + \sankeyadvance{H2}{10mm} + \sankeyend{H2} + + \sankeyadvance{GHD}{30mm} + \sankeyturnright{GHD}{90} + \sankeynode{as=GHD,name=GHD2,at=GHD|-In label} + \sankeyoutin{GHD}{GHD2} + \coordinate (GHD label) at (GHD2); + \sankeyadvance{GHD2}{10mm} + \sankeyend{GHD2} + \end{sankeydiagram} + + % labels + \tikzset{ + label/.style={ + fill=white,fill opacity=.8,text opacity=1, + inner sep=1mm, + text=cyan!50!blue!50!black, + inner xsep=2mm, + font=\sffamily\bfseries\footnotesize, + align=center, + }, + } + \node[label,anchor=north] (B label) at (B label) {7.2}; + \node[label,left=1mm of B label] {Bestands-\\entnahme}; + \node[label,anchor=north] at (GI label) {137.3}; + \node[label,above=5mm of GI label] {Gewinnung\\im Inland}; + \node[label,anchor=north] at (I label) {397.8}; + \node[label,above=5mm of I label] {Import}; + + \node[label] at (EI label) {542.3\\Energieaufkommen im Inland}; + + \node[label,anchor=center] (EB label) at (EB label) {63.1}; + \node[label,above=1mm of EB label] {Export und\\Bunkerung}; + + \node[label] at (P label) {479.2\\Primärenergieverbrauch}; + + \node[label,anchor=center] (NV label) at (NV label) {33.5}; + \node[label,above=0mm of NV label] {Nichtenergetischer Verbrauch}; + + \node[label,anchor=center] (U label) at (U label) {118.1}; + \node[label,below=3mm of U label] {Umwandlungsverluste}; + + \node[label,anchor=center] (SD label) at (SD label) {0.4}; + \node[label,above=0mm of SD label] {Statistische\\Differenzen}; + + \node[label,anchor=center] (VE label) at (VE label) {18.8}; + \node[label,below=0mm of VE label] {Verbrauch in den\\Energiesktoren}; + + \node[label,anchor=north] (E label) at (E label) + {308.4\\Endenergieverbrauch}; + + \node[label,anchor=north] (In label) at (In label) {86.1}; + \node[label,anchor=north,below=1cm of In label] {Industrie}; + + \node[label,anchor=north] (V label) at (V label) {87.2}; + \node[label,anchor=north,below=1cm of V label] {Verkehr}; + + \node[label,anchor=north] (H label) at (H label) {88.1}; + \node[label,anchor=north,below=1cm of H label] {Haushalte}; + + \node[label,anchor=north] (GHD label) at (GHD label) {47.0}; + \node[label,anchor=north,below=1cm of GHD label] + {Gewerbe, Handel\\Diensleistungen}; +\end{tikzpicture} +%</example2> +% \fi +% +%^^A % ------------------------------------------------------------ +% \clearpage +% \section{Reproduction of an example from Google Charts documentation} +%^^A % ------------------------------------------------------------ +% +% \changes{v3.0}{2021/03/14}{add the reproduction of an example from +% Google Charts documentation} +% +% \embedfile[mimetype=text/plain]{sankey-example3.tex} +% +% This example is a reproduction of an example of Google +% Charts Documentation\footnote{\url{https://developers.google.com/chart/interactive/docs/gallery/sankey}}. +% +% See figure \vref{fig:google-example}. The \code{sankey-example3.tex} +% file contains the following code and is an attachement of the current +% PDF document. +% +% \begin{figure} +% \centering +% {\MakePercentComment\input{sankey-example3}} +% \caption{Reproduction of an example from Google Charts +% documentation} +% \label{fig:google-example} +% \end{figure} +% +% \lstinputlisting[style=LaTeXsmall]{sankey-example3} +% +% \iffalse +%<*example3> +\begin{tikzpicture} + \begin{sankeydiagram}%[debug] + \sffamily + \sankeyset{ + ratio=1cm/10, + outin steps=2, + draw/.style={draw=none,line width=0pt}, + color/.style={fill/.style={fill=#1,fill opacity=.75}}, + shade/.style 2 args={fill/.style={left color=#1, + right color=#2,fill opacity=.5}}, + % colors + @define HTML color/.code args={#1/#2}{\definecolor{#1}{HTML}{#2}}, + @define HTML color/.list={ + cyan/a6cee3,lime/b2df8a,red/fb9a99,orange/fdbf6f, + violet/cab2d6,yellow/ffff99,blue/1f78b4,green/33a02c + }, + % colors of countries + @let country color/.code args={#1/#2}{\colorlet{#1}[rgb]{#2}}, + @let country color/.list={ + CA/red,US/orange,MX/orange,BR/cyan,FR/lime,GB/red, + SP/lime,PT/cyan,ML/blue,SN/violet,MA/yellow, + AO/violet,ZA/yellow,IN/green,JP/green,CN/blue + }, + } + \def\vdist{5mm} + \def\hwidth{.5em} + \def\hdist{4.1cm} + + \sankeynode{name=CA,quantity=7} + \sankeynode{name=US,quantity=8,at={[yshift=\vdist]CA.left},anchor=right} + \sankeynode{name=MX,quantity=8,at={[yshift=\vdist]US.left},anchor=right} + \sankeynode{name=BR,quantity=8,at={[yshift=\vdist]MX.left},anchor=right} + + \foreach \country in {CA,US,MX,BR}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \sankeyfork{CA}{1/CA-to-PT,1/CA-to-GB,5/CA-to-FR} + \sankeyfork{US}{1/US-to-PT,1/US-to-SP,5/US-to-GB,1/US-to-FR} + \sankeyfork{MX}{1/MX-to-PT,5/MX-to-SP,1/MX-to-GB,1/MX-to-FR} + \sankeyfork{BR}{5/BR-to-PT,1/BR-to-SP,1/BR-to-GB,1/BR-to-FR} + + \sankeynode{name=FR,quantity=11, + at={[xshift=\hdist]CA.right},anchor=right} + \sankeynode{name=GB,quantity=11, + at={[yshift=\vdist]FR.left},anchor=right} + \sankeynode{name=SP,quantity=7, + at={[yshift=\vdist]GB.left},anchor=right} + \sankeynode{name=PT,quantity=8, + at={[yshift=\vdist]SP.left},anchor=right} + + \sankeyfork{FR} + {1/FR-from-BR,1/FR-from-MX,1/FR-from-US,5/FR-from-CA,3/FR-from-00} + \sankeyfork{GB} + {1/GB-from-BR,1/GB-from-MX,5/GB-from-US,1/GB-from-CA,3/GB-from-00} + \sankeyfork{SP}{1/SP-from-BR,5/SP-from-MX,1/SP-from-US} + \sankeyfork{PT}{5/PT-from-BR,1/PT-from-MX,1/PT-from-US,1/PT-from-CA} + + \foreach \country in {FR,GB,SP,PT}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \sankeyfork{FR}{1/FR-to-ZA,1/FR-to-AO,3/FR-to-MA,3/FR-to-SN,3/FR-to-ML} + \sankeyfork{GB}{7/GB-to-ZA,1/GB-to-AO,2/GB-to-MA,1/GB-to-SN} + \sankeyfork{SP}{1/SP-to-ZA,3/SP-to-MA,1/SP-to-SN,2/SP-to-00} + \sankeyfork{PT}{3/PT-to-ZA,2/PT-to-AO,1/PT-to-MA,1/PT-to-SN,1/PT-to-00} + + \sankeynode{name=ML,quantity=9, + at={[xshift=\hdist]FR.right},anchor=right} + \sankeynode{name=SN,quantity=9, + at={[yshift=\vdist]ML.left},anchor=right} + \sankeynode{name=MA,quantity=9, + at={[yshift=\vdist]SN.left},anchor=right} + \sankeynode{name=AO,quantity=9, + at={[yshift=\vdist]MA.left},anchor=right} + \sankeynode{name=ZA,quantity=12, + at={[yshift=\vdist]AO.left},anchor=right} + + \sankeyfork{ML}{3/ML-from-FR,6/Mail-from-00} + \sankeyfork{SN} + {1/SN-from-PT,1/SN-from-SP,1/SN-from-GB,3/SN-from-FR,3/SN-from-00} + \sankeyfork{MA}{1/MA-from-PT,3/MA-from-SP,2/MA-from-GB,3/MA-from-FR} + \sankeyfork{AO}{2/AO-from-PT,1/AO-from-GB,1/AO-from-FR,5/AO-from-00} + \sankeyfork{ZA}{3/ZA-from-PT,1/ZA-from-SP,7/ZA-from-GB,1/ZA-from-FR} + + \foreach \country in {ML,SN,MA,AO,ZA}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \sankeyfork{ML}{5/ML-to-CN,3/ML-to-JP,1/ML-to-IN} + \sankeyfork{SN}{5/SN-to-CN,3/SN-to-JP,1/SN-to-IN} + \sankeyfork{MA}{5/MA-to-CN,3/MA-to-JP,1/MA-to-IN} + \sankeyfork{AO}{5/AO-to-CN,3/AO-to-JP,1/AO-to-IN} + \sankeyfork{ZA}{5/ZA-to-CN,3/ZA-to-JP,1/ZA-to-IN,3/ZA-to-00} + + \sankeynode{name=IN,quantity=5, + at={[xshift=\hdist]ML.right},anchor=right} + \sankeynode{name=JP,quantity=15, + at={[yshift=\vdist]IN.left},anchor=right} + \sankeynode{name=CN,quantity=25, + at={[yshift=\vdist]JP.left},anchor=right} + + \sankeyfork{IN} + {1/IN-from-ZA,1/IN-from-AO,1/IN-from-MA,1/IN-from-SN,1/IN-from-ML} + \sankeyfork{JP} + {3/JP-from-ZA,3/JP-from-AO,3/JP-from-MA,3/JP-from-SN,3/JP-from-ML} + \sankeyfork{CN} + {5/CN-from-ZA,5/CN-from-AO,5/CN-from-MA,5/CN-from-SN,5/CN-from-ML} + + \foreach \country in {IN,JP,CN}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \foreach \startcountry/\countries in { + CA/{PT,GB,FR}, US/{PT,SP,GB,FR}, MX/{PT,SP,GB,FR}, + BR/{PT,SP,GB,FR}, FR/{ML,SN,MA,AO,ZA}, GB/{SN,MA,AO,ZA}, + SP/{SN,MA,ZA}, PT/{SN,MA,AO,ZA}, ML/{IN,JP,CN}, + SN/{IN,JP,CN}, MA/{IN,JP,CN}, AO/{IN,JP,CN}, + ZA/{IN,JP,CN}} + { + \foreach \endcountry in \countries { + \sankeyoutin[shade={\startcountry}{\endcountry}] + {\startcountry-to-\endcountry}{\endcountry-from-\startcountry} + } + } + + \foreach \country/\countryname in {CA/Canada, US/USA, MX/Mexico, + BR/Brazil, FR/France, GB/England, SP/Spain, PT/Portugal} + { + \node[anchor=west,inner sep=.1em,font=\small] + at (\country) {\countryname\vphantom{Ag}}; + } + + \foreach \country/\countryname in { + ML/Mali, SN/Senegal, MA/Morocco, AO/Angola, + ZA/South Africa, IN/India, JP/Japan, CN/China} + { + \node[anchor=east,inner sep=.1em,font=\small] + at (\country-old) {\countryname\vphantom{Ag}}; + } + \end{sankeydiagram} +\end{tikzpicture} +%</example3> +% \fi +% +%^^A % ------------------------------------------------------------ +% \subsection{Variation} +%^^A % ------------------------------------------------------------ +% +% Here is a variation of the previous example using the \code{rotate} +% key. +% +% See figure \vref{fig:google-example-variation}. The +% \code{sankey-example3-variation.tex} file contains the following code +% and is an attachement of the current PDF document. +% +% \begin{figure} +% \centering +% {\MakePercentComment\input{sankey-example3-variation}} +% \caption{Reproduction of an example from Google Charts documentation +% -- variation using the \protect\texttt{rotate} key.} +% \label{fig:google-example-variation} +% \end{figure} +% +% \lstinputlisting[style=LaTeXsmall]{sankey-example3-variation} +% +% \iffalse +%<*example3-variation> +\begin{tikzpicture}[rotate=-90] + \begin{sankeydiagram}[rotate=-90] + \sffamily + \sankeyset{ + ratio=1.7cm/10, + outin steps=2, + start style=arrow, + end style=simple, + draw/.style={draw=white,line width=.4pt}, + color/.style={fill/.style={fill=#1,fill opacity=.75}}, + shade/.style 2 args={fill/.style={ + fill=none,line width=0, + top color=#1,bottom color=#2, + middle color=#1!50!#2!50!white, + fill opacity=.75}}, + % colors + @define HTML color/.code args={#1/#2}{\definecolor{#1}{HTML}{#2}}, + @define HTML color/.list={ + cyan/a6cee3,lime/b2df8a,red/fb9a99,orange/fdbf6f, + violet/cab2d6,yellow/ffff99,blue/1f78b4,green/33a02c + }, + % colors of countries + @let country color/.code args={#1/#2}{\colorlet{#1}[rgb]{#2}}, + @let country color/.list={ + CA/red,US/orange,MX/lime,BR/violet,FR/yellow,GB/blue, + SP/green,PT/cyan,ML/cyan,SN/red,MA/orange, + AO/violet,ZA/lime,IN/blue,JP/yellow,CN/green + }, + } + \def\vdist{5mm} + \def\hwidth{1em} + \def\hdist{6cm} + + \sankeynode{name=CA,quantity=7} + \sankeynode{name=US,quantity=8,at={[yshift=\vdist]CA.left},anchor=right} + \sankeynode{name=MX,quantity=8,at={[yshift=\vdist]US.left},anchor=right} + \sankeynode{name=BR,quantity=8,at={[yshift=\vdist]MX.left},anchor=right} + + \foreach \country in {CA,US,MX,BR}{ + \sankeystart[color=\country]{\country} + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \sankeyfork{CA}{1/CA-to-PT,1/CA-to-GB,5/CA-to-FR} + \sankeyfork{US}{1/US-to-PT,1/US-to-SP,5/US-to-GB,1/US-to-FR} + \sankeyfork{MX}{1/MX-to-PT,5/MX-to-SP,1/MX-to-GB,1/MX-to-FR} + \sankeyfork{BR}{5/BR-to-PT,1/BR-to-SP,1/BR-to-GB,1/BR-to-FR} + + \sankeynode{name=FR,quantity=11, + at={[xshift=\hdist]CA.right},anchor=right} + \sankeynode{name=GB,quantity=11, + at={[yshift=\vdist]FR.left},anchor=right} + \sankeynode{name=SP,quantity=7, + at={[yshift=\vdist]GB.left},anchor=right} + \sankeynode{name=PT,quantity=8, + at={[yshift=\vdist]SP.left},anchor=right} + + \sankeyfork{FR} + {1/FR-from-BR,1/FR-from-MX,1/FR-from-US,5/FR-from-CA,3/FR-from-00} + \sankeyfork{GB} + {1/GB-from-BR,1/GB-from-MX,5/GB-from-US,1/GB-from-CA,3/GB-from-00} + \sankeyfork{SP}{1/SP-from-BR,5/SP-from-MX,1/SP-from-US} + \sankeyfork{PT}{5/PT-from-BR,1/PT-from-MX,1/PT-from-US,1/PT-from-CA} + + \foreach \country in {FR,GB,SP,PT}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \sankeyfork{FR}{1/FR-to-ZA,1/FR-to-AO,3/FR-to-MA,3/FR-to-SN,3/FR-to-ML} + \sankeyfork{GB}{7/GB-to-ZA,1/GB-to-AO,2/GB-to-MA,1/GB-to-SN} + \sankeyfork{SP}{1/SP-to-ZA,3/SP-to-MA,1/SP-to-SN,2/SP-to-00} + \sankeyfork{PT}{3/PT-to-ZA,2/PT-to-AO,1/PT-to-MA,1/PT-to-SN,1/PT-to-00} + + \sankeynode{name=ML,quantity=9, + at={[xshift=\hdist]FR.right},anchor=right} + \sankeynode{name=SN,quantity=9, + at={[yshift=\vdist]ML.left},anchor=right} + \sankeynode{name=MA,quantity=9, + at={[yshift=\vdist]SN.left},anchor=right} + \sankeynode{name=AO,quantity=9, + at={[yshift=\vdist]MA.left},anchor=right} + \sankeynode{name=ZA,quantity=12, + at={[yshift=\vdist]AO.left},anchor=right} + + \sankeyfork{ML}{3/ML-from-FR,6/Mail-from-00} + \sankeyfork{SN} + {1/SN-from-PT,1/SN-from-SP,1/SN-from-GB,3/SN-from-FR,3/SN-from-00} + \sankeyfork{MA}{1/MA-from-PT,3/MA-from-SP,2/MA-from-GB,3/MA-from-FR} + \sankeyfork{AO}{2/AO-from-PT,1/AO-from-GB,1/AO-from-FR,5/AO-from-00} + \sankeyfork{ZA}{3/ZA-from-PT,1/ZA-from-SP,7/ZA-from-GB,1/ZA-from-FR} + + \foreach \country in {ML,SN,MA,AO,ZA}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + } + + \sankeyfork{ML}{5/ML-to-CN,3/ML-to-JP,1/ML-to-IN} + \sankeyfork{SN}{5/SN-to-CN,3/SN-to-JP,1/SN-to-IN} + \sankeyfork{MA}{5/MA-to-CN,3/MA-to-JP,1/MA-to-IN} + \sankeyfork{AO}{5/AO-to-CN,3/AO-to-JP,1/AO-to-IN} + \sankeyfork{ZA}{5/ZA-to-CN,3/ZA-to-JP,1/ZA-to-IN,3/ZA-to-00} + + \sankeynode{name=IN,quantity=5, + at={[xshift=\hdist]ML.right},anchor=right} + \sankeynode{name=JP,quantity=15, + at={[yshift=\vdist]IN.left},anchor=right} + \sankeynode{name=CN,quantity=25, + at={[yshift=\vdist]JP.left},anchor=right} + + \sankeyfork{IN} + {1/IN-from-ZA,1/IN-from-AO,1/IN-from-MA,1/IN-from-SN,1/IN-from-ML} + \sankeyfork{JP} + {3/JP-from-ZA,3/JP-from-AO,3/JP-from-MA,3/JP-from-SN,3/JP-from-ML} + \sankeyfork{CN} + {5/CN-from-ZA,5/CN-from-AO,5/CN-from-MA,5/CN-from-SN,5/CN-from-ML} + + \foreach \country in {IN,JP,CN}{ + \sankeyadvance[color=\country]{\country}{\hwidth} + \sankeyend[color=\country]{\country} + } + + \foreach \startcountry/\countries in { + CA/{PT,GB,FR}, US/{PT,SP,GB,FR}, MX/{PT,SP,GB,FR}, + BR/{PT,SP,GB,FR}, FR/{ML,SN,MA,AO,ZA}, GB/{SN,MA,AO,ZA}, + SP/{SN,MA,ZA}, PT/{SN,MA,AO,ZA}, ML/{IN,JP,CN}, + SN/{IN,JP,CN}, MA/{IN,JP,CN}, AO/{IN,JP,CN}, + ZA/{IN,JP,CN}} + { + \foreach \endcountry in \countries { + \sankeyoutin[shade={\startcountry}{\endcountry}] + {\startcountry-to-\endcountry}{\endcountry-from-\startcountry} + } + } + + + \foreach \country/\countryname in {CA/Canada, US/USA, MX/Mexico, + BR/Brazil, FR/France, GB/England, SP/Spain, PT/Portugal} + { + \node[anchor=south,inner sep=.1em,font=\small] + at (\country) {\countryname\vphantom{Ag}}; + } + + \foreach \country/\countryname in { + ML/Mali, SN/Senegal, MA/Morocco, AO/Angola, + ZA/South Africa, IN/India, JP/Japan, CN/China} + { + \node[anchor=south,inner sep=.1em,font=\small] + at (\country) {\countryname\vphantom{Ag}}; + } + \end{sankeydiagram} +\end{tikzpicture} +%</example3-variation> +% \fi +% +%^^A % ------------------------------------------------------------ +% \clearpage +% \section{Very nice example -- Nadieh Bremer creation} +%^^A % ------------------------------------------------------------ +% +% \embedfile[mimetype=text/plain]{sankey-example4.tex} +% +% \begin{figure} +% \centering +% {\MakePercentComment\input{sankey-example4}} +% \caption{Very nice example -- Nadieh Bremer's creation} +% (from +% \href{https://www.visualcinnamon.com/portfolio/adyen-report-2019/}{Adyen's +% Shareholder Report}) +% \label{fig:nice-example} +% \end{figure} +% +% Graphic designer Nadieh Bremer created this very nice Sankey +% diagram\footnote{\url{https://www.visualcinnamon.com/portfolio/adyen-report-2019/}} +% for Adyen's second half 2018 report to shareholders. It is coded here +% with her kind permission. +% +% You can change the data values between lines 28 and 53. +% +% See figure~\vref{fig:nice-example}. The \code{sankey-example4.tex} +% file contains the following code and is an attachement of the current +% PDF document. +% +% \lstinputlisting[numbers=left,style=LaTeXsmall]{sankey-example4} +% +% \iffalse +%<*example4> +\begin{tikzpicture} + \renewcommand*\sfdefault{txss} + \sffamily + \sisetup{ + detect-all=true, + group-separator={,}, + group-minimum-digits=4, + } + % storage of labels + \newcommand\LabSet[2]{% node name, label + \expandafter\edef\csname#1@Lab\endcsname{#2}} + \newcommand\Lab[1]{% node name + \csname#1@Lab\endcsname} + % storage of quantities + \newcommand\QtySet[2]{% node name, quantity + \expandafter\edef\csname#1@Qty\endcsname{\fpeval{#2}}} + \newcommand\Qty[1]{% node name + \csname#1@Qty\endcsname} + % all nodes with their name, label and quantity + \sankeyset{ + def data/.code args={#1/#2/#3}{% node name/label/values + \LabSet{#1}{#2} + \QtySet{#1}{#3} + \typeout{#1: \Qty{#1}€ (\Lab{#1})} + }, + def data/.list={ + {Pf/Processing\\fees/71713}, + {Sog/Sales of\\good/4547}, + {Sf/Settlement\\fees/842075}, + {Os/Other\\services/37532}, + {R/Revenues/\Qty{Pf}+\Qty{Sog}+\Qty{Sf}+\Qty{Os}}, + {Coi/Cost of Inventory/5151}, + {Ciffi/Cost insecure from financial institutions/758234}, + {Nr/Net revenue/\Qty{R}-\Qty{Coi}-\Qty{Ciffi}}, + {Aadotaifa/Amortization and\\depreciation of tangible and\\ + intangible fixed assets/4688}, + {Ssapc/Social securities and\\pension costs/7860}, + {Was/Wages and salaries/35627}, + {Ooe/Other operating expenses/37346}, + {Nr2/-/\Qty{Nr}-\Qty{Aadotaifa}-\Qty{Ssapc}-\Qty{Was}-\Qty{Ooe}}, + {Oi/Other income/47}, + {Ibiiieait/Income before interest income,\\interest expense and + income taxes/\Qty{Nr2}+\Qty{Oi}}, + {Fe/Finance expense/561}, + {Ofr/Other financial results/2533}, + {Ibiiieait2/-/\Qty{Ibiiieait}-\Qty{Fe}-\Qty{Ofr}}, + {Fi/Finance income/204}, + {Ibit/Income before income taxes/\Qty{Ibiiieait2}+\Qty{Fi}}, + {It/Income taxes/21134}, + {Niftp/Net income for the period/\Qty{Ibit}-\Qty{It}}, + {Octa/Other currency\\translation adjustments/785}, + {Tci/Total comprehensive income/\Qty{Niftp}+\Qty{Octa}} + }, + } + + \definecolor{mygreen}{RGB}{9,192,82} + \tikzset{ + cost node/.style={ + overlay, + align=flush center, + node font=\footnotesize\sffamily\bfseries, + inner sep=0, + node contents={% + {\mdseries€\,\num{\Qty{#1}}}\\ + \Lab{#1}\vphantom{g}% + }, + }, + white hash/.style={ + draw=none,fill=none, + pattern={Lines[angle=60,line width=2pt,distance=4pt]}, + pattern color=white, + }, + line sep/.style={draw=white,line width=1pt}, + left label/.style={left=#1,align=flush right,anchor=north east}, + right label/.style={right=#1,align=flush left}, + right label hashed/.style={ + right=1mm of $(#1.left)!.5!(#1-old.left)$,align=flush left, + }, + left label hashed/.style={ + left=1mm of $(#1.right)!.5!(#1-old.right)$,align=flush right, + }, + } + + \newcommand\turnandstop[1]{ + \sankeyturn[green to greenwhite]{#1}{-90} + \sankeynode{as=#1,name=#1-e,at={#1 -| Coi}} + \sankeyoutin[greenwhite to white]{#1}{#1-e} + \node[cost node=#1,left label={1mm of #1-e.right}]; + } + + \begin{sankeydiagram}%[debug] + \sankeyset{ + ratio=28em/1000000, + minimum radius=2cm, + start style=none, + every node/.style={angle=-90}, + % default fill and draw styles + fill/.style={ + line width=0pt, + fill=mygreen, + }, + draw/.style={draw=none}, + % specific fill and draw styles + green to greenwhite/.style={ + fill/.style={ + line width=0pt, + right color=mygreen, + left color=mygreen!20!white, + } + }, + greenwhite to white/.style={ + fill/.style={ + line width=0pt, + right color=mygreen!20!white, + left color=mygreen!5!white, + } + }, + dashed/.style={draw/.style={draw=mygreen,dashed}}, + } + + \coordinate (top) at (0,2em); + + \sankeynodestart{name=Pf,quantity=\Qty{Pf}} + \node[cost node=Pf,above=.5em of Pf.center]; + + \sankeynodestart{name=Sog,quantity=\Qty{Sog}, + at={[xshift=4em]Pf.left},anchor=right} + \node[cost node=Sog,above=.5em of Sog.center]; + + \sankeynodestart{name=Sf,quantity=\Qty{Sf}, + at={[xshift=2em]Sog.left},anchor=right} + \node[cost node=Sf,above=.5em of Sf.center]; + + \sankeynodestart{name=Os,quantity=\Qty{Os}, + at={[xshift=2em]Sf.left},anchor=right} + \node[cost node=Os,above=.5em of Os.center]; + + \sankeynode{ + name=R,quantity=\Qty{R},at={[yshift=-10em]Sf.center}, + forked={\Qty{Os}/Os-a,\Qty{Sf}/Sf-a,\Qty{Sog}/Sog-a,\Qty{Pf}/Pf-a}, + } + + \foreach \nodename in {Pf,Sog,Sf,Os}{ + \sankeyoutin[fill/.style={top color=white,bottom color=mygreen}] + {\nodename}{\nodename-a} + } + + \sankeyadvance{R}{1em} + \node[cost node=R,right label hashed=R]; + + \sankeyfork{R}{\Qty{Ciffi}/Ciffi,\Qty{Nr}/Nr,\Qty{Coi}/Coi} + + \sankeyturnleft[minimum radius=1.cm]{Ciffi}{90} + \node[cost node=Ciffi,at={([shift={(1mm,0)}]Ciffi.center)},rotate=-90, + anchor=south,align=flush left,node font=\scriptsize\sffamily\bfseries]; + + \sankeyturnright[green to greenwhite]{Coi}{90} + \sankeyadvance[greenwhite to white]{Coi}{1em} + \node[cost node=Coi,left={1mm of [yshift=.75ex]Coi.left}, + align=flush right,anchor=north east,overlay]; + + \sankeyadvance{Nr}{9em} + \sankeyadvance{Nr}{1em} + \node[cost node=Nr,left label hashed=Nr, + node font=\large\sffamily\bfseries]; + + \sankeyfork{Nr}{\Qty{Nr2}/Nr2,\Qty{Ooe}/Ooe, + \Qty{Was}/Was,\Qty{Ssapc}/Ssapc,\Qty{Aadotaifa}/Aadotaifa} + + \turnandstop{Aadotaifa} + + \sankeyadvance{Ssapc}{5em} + \turnandstop{Ssapc} + + \sankeyadvance{Was}{9em} + \turnandstop{Was} + + \sankeyadvance{Ooe}{12em} + \turnandstop{Ooe} + + \sankeyadvance{Nr2}{15em} + \sankeynode{name=Ibiiieait,quantity=\Qty{Ibiiieait}, + anchor=right,at={Nr2.right}, + forked={\Qty{Oi}/Oi,\Qty{Nr2}/Nr2-e}} + + \sankeyturnleftbackward[minimum radius=1cm,dashed]{Oi}{90} + \node[cost node=Oi,right label=1mm of Oi.left]; + + \sankeyadvance{Ibiiieait}{1em} + \node[cost node=Ibiiieait,right label hashed=Ibiiieait]; + + \sankeyfork{Ibiiieait} + {\Qty{Ibiiieait2}/Ibiiieait2,\Qty{Ofr}/Ofr,\Qty{Fe}/Fe} + + \turnandstop{Fe} + + \sankeyadvance{Ofr}{3em} + \turnandstop{Ofr} + + \sankeyadvance{Ibiiieait2}{6em} + \sankeynode{name=Ibit,quantity={\Qty{Ibiiieait2}+\Qty{Fi}}, + anchor=right,at={Ibiiieait2.right}, + forked={\Qty{Fi}/Fi,\Qty{Ibiiieait2}/Ibiiieait2-e}} + + \sankeyturnleftbackward[minimum radius=1cm,dashed]{Fi}{90} + \node[cost node=Fi,right label=1mm of Fi.left]; + + \sankeyadvance{Ibit}{1em} + \node[cost node=Ibit,right label hashed=Ibit]; + + \sankeyfork{Ibit}{\Qty{Niftp}/Niftp,\Qty{It}/It} + + \turnandstop{It} + + \sankeyadvance{Niftp}{6em} + + \sankeyadvance{Niftp}{1em} + \node[cost node=Niftp,right label hashed=Niftp]; + + \sankeynode{name=Tci,quantity=\Qty{Niftp}+\Qty{Octa}, + anchor=right,at={[yshift=-6em]Niftp.right}, + forked={\Qty{Octa}/Octa,\Qty{Niftp}/Niftp-e}} + \sankeyoutin{Niftp}{Niftp-e} + + \sankeyturnleftbackward[minimum radius=1cm]{Octa}{90} + \node[cost node=Octa,right label=1mm of Octa.left]; + + \sankeyadvance{Tci}{1em} + \node[cost node=Tci,right label hashed=Tci]; + + \newcommand\hashband[1]{ + \draw[line sep] (#1-old.right) -- (#1-old.left); + \draw[line sep] (#1.right) -- (#1.left); + \path[white hash] (#1-old.right) rectangle (#1.left); + } + + \foreach \nodename in {R,Nr,Nr,Ibiiieait,Ibit,Niftp,Tci}{ + \hashband{\nodename} + } + + \end{sankeydiagram} +\end{tikzpicture} +%</example4> +% \fi +% +% \clearpage +% +% \StopEventually{} +%^^A % ------------------------------------------------------------ +% +% \manualparts +% +% \part{Implementation} +% \label{implementation} +%^^A % ------------------------------------------------------------ +% +% { +% \setlength{\parskip}{0pt} +% \localtableofcontents +% } +% +%^^A % ------------------------------------------------------------ +% \section{The \texttt{sankey.sty} file} +%^^A % ------------------------------------------------------------ +% +% Poorly commented source code... +% +% \changes{v1.0}{2016/03/06}{first version} +% \changes{v2.0}{2021/01/27}{first public version (on CTAN)} +% \changes{v3.0}{2021/03/14}{better naming rule} +% \changes{v3.0}{2021/03/14}{use .ins and .dtx files} +% +% \iffalse +%<*sankey> +% \fi +% +% Version information: +% +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e}[2015/10/01] +\ProvidesPackage{sankey}[2021/03/14 v3.0 to draw Sankey diagrams] +% \end{macrocode} +% +% All required packages and TikZ libraries: +% \begin{macrocode} +\RequirePackage{xparse} +\RequirePackage{etoolbox} +\RequirePackage{xfp} +\RequirePackage{tikz} +\usetikzlibrary{ + calc, + decorations.markings, + dubins +} +% \end{macrocode} +% +% Declarations of PGF layers (to debug Sankey diagrams): +% +% \begin{macrocode} +%% add a new layer to debug sankey diagrams +\pgfdeclarelayer{background} +\pgfdeclarelayer{foreground} +\pgfdeclarelayer{sankeydebug} +\pgfsetlayers{background,main,foreground,sankeydebug} +% \end{macrocode} +% +% +%^^A % ------------------------------------------------------------ +% \subsection{Fields} +%^^A % ------------------------------------------------------------ +% +% \begin{macro}{\snk@newfield} +% +% The \code{sankeynewfield} macro defines +% setter and getter macros for \emph{key}/\emph{value} pairs. +% It requires five parameters: the \emph{def} macro used to +% store a new value, the \emph{setter} macro name, the \emph{getter} macro name, +% the \emph{cs name} used by the new field (including a \texttt{\#1} +% parameter -- the \emph{key}) and the \emph{error message} (used by the getter +% macro if the key is not defined). +% +% The \emph{setter} macro requires +% two parameters: the key and the value. +% The \emph{getter} macro requires +% one parameter: the key. +% +% \begin{macrocode} +\def\snk@newfield#1#2#3#4#5{ + % setter + \def#2##1##2{\expandafter#1\csname #4\endcsname{##2}} + % getter + \def#3##1{% + \ifcsdef{#4}{% + \csname#4\endcsname% + }{% + \PackageError{sankey}{#5}{unknown key with \string#3}% + }% + } +} +% \end{macrocode} +% \end{macro} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Definition of \emph{global} and \emph{expanded} fields (using +% \texttt{\protect\string\xdef})} +%^^A % ------------------------------------------------------------ +% +% \begin{macro}{\snk@setnodeqty} +% \begin{macro}{\sankeygetnodeqty} +% The setter and getter macros to store and retrieve +% the \emph{quantity} field associated with +% each Sankey node (the key is the name of the Sankey node). +% \begin{macrocode} +\snk@newfield\xdef\snk@setnodeqty\sankeygetnodeqty% +{@snk@node@qty@#1}{Unknown sankey node '#1'} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\snk@setnodeorient} +% \begin{macro}{\sankeygetnodeorient} +% The setter and getter macros to store and retrieve +% the \emph{angle} (or orientation) field +% associated with each Sankey node (the key is the name of the Sankey node). +% \begin{macrocode} +\snk@newfield\xdef\snk@setnodeorient\sankeygetnodeorient% +{@snk@node@orient@#1}{Unknown sankey node '#1'} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Definitions of \emph{local} fields (using \texttt{\protect\string\def})} +%^^A % ------------------------------------------------------------ +% +% \begin{macro}{\snk@setstartfill} +% \begin{macro}{\snk@getstartfill} +% \begin{macro}{\snk@setstartdraw} +% \begin{macro}{\snk@getstartdraw} +% The setter and getter macros to store and retrieve the starting fill/draw +% paths (the key is the style name). +% \begin{macrocode} +\snk@newfield\def\snk@setstartfill\snk@getstartfill% +{@snk@start@fill@#1}{Unknown sankey start fill path #1} + +\snk@newfield\def\snk@setstartdraw\snk@getstartdraw% +{@snk@start@draw@#1}{Unknown sankey start draw path #1} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\snk@setendfill} +% \begin{macro}{\snk@getendfill} +% \begin{macro}{\snk@setenddraw} +% \begin{macro}{\snk@getenddraw} +% The setter and getter macros to store and retrieve the ending fill/draw +% paths (the key is the style name). +% \begin{macrocode} +\snk@newfield\def\snk@setendfill\snk@getendfill% +{@snk@end@fill@#1}{Unknown sankey end fill path #1} + +\snk@newfield\def\snk@setenddraw\snk@getenddraw% +{@snk@end@draw@#1}{Unknown sankey end draw path #1} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Check if a sankey node is defined} +%^^A % ------------------------------------------------------------ +% +% \begin{macro}{\snk@ifnodedefined} + +% The \code{\snk@ifnodedefined} macro checks if a Sankey +% node is defined by checking if its name is associated to +% a \emph{quantity}. +% \begin{macrocode} +\newcommand\snk@ifnodedefined[3]{% + \ifcsdef{@snk@node@qty@#1}{#2}{#3}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\snk@errorifnotdefined} +% The \code{\snk@errorifnotdefined} macro generares +% an error message if the Sankye node is not defined. +% \begin{macrocode} +\newcommand\snk@errorifnotdefined[1]{% + \snk@ifnodedefined{#1}{}% + {\PackageError{sankey}{Unknown sankey node '#1'}{}}% +} +% \end{macrocode} +% \end{macro} +% +%^^A % ------------------------------------------------------------ +% \subsection{The \texttt{sankey node} shape} +%^^A % ------------------------------------------------------------ +% +% +% A \code{sankey node} is defined as a TikZ node +% with a particular \emph{shape}: its width is null and its +% height matches the associated \emph{quantity}. +% This shape requires only three anchors: \code{center}, \code{left} +% and \code{right}. +% These threee anchors are sufficient to use the +% \code{sankey} package. But the \code{fit} library needs +% anchors defined by rectangular node. +% +% \begin{macrocode} +\pgfdeclareshape{sankey node}{ + \inheritsavedanchors[from=rectangle] + \inheritanchor[from=rectangle]{center} + \inheritanchorborder[from=rectangle] + \anchor{left}{\pgf@process{\northeast}} + \anchor{right}{\pgf@process{\southwest}} + % compatibility with 'fit' library + \inheritanchor[from=rectangle]{west} + \inheritanchor[from=rectangle]{east} + \inheritanchor[from=rectangle]{north} + \inheritanchor[from=rectangle]{south} + \inheritanchor[from=rectangle]{north west} + \inheritanchor[from=rectangle]{south east} + \inheritanchor[from=rectangle]{north east} + \inheritanchor[from=rectangle]{south west} +} +% \end{macrocode} +% +%^^A % ------------------------------------------------------------ +% \subsection{Keys} +%^^A % ------------------------------------------------------------ +% +% \begin{macro}{\sankeyset} +% The \code{sankey} package uses \code{pgfkeys} to set options via +% \emph{key=value} pairs using the \texttt{/sankey} path +% (for Sankey diagram options) and using the +% \texttt{/sankey/node parameters} path (for Sankey node parameters). +% +% The \code{\sankeyset} macro processes +% its parameter as a list of comma separated pairs of the form +% \emph{key=value} with the default path set to \texttt{/sankey}. +% +% \begin{macrocode} +\pgfkeys{/sankey/.is family} +\NewDocumentCommand\sankeyset{m}{\pgfkeys{sankey,#1}} +% \end{macrocode} +% \end{macro} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Keys to define the scale} +%^^A % ------------------------------------------------------------ +% \begin{macro}{\snk@totalqty} +% \begin{macro}{\snk@totallen} +% +% The \code{ratio quantity}, \code{ratio length} and +% \code{ratio} keys define the ratio between +% \emph{flow quantity} and \emph{graphic length} (the scale). +% The \code{\snk@totalqty} and \code{\snk@totallen} macros store the values. +% All \emph{quantities} are processed by \code{\fpeval} and +% all \emph{lengths} are processed by \code{pgfmath}. +% \begin{macrocode} +\sankeyset{ + ratio quantity/.code={\edef\snk@totalqty{\fpeval{#1}}}, + ratio quantity/.value required, + ratio length/.code={ + \pgfmathsetmacro\snk@totallen{#1} + \edef\snk@totallen{\snk@totallen pt} + }, + ratio length/.value required, + ratio/.style args={#1/#2}{ + ratio length=#1, + ratio quantity=#2, + }, + ratio/.value required, +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Rotate offset} +%^^A % ------------------------------------------------------------ +% +% \begin{macro}{\snk@rotate} +% +% The \code{rotate} key stores an offset angle applied to all Sankey +% nodes. This is useful when using the \code{rotate} option within a +% \code{tikzpicture} or a \code{scope}. This TikZ option is only +% applied to coordinates and not to TikZ nodes (remember that Sankey +% nodes are TikZ nodes). It's up to the author to keep the +% \code{rotate} option of the \code{tikzpicture} and that of the +% \code{sankeydiagram} synchronous. +% +% \begin{macrocode} +\sankeyset{ + rotate/.code={\edef\snk@rotate{\fpeval{#1}}}, + rotate/.value required, +} +% \end{macrocode} +% \end{macro} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Minimum radius} +%^^A % ------------------------------------------------------------ +% +% \begin{macro}{\snk@minradius} +% +% The \code{minimum radius} key processes the minimum radius +% of curvature by \code{pgfmath} then stores it in +% the \code{\snk@minradius} macro. +% \begin{macrocode} +\sankeyset{ + minimum radius/.code={ + \pgfmathsetmacro\snk@minradius{#1} + \edef\snk@minradius{\snk@minradius pt} + }, + minimum radius/.value required, +} +% \end{macrocode} +% \end{macro} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Outin step} +%^^A % ------------------------------------------------------------ +% +% \begin{macro}{\snk@stepoutin} +% The \code{outin} key stores its value in +% the \code{\snk@stepoutin} macro. +% +% \begin{macrocode} +\sankeyset{ + outin steps/.estore in=\snk@stepoutin, + outon steps/.value required, +} +% \end{macrocode} +% \end{macro} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Sankey debug} +%^^A % ------------------------------------------------------------ +% +% +% The \code{debug} key drives the \code{sankey debug} toggle. +% +% \begin{macrocode} +\newtoggle{sankey debug} +\sankeyset{ + debug/.is choice, + debug/true/.code={\toggletrue{sankey debug}}, + debug/false/.code={\togglefalse{sankey debug}}, + debug/.default=true, +} +% \end{macrocode} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Start and end styles} +%^^A % ------------------------------------------------------------ +% +% \begin{macro}{\snk@startstyle} +% \begin{macro}{\snk@endstyle} +% The \code{start style} and \code{end style} keys are choices. +% +% The \code{new start style} and \code{new end style} keys +% add new option to these choices. +% They use the \code{startfill}, \code{startdraw} fields +% or the \code{endfill} and \code{enddraw} +% fields (using the style \emph{name} as key) to store the fill and draw +% paths then create a new option to install the new +% start (\code{\snk@startstyle}) or end (\code{\snk@endstyle}) style. +% +% \begin{macrocode} +\sankeyset{ + start style/.is choice, + end style/.is choice, + % to define new start and end styles + new start style/.code n args={3}{% name, fill path, draw path + \snk@setstartfill{#1}{#2} + \snk@setstartdraw{#1}{#3} + \sankeyset{start style/#1/.code={\def\snk@startstyle{#1}}} + }, + new end style/.code n args={3}{% name, fill path, draw path + \snk@setendfill{#1}{#2} + \snk@setenddraw{#1}{#3} + \sankeyset{end style/#1/.code={\def\snk@endstyle{#1}}} + }, +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Initial parameters} +%^^A % ------------------------------------------------------------ +% +% The \code{@initial options} style defines default values for +% options of Sankey diagram. The \code{every diagram} style (initially +% empty) allows the user to choose its own default values. +% +% The \code{@initial options} and the \code{every diagram} styles are +% applied (in this order) at the beginning of each Sankey diagram. +% +% \begin{macrocode} +\sankeyset{ + debug color/.style={/utils/exec={\colorlet{debug color}{#1}}}, + @initial options/.style={ + ratio=1cm/10, + minimum radius=5mm,% + outin steps=10, + debug=false, + start style=none, + end style=none, + rotate=0, + % default fill/draw styles, + fill/.style={line width=0pt,fill=white}, + draw/.style={draw=black,line width=.4pt}, + % debug color used by all debug macros + debug color=red!75!black, + % debug line between left and right anchors + debug line/.style={overlay,draw=debug color,|-|}, + % debug line between center and label + debug normal/.style={overlay,draw=debug color}, + % debug node label + debug label/.style={ + overlay, + draw, + font=\ttfamily\tiny, + text=debug color,text opacity=1, + inner sep=.1em, + fill=white,fill opacity=1, + rounded corners=.1em, + node contents={\name}, + }, + every node/.style={}, + }, + every diagram/.style={}, +} + +% \end{macrocode} +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Sankey node parameters} +%^^A % ------------------------------------------------------------ +% +% The \code{/sankey/node parameters} family defines all parameters during +% creation of Sankey node. +% +% \begin{macrocode} +\sankeyset{node parameters/.is family} +% \end{macrocode} +% \begin{macro}{\name} +% \begin{macro}{\qty} +% \begin{macro}{\orient} +% \begin{macro}{\pos} +% +% The \code{name}, \code{quantity}, \code{angle} and \code{at} keys use the +% \code{\name}, \code{\qty}, \code{\orient} and \code{\pos} macros +% to store the \emph{name}, the \emph{quantity}, the \emph{orientation} (or +% \emph{angle}) and the \emph{position} of a Sankey node during its +% creation. +% +% The \emph{quantity} is processed via \code{\fpeval}. The +% \emph{orientation} is normalized. +% +% \begin{macrocode} +\sankeyset{node parameters, + name/.estore in=\name, + name/.value required, + quantity/.code={\edef\qty{\fpeval{#1}}}, + quantity/.value required, + angle/.code={\edef\orient{\snk@normalize@angle{#1}}}, + angle/.value required, + at/.code={\snk@getpos\pos{#1}}, + at/.value required, +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% The \code{as} key is just a shortcut to define the four current node +% parameters by copying them from an existing Sankey node. +% +% \begin{macrocode} +\sankeyset{node parameters, + as/.style={ + name=#1, + quantity=\sankeygetnodeqty{#1}, + angle=\sankeygetnodeorient{#1}, + at={#1.center}, + }, + as/.value required, +} +% \end{macrocode} +% +% \begin{macro}{\snk@anchor} +% +% The \code{anchor} key stores in the \code{\snk@anchor} macro +% the anchor name to use to create the new current Sankey node +% +% \begin{macrocode} +\sankeyset{node parameters, + anchor/.is choice, + anchor/left/.code={\def\snk@anchor{left}}, + anchor/right/.code={\def\snk@anchor{right}}, + anchor/center/.code={\def\snk@anchor{center}}, + anchor/.value required, +} +% \end{macrocode} +% \end{macro} +% +% The \code{start} and \code{end} keys drive the +% \code{sankey node start} and \code{sankey node end} +% toggles. +% +% \begin{macrocode} +\newtoggle{sankey node start} +\newtoggle{sankey node end} +\sankeyset{node parameters, + start/.is choice, + start/true/.code={\toggletrue{sankey node start}}, + start/false/.code={\togglefalse{sankey node start}}, + start/.default=true, + % + end/.is choice, + end/true/.code={\toggletrue{sankey node end}}, + end/false/.code={\togglefalse{sankey node end}}, + end/.default=true, +} +% \end{macrocode} +% \begin{macro}{\snk@listofforks} +% \begin{macro}{\snk@forkanchor} +% +% The \code{forked} and \code{fork anchor} keys store their value in the +% \code{\snk@listofforks} and \code{\snk@forkanchor} macros. +% +% \begin{macrocode} +\sankeyset{node parameters, + forked/.estore in=\snk@listofforks, + forked/.value required, + fork anchor/.estore in=\snk@forkanchor, + fork anchor/.value required, +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% The \code{@initial parameters} style initialises all Sankey node +% parameters at the start of the creation of a new Sankey node. +% +% \begin{macrocode} +\sankeyset{node parameters, + @initial parameters/.style={ + start=false, + end=false, + forked=, + fork anchor=, + anchor=center, + at={0,0}, + angle=0, + }, +} +% \end{macrocode} +% +% +%^^A % ------------------------------------------------------------ +% \subsubsection{Internal Tikz style} +%^^A % ------------------------------------------------------------ +% +% To apply this style with Tikz, use absolute key name +% (\texttt{/sankey/@sankey node}). This style is used to create the Tikz +% node assoicated to a Sankey node. +% +% \begin{macrocode} +\sankeyset{ + % sankey node TikZ style + @sankey node/.style n args={3}{% name, pos, anchor + shape=sankey node, + inner sep=0, + minimum height={\sankeyqtytolen{\sankeygetnodeqty{#1}}}, + minimum width=0, + draw=none, + line width=0pt, + fill=none, + node contents={}, + rotate=\sankeygetnodeorient{#1}+\snk@rotate, + at={(#2)}, + name=#1, + anchor=#3, + }, +} +% \end{macrocode} +% +%^^A % ------------------------------------------------------------ +% \subsection{The \texttt{sankeydiagram} environment} +% ^^A % ------------------------------------------------------------ +% +% \begin{environment}{sankeydiagram} +% +% The \code{sankeydiagram} environment defines locally all the macros +% used by a Sankey diagram. Then it applies the % +% \code{@initial options} and \code{every diagram} styles (in this +% order) and applies all the keys provided in its optional argument. +% +% \begin{macrocode} +\NewDocumentEnvironment{sankeydiagram}{O{}}{ +% \end{macrocode} +% +%^^A % ------------------------------------------------------------ +% \subsection{Internal macros} +%^^A % ------------------------------------------------------------ +% +% \begin{macro}{\snk@getpos} +% +% The \code{\snk@getpos} macro extracts the position of a TikZ +% node\footnote{Thanks to Andrew Stacey \url{https://tex.stackexchange.com/a/33765/14500}}. +% +% \begin{macrocode} + \def\snk@getpos##1##2{% + \tikz@scan@one@point\pgfutil@firstofone(##2)\relax% + \edef##1{\the\pgf@x,\the\pgf@y}% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\snk@modulo} +% +% The \code{\snk@modulo} macro evaluates \#1 modulo \#2 using \code{\fpeval}. +% +% \begin{macrocode} + \def\snk@modulo##1##2{\fpeval{##1-(floor((##1)/(##2),0)*##2)}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\snk@normalize@angle} +% +% The \code{\snk@normalize@angle} macro normalizes \#1 (an angle) between +% $-180$ and $180$ (using \code{\fpeval}). +% +% \begin{macrocode} + \def\snk@normalize@angle##1{% + \fpeval{\snk@modulo{(##1)+180}{360}-180}% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\snk@show@debug} +% +% The \code{snk@show@debug} macro draws debug information +% of the Sankey node named \#1 but only if the \code{sankey debug} +% toogle is true. Everything is drawn on the \code{sankeydebug} +% layer. It uses the \code{/sankey/debug line}, +% \code{/sankey/debug normal} and \code{/sankey/debug label} Tikz styles. +% +% \begin{macrocode} + \def\snk@show@debug##1{% node name + \iftoggle{sankey debug}{ + \begingroup + \edef\name{##1} + \edef\qty{\sankeygetnodeqty{\name}} + \edef\orient{\sankeygetnodeorient{\name}} + \begin{pgfonlayer}{sankeydebug} + \path[/sankey/debug line] (\name.left) -- (\name.right); + \pgfmathsetmacro{\snk@len}{\sankeyqtytolen{\qty}/3} + \path[/sankey/debug normal] (\name.center) + -- ($(\name.center)!\snk@len pt!90:(\name.right)$) + node[/sankey/debug label,rotate=\orient+90+\snk@rotate,anchor=north]; + \end{pgfonlayer} + \endgroup + }{} + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\snk@makeforkednode} +% \begin{macro}{\snk@tot} +% \begin{macro}{\snk@subnodeqty} +% \begin{macro}{\snk@subnodename} +% \begin{macro}{\snk@added@values} +% +% The \code{\snk@makeforkednode} forks a Sankey node. +% +% \begin{macrocode} + \def\snk@makeforkednode{ + \begingroup + \ifdefempty{\snk@listofforks}{ + \ifdefempty{\snk@forkanchor}{}{ + \PackageWarning{sankey}% + {Can't use 'fork anchor' key without 'forked' key} + } + }{ + \def\snk@tot{0} + \def\snk@added@values{} + \sankeyset{ + @add forked node/.code args={####1/####2}{ + \coordinate (####2) at ($(\name.left)% + !\fpeval{(\snk@tot+.5*(####1))/\qty}% + !(\name.right)$); + \edef\snk@orient{\orient} + \sankeynode[debug=false] + {name=####2,quantity=####1,at=####2,angle=\snk@orient} + \edef\snk@tot{\fpeval{\snk@tot+####1}} + \edef\snk@added@values{\snk@added@values+####1} + }, + @add forked node/.list/.expand once=\snk@listofforks, + } + \edef\snk@diff{\fpeval{abs(\qty-\snk@tot)}} + \ifnumequal{\snk@diff}{0}{}{ + \PackageWarning{sankey}% + {^^J*** Warning: bad sankey fork: % + \qty\space!=\space\snk@added@values(=\snk@tot)% + ^^J\snk@listofforks} + } + \ifdefempty{\snk@forkanchor}{ + \edef\snk@forkanchor{\name.\snk@anchor} + }{} + \snk@getpos\snk@c{$(\snk@forkanchor) - (\pos)$} + \sankeynode{as=\name,at={$(\name) - (\snk@c)$}} + \foreach \snk@subnodeqty/\snk@subnodename in \snk@listofforks { + \sankeynode{as=\snk@subnodename,at={$(\snk@subnodename) - (\snk@c)$}} + } + } + \endgroup + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macro}{\snk@makenode} +% +% The \code{\snk@makenode} macro creates a new Sankey node named +% \code{\name} with \code{\qty} quantity, oriented at +% \code{\orient} degrees (but modified by the \code{\snk@rotate} +% angle offset), anchored by its \code{\anchor} (or its \emph{center} +% by default) at \code{\pos} position. +% +% \begin{macrocode} + \def\snk@makenode{ + \begingroup + \snk@setnodeqty{\name}{\qty} + \edef\orient{\snk@normalize@angle{\orient}} + \snk@setnodeorient{\name}{\orient} + \ifundef{\snk@anchor}{\def\snk@anchor{center}}{} + \node[/sankey/@sankey node={\name}{\pos}{\snk@anchor}]; + \endgroup + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\snk@filldrawstart} +% +% The \code{\snk@filldrawstart} macro fills +% (with the \code{/sankey/fill} TikZ style) then draws +% (with the \code{/sankey/draw} TikZ style) +% a start of flow using paths from style \code{\snk@startstyle} on +% the Sankey node named \code{\name}. +% +% \begin{macrocode} + \def\snk@filldrawstart{ + \begin{scope}[shift={(\name)},rotate=\orient] + \path[/sankey/fill] \snk@getstartfill{\snk@startstyle}; + \path[/sankey/draw] \snk@getstartdraw{\snk@startstyle}; + \end{scope} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\snk@filldrawend} +% +% The \code{\snk@filldrawend} macro fills +% (with the \code{/sankey/fill} TikZ style) then draws +% (with the \code{/sankey/draw} TikZ style) +% a end of flow using paths from style \code{\snk@endstyle} on +% the Sankey node named \code{\name}. +% +% \begin{macrocode} + \def\snk@filldrawend{ + \begin{scope}[shift={(\name)},rotate=\sankeygetnodeorient{\name}] + \path[/sankey/fill] \snk@getendfill{\snk@endstyle}; + \path[/sankey/draw] \snk@getenddraw{\snk@endstyle}; + \end{scope} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\snk@checkquantities} +% \begin{macro}{\snk@qtyi} +% \begin{macro}{\snk@qtyii} +% The \code{\snk@checkquantities} compares quantities +% from Sankey nodes \code{#1} and \code{#2} and emits +% an error message if they differ (\code{#3} is the name +% of the macro which requested the verification). +% +% \begin{macrocode} + \def\snk@checkquantities##1##2##3{ + \begingroup + \edef\snk@qtyi{\sankeygetnodeqty{##1}} + \edef\snk@qtyii{\sankeygetnodeqty{##2}} + \ifdefstrequal{\snk@qtyi}{\snk@qtyii}{}{ + \PackageError{sankey}% + {^^J*** \string##3: quantities differ between % + ##1 (\snk@qtyi) and ##2 (\snk@qtyii)% + ^^J}% + {The quantities of the two Sankey nodes must be equal.} + } + \endgroup + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +%^^A % ------------------------------------------------------------ +% \subsection{User macros} +%^^A % ------------------------------------------------------------ +% +% \begin{macro}{\sankeydubins} +% +% The \code{\sankeydubins} macro links two Sankey nodes via +% a Dubins path. First, it computes the Dubins path between +% centers (left and right radii are the same) and stores the +% result in \code{sankey}. Then it uses the stored result +% to fill and draw the lane (left border and right borders +% use Dubins paths with asymmetric radii). +% +% \begin{macrocode} + \NewDocumentCommand\sankeydubins{O{}mm}{% options, sn, en + \snk@errorifnotdefined{##2} + \snk@errorifnotdefined{##3} + \snk@checkquantities{##2}{##3}{\sankeydubins} + \begingroup + \sankeyset{##1} + \pgfmathsetmacro\qty{\sankeygetnodeqty{##2}} + \dubinspathset{ + sankey/.style={ + start point=##2.center,start angle=\sankeygetnodeorient{##2}, + end point=##3.center,end angle=\sankeygetnodeorient{##3}, + minimum radius=\snk@minradius + .5 * \sankeyqtytolen{\qty} pt, + }, + } + \dubinspathcalc{sankey,store=sankey} + \dubinspathset{ + left border/.style={ + sankey, use store=sankey, + left and right minimum radii={\snk@minradius} + and {\snk@minradius + \sankeyqtytolen{\qty} pt}, + }, + right border/.style={ + sankey, use store=sankey, + left and right minimum radii= + {\snk@minradius + \sankeyqtytolen{\qty} pt} + and {\snk@minradius}, + }, + } + % fill the region + \path[/sankey/fill] (##2.left) \dubinspath{left border} + -- (##3.left) -- (##3.right) \dubinspath{right border,reverse} + -- (##2.right) -- cycle; + % draw left and right borders + \path[/sankey/draw] (##2.left) \dubinspath{left border} + (##2.right) \dubinspath{right border}; + \endgroup + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sankeyoutin} +% +% The \code{\sankeyoutin} macro links two Sankey nodes via a Bézier curve. +% First, to simulate constant width, it creates \code{\snk@stepoutin} +% intermediate Sankey nodes along the Bézier curve. Then, the lane is +% filled and drawn linking all the intermediate Sankey node via smaller +% Bézier curves. +% +% \begin{macrocode} + \NewDocumentCommand\sankeyoutin{O{}mm}{% options, sn, en + \snk@errorifnotdefined{##2} + \snk@errorifnotdefined{##3} + \snk@checkquantities{##2}{##3}{\sankeyoutin} + \begingroup + \sankeyset{##1} + \edef\qty{\sankeygetnodeqty{##2}} + \pgfmathsetmacro\snk@len{\sankeyqtytolen{\qty}/2} + \edef\snk@step{\fpeval{1/\snk@stepoutin}} + \edef\snk@laststep{\inteval{\snk@stepoutin-1}} + \path[overlay,decorate,decoration={ + markings, + mark=between positions \snk@step and {\fpeval{1-.5*\snk@step}} + step \snk@step with { + \edef\snk@outinmidptname{% + snk@outinmidpt-% + \pgfkeysvalueof{/pgf/decoration/mark info/sequence number}% + } + \path + (0,0) coordinate(\snk@outinmidptname) + (0,-\snk@len pt) coordinate (\snk@outinmidptname-r) + (0,\snk@len pt) coordinate (\snk@outinmidptname-l) + ; + } + }] + (##2.center) + to[out=\sankeygetnodeorient{##2},in=\sankeygetnodeorient{##3}+180] + (##3.center); + \foreach \snk@ptnum in {1,...,\snk@laststep}{ + \edef\snk@outinmidptname{snk@outinmidpt-\snk@ptnum} + \dbp@anglebetween\snk@outinmidptangle% + {\snk@outinmidptname-r}{\snk@outinmidptname-l} + \sankeynode[debug=false]{% + name=\snk@outinmidptname, + quantity=\qty, + angle=\snk@outinmidptangle-90,% + at=\snk@outinmidptname% + } + } + \sankeynode[debug=false]{% + name={snk@outinmidpt-0}, + quantity=\sankeygetnodeqty{##2}, + angle=\sankeygetnodeorient{##2},% + at={##2}% + } + \sankeynode[debug=false]{% + name={snk@outinmidpt-\snk@stepoutin}, + quantity={\sankeygetnodeqty{##3}}, + angle={\sankeygetnodeorient{##3}},% + at={##3}% + } + \path[/sankey/fill,looseness=1] + (snk@outinmidpt-0.left) + \foreach \snk@curpt + [remember=\snk@curpt as \snk@prevpt (initially 0)] + in {1,...,\snk@stepoutin}{ + to[out=\sankeygetnodeorient{snk@outinmidpt-\snk@prevpt}, + in=\sankeygetnodeorient{snk@outinmidpt-\snk@curpt}+180] + (snk@outinmidpt-\snk@curpt.left) + } + -- + (snk@outinmidpt-\snk@stepoutin.right) + \foreach \snk@curpt + [remember=\snk@curpt as \snk@prevpt (initially \snk@stepoutin)] + in {\snk@laststep,...,0}{ + to[out=\sankeygetnodeorient{snk@outinmidpt-\snk@prevpt}+180, + in=\sankeygetnodeorient{snk@outinmidpt-\snk@curpt}] + (snk@outinmidpt-\snk@curpt.right) + } + -- cycle; + \path[/sankey/draw,looseness=1] + (snk@outinmidpt-0.left) + \foreach \snk@curpt + [remember=\snk@curpt as \snk@prevpt (initially 0)] + in {1,...,\snk@stepoutin}{ + to[out=\sankeygetnodeorient{snk@outinmidpt-\snk@prevpt}, + in=\sankeygetnodeorient{snk@outinmidpt-\snk@curpt}+180] + (snk@outinmidpt-\snk@curpt.left) + } + (snk@outinmidpt-\snk@stepoutin.right) + \foreach \snk@curpt + [remember=\snk@curpt as \snk@prevpt (initially \snk@stepoutin)] + in {\snk@laststep,...,0}{ + to[out=\sankeygetnodeorient{snk@outinmidpt-\snk@prevpt}+180, + in=\sankeygetnodeorient{snk@outinmidpt-\snk@curpt}] + (snk@outinmidpt-\snk@curpt.right) + }; + \endgroup + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\sankeynodealias} +% +% The \code{\sankeynodealias} macro clones the Sankey node +% named \code{#1} into a Sankey node named \code{#2}. +% +% \begin{macrocode} + \NewDocumentCommand\sankeynodealias{mm}{%name, alias + \snk@errorifnotdefined{##1} + \path[late options={name=##1,alias=##2}]; + \snk@setnodeqty{##2}{\sankeygetnodeqty{##1}} + \snk@setnodeorient{##2}{\sankeygetnodeorient{##1}} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sankeynode} +% +% The \code{\sankeynode} macro creates the new Sankey +% node named \code{#2}. +% +% \begin{macrocode} + \NewDocumentCommand\sankeynode{O{}m}{% options, node parameters + \begingroup + \sankeyset{##1} + \sankeyset{node parameters,@initial parameters,/sankey/every node,##2} + \snk@makenode{} + \snk@makeforkednode{} + \iftoggle{sankey node start}{\snk@filldrawstart}{} + \iftoggle{sankey node end}{\snk@filldrawend}{} + \snk@show@debug{\name} + \endgroup + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sankeystart} +% +% The \code{\sankeystart} macro fills and draws a starting lane +% attached to the Sankey node named \code{#2}. +% +% \begin{macrocode} + \NewDocumentCommand\sankeystart{O{}m}{% options, name + \snk@errorifnotdefined{##2} + \begingroup + \sankeyset{##1} + \edef\name{##2} + \edef\orient{\sankeygetnodeorient{##2}} + \edef\qty{\sankeygetnodeqty{##2}} + \snk@filldrawstart + \endgroup + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sankeynodestart} +% +% The \code{\sankeynodestart} macro creates the new Sankey +% node named \code{#2} then fills and draws a starting lane +% attached to this new Sankey node. +% +% \begin{macrocode} + \NewDocumentCommand\sankeynodestart{O{}m}{% option, node parameters + \sankeynode[##1]{start,##2} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sankeyend} +% +% The \code{\sankeyend} macro fills and draws an ending lane +% attached to the Sankey node named \code{#2}. +% +% \begin{macrocode} + \NewDocumentCommand\sankeyend{O{}m}{%options, name + \snk@errorifnotdefined{##2} + \begingroup + \sankeyset{##1} + \edef\name{##2} + \edef\orient{\sankeygetnodeorient{##2}} + \edef\qty{\sankeygetnodeqty{##2}} + \snk@filldrawend + \endgroup + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sankeynodeend} +% +% The \code{\sankeynodeend} macro creates the new Sankey +% node named \code{#2} then fills and draws an ending lane +% attached to this new Sankey node. +% +% \begin{macrocode} + \NewDocumentCommand\sankeynodeend{O{}m}{% options, node parameters + \sankeynode[##1]{end,##2} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sankeyadvance} +% \begin{macro}{\sankeyadvance*} +% +% The \code{\sankeyadvance} macro moves toward (or backward if +% \emph{starred} calls -- \code{#1}) the Sankey node named \code{#3}. +% \code{#4} is a distance. The previous position is keeped +% by a Sankey node named \code{#3-old}. +% +% \begin{macrocode} + \NewDocumentCommand\sankeyadvance{sO{}mm}{% + %params: *(reverse), options, name, distance + \snk@errorifnotdefined{##3} + \begingroup + \sankeyset{##2} + \edef\name{##3} + \edef\snk@oldname{##3-old} + \sankeynodealias{\name}{\snk@oldname} + \IfBooleanTF{##1}{ + % move backward + \sankeynode{ + at={$(\snk@oldname.center)!##4!90:(\snk@oldname.left)$}, + angle=\sankeygetnodeorient{\snk@oldname}, + quantity=\sankeygetnodeqty{\snk@oldname}, + name=\name, + } + \path[/sankey/fill] + (\name.left) -- (\snk@oldname.left) + -- (\snk@oldname.right) -- (\name.right) -- cycle; + \path[/sankey/draw] + (\name.left) -- (\snk@oldname.left) + (\snk@oldname.right) -- (\name.right); + }{ + % move forward + \sankeynode{ + at={$(\snk@oldname.center)!##4!-90:(\snk@oldname.left)$}, + angle=\sankeygetnodeorient{\snk@oldname}, + quantity=\sankeygetnodeqty{\snk@oldname}, + name=\name, + } + \path[/sankey/fill] + (\snk@oldname.left) -- (\name.left) + -- (\name.right) -- (\snk@oldname.right) -- cycle; + \path[/sankey/draw] + (\snk@oldname.left) -- (\name.left) + (\name.right) -- (\snk@oldname.right); + } + \snk@show@debug{\name} + \endgroup + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\sankeyturnright} +% \begin{macro}{\sankeyturnright*} +% +% \changes{v3.0}{2021/03/14}{new macro} +% +% The \code{sankeyturnright} macro moves forward the Sankey node +% named \code{#3} by turning right. The angle is \code{#4} (the starred +% version uses the opposite of \code{#4}). If the angle is \emph{negative}, the +% macro calls the \code{\sankeyturnrightbackward} macro to move backward else +% the macro fills/draws the lane between the previous position and the new +% position. The previous position is keeped by a Sankey +% node named \code{#3-old}. +% +% \begin{macrocode} + \NewDocumentCommand\sankeyturnright{sO{}mm}{ + % *(reverse), options, name, angle + \snk@errorifnotdefined{##3} + \begingroup + \IfBooleanTF{##1} + {\edef\snk@angle{\fpeval{-1*##4}}} + {\edef\snk@angle{\fpeval{1*##4}}} + \edef\snk@anglesign{\fpeval{sign(\snk@angle)}} + \ifnumgreater{\snk@anglesign}{-1}{ + \sankeyset{##2} + \edef\name{##3} + \edef\snk@oldname{##3-old} + \sankeynodealias{\name}{\snk@oldname} + \edef\qty{\sankeygetnodeqty{\name}} + \edef\orient{\snk@normalize@angle{\sankeygetnodeorient{\name}-\snk@angle}} + \snk@getpos\snk@c{$(\name.right)!-\snk@minradius!(\name.left)$} + \snk@getpos\pos{$(\snk@c)!1!-\snk@angle:(\name.center)$} + \snk@makenode{} + % fill the region + \path[/sankey/fill] let + \p1=(\snk@oldname.left),\p2=(\snk@oldname.right), + \p3=(\name.left),\p4=(\name.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, + \n{minr}={\snk@minradius} + in + (\p1) arc(\orient+\snk@angle+90:\orient+90:\n{maxr}) -- (\p3) -- + (\p4) arc(\orient+90:\orient+\snk@angle+90:\n{minr}) -- (\p2) -- cycle; + % draw left and right borders + \path[/sankey/draw] let + \p1=(\snk@oldname.left),\p2=(\snk@oldname.right), + \p3=(\name.left),\p4=(\name.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, + \n{minr}={\snk@minradius} + in + (\p1) arc(\orient+\snk@angle+90:\orient+90:\n{maxr}) + (\p4) arc(\orient+90:\orient+\snk@angle+90:\n{minr}); + \snk@show@debug{\name} + }{ + \sankeyturnrightbackward[##2]{##3}{-1*\snk@angle} + } + \endgroup + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\sankeyturnrightbackward} +% \begin{macro}{\sankeyturnrightbackward*} +% +% \changes{v3.0}{2021/03/14}{new macro} +% +% The \code{sankeyturnrightbackward} macro moves backward the Sankey node +% named \code{#3} by turning right. The angle is \code{#4} (the starred +% version uses the opposite of \code{#4}). If the angle is \emph{negative}, the +% macro calls the \code{\sankeyturnright} macro to move forward else +% the macro fills/draws the lane between the previous position and the new +% position. The previous position is keeped by a Sankey +% node named \code{#3-old}. +% +% \begin{macrocode} + \NewDocumentCommand\sankeyturnrightbackward{sO{}mm}{ + % *(reverse), options, name, angle + \snk@errorifnotdefined{##3} + \begingroup + \IfBooleanTF{##1} + {\edef\snk@angle{\fpeval{-1*##4}}} + {\edef\snk@angle{\fpeval{1*##4}}} + \edef\snk@anglesign{\fpeval{sign(\snk@angle)}} + \ifnumgreater{\snk@anglesign}{-1}{ + \sankeyset{##2} + \edef\name{##3} + \edef\snk@oldname{##3-old} + \sankeynodealias{\name}{\snk@oldname} + \edef\qty{\sankeygetnodeqty{\name}} + \edef\orient{\snk@normalize@angle{\sankeygetnodeorient{\name}+\snk@angle}} + \snk@getpos\snk@c{$(\name.right)!-\snk@minradius!(\name.left)$} + \snk@getpos\pos{$(\snk@c)!1!\snk@angle:(\name.center)$} + \snk@makenode{} + % fill the region + \path[/sankey/fill] let + \p1=(\name.left),\p2=(\name.right), + \p3=(\snk@oldname.left),\p4=(\snk@oldname.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius} + in + (\p1) arc(\orient+90:\orient-\snk@angle+90:\n{maxr}) -- (\p3) -- + (\p4) arc(\orient-\snk@angle+90:\orient+90:\n{minr}) -- (\p2) -- cycle; + % draw left and right borders + \path[/sankey/draw] let + \p1=(\name.left),\p2=(\name.right), + \p3=(\snk@oldname.left),\p4=(\snk@oldname.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius} + in + (\p1) arc(\orient+90:\orient-\snk@angle+90:\n{maxr}) + (\p4) arc(\orient-\snk@angle+90:\orient+90:\n{minr}); + \snk@show@debug{\name} + }{ + \sankeyturnright[##2]{##3}{-1*\snk@angle} + } + \endgroup + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\sankeyturnleft} +% \begin{macro}{\sankeyturnleft*} +% +% \changes{v3.0}{2021/03/14}{new macro} +% +% The \code{sankeyturnleft} macro moves forward the Sankey node +% named \code{#3} by turning left. The angle is \code{#4} (the starred +% version uses the opposite of \code{#4}). If the angle is \emph{negative}, the +% macro calls the \code{\sankeyturnleftbackward} macro to move backward else +% the macro fills/draws the lane between the previous position and the new +% position. The previous position is keeped by a Sankey +% node named \code{#3-old}. +% +% \begin{macrocode} + \NewDocumentCommand\sankeyturnleft{sO{}mm}{ + % *(reverse), options, name, angle + \snk@errorifnotdefined{##3} + \begingroup + \IfBooleanTF{##1} + {\edef\snk@angle{\fpeval{-1*##4}}} + {\edef\snk@angle{\fpeval{1*##4}}} + \edef\snk@anglesign{\fpeval{sign(\snk@angle)}} + \ifnumgreater{\snk@anglesign}{-1}{ + \sankeyset{##2} + \edef\name{##3} + \edef\snk@oldname{##3-old} + \sankeynodealias{\name}{\snk@oldname} + \edef\qty{\sankeygetnodeqty{\name}} + \edef\orient{\snk@normalize@angle{\sankeygetnodeorient{\name}+\snk@angle}} + \snk@getpos\snk@c{$(\name.left)!-\snk@minradius!(\name.right)$} + \snk@getpos\pos{$(\snk@c)!1!\snk@angle:(\name.center)$} + \snk@makenode{} + % fill the region + \path[/sankey/fill] let + \p1=(\snk@oldname.left),\p2=(\snk@oldname.right), + \p3=(\name.left),\p4=(\name.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius} + in + (\p1) arc(\orient-\snk@angle-90:\orient-90:\n{minr}) -- (\p3) -- + (\p4) arc(\orient-90:\orient-\snk@angle-90:\n{maxr}) -- (\p2) -- cycle; + % draw left and right borders + \path[/sankey/draw] let + \p1=(\snk@oldname.left),\p2=(\snk@oldname.right), + \p3=(\name.left),\p4=(\name.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius} + in + (\p1) arc(\orient-\snk@angle-90:\orient-90:\n{minr}) + (\p4) arc(\orient-90:\orient-\snk@angle-90:\n{maxr}); + \snk@show@debug{\name} + }{ + \sankeyturnleftbackward[##2]{##3}{-1*\snk@angle} + } + \endgroup + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\sankeyturnleftbackward} +% \begin{macro}{\sankeyturnleftbackward*} +% +% \changes{v3.0}{2021/03/14}{new macro} +% +% The \code{sankeyturnleftbackward} macro moves backward the Sankey node +% named \code{#3} by turning left. The angle is \code{#4} (the starred +% version uses the opposite of \code{#4}). If the angle is \emph{negative}, the +% macro calls the \code{\sankeyturnleft} macro to move forward else +% the macro fills/draws the lane between the previous position and the new +% position. The previous position is keeped by a Sankey +% node named \code{#3-old}. +% +% \begin{macrocode} + \NewDocumentCommand\sankeyturnleftbackward{sO{}mm}{ + % *(reverse), options, name, angle + \snk@errorifnotdefined{##3} + \begingroup + \IfBooleanTF{##1} + {\edef\snk@angle{\fpeval{-1*##4}}} + {\edef\snk@angle{\fpeval{1*##4}}} + \edef\snk@anglesign{\fpeval{sign(\snk@angle)}} + \ifnumgreater{\snk@anglesign}{-1}{ + \sankeyset{##2} + \edef\name{##3} + \edef\snk@oldname{##3-old} + \sankeynodealias{\name}{\snk@oldname} + \edef\qty{\sankeygetnodeqty{\name}} + \edef\orient{\snk@normalize@angle{\sankeygetnodeorient{\name}-\snk@angle}} + \snk@getpos\snk@c{$(\name.left)!-\snk@minradius!(\name.right)$} + \snk@getpos\pos{$(\snk@c)!1!-\snk@angle:(\name.center)$} + \snk@makenode{} + % fill the region + \path[/sankey/fill] let + \p1=(\name.left),\p2=(\name.right), + \p3=(\snk@oldname.left),\p4=(\snk@oldname.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius} + in + (\p1) arc(\orient-90:\orient+\snk@angle-90:\n{minr}) -- (\p3) -- + (\p4) arc(\orient+\snk@angle-90:\orient-90:\n{maxr}) -- (\p2) -- cycle; + % draw left and right borders + \path[/sankey/draw] let + \p1=(\name.left),\p2=(\name.right), + \p3=(\snk@oldname.left),\p4=(\snk@oldname.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius} + in + (\p1) arc(\orient-90:\orient+\snk@angle-90:\n{minr}) + (\p4) arc(\orient+\snk@angle-90:\orient-90:\n{maxr}); + \snk@show@debug{\name} + }{ + \sankeyturnleft[##2]{##3}{-1*\snk@angle} + } + \endgroup + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\sankeyturn} +% \begin{macro}{\sankeyturn*} +% +% \changes{v3.0}{2021/03/14}{simplification by using new \emph{turn} macros} +% +% The \code{\sankeyturn} macro moves toward (or backward if +% \emph{starred} calls -- \code{#1}) the Sankey node named +% \code{#3} by turning left (angle \code{#4} is positive) +% or right (angle \code{#4} is negative). +% The previous position is keeped by a Sankey node named +% \code{#3-old}. +% +% \begin{macrocode} + \NewDocumentCommand\sankeyturn{sO{}mm}{% + % *(reverse), options, name, angle + \snk@errorifnotdefined{##3} + \begingroup + \edef\snk@anglesign{\fpeval{sign(##4)}} + \IfBooleanTF{##1}{ + \ifnumgreater{\snk@anglesign}{-1} + {\sankeyturnleftbackward[##2]{##3}{##4}} + {\sankeyturnrightbackward[##2]{##3}{-1*##4}} + }{ + \ifnumgreater{\snk@anglesign}{-1} + {\sankeyturnleft[##2]{##3}{##4}} + {\sankeyturnright[##2]{##3}{-1*##4}} + } + \endgroup + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\sankeyfork} +% +% The \code{\sankeyfork} macro forks the Sankey node named +% \code{#2} to the list of subnodes given by \code{#3}. +% The subnodes are cloned to take into account +% the \code{debug} option. +% +% \begin{macrocode} + \NewDocumentCommand\sankeyfork{O{}mm}{%options, name, list of forks + \snk@errorifnotdefined{##2} + \begingroup + \sankeyset{##1} + \sankeynode[debug=false]{as={##2},forked={##3}} + \foreach \qty/\snk@subnodename in {##3}{\sankeynode{as={\snk@subnodename}}} + \endgroup + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\sankeyqtytolen} +% +% The \code{\sankeyqtytolen} macro converts quantity +% to length using \code{\fpeval} and the ratio determined +% by \code{\snk@totalqty} and \code{sankeytotallen}. +% +% \begin{macrocode} + \def\sankeyqtytolen##1{\fpeval{(##1)/\snk@totalqty*\snk@totallen}} +% \end{macrocode} +% \end{macro} +% +%^^A % ------------------------------------------------------------ +% \subsection{The \protect\texttt{sankeydiagram} environment (the end)} +%^^A % ------------------------------------------------------------ +% +% Here is the end of the definition of the \code{sankeydiagram} +% environment. The \code{@initial options} style and the % +% \code{every diagram} style are applied before options provided by +% user. +% +% \begin{macrocode} + \sankeyset{ + @initial options, + every diagram, + % user values + #1} +} +{} % empty but mandatory ! :-) +% \end{macrocode} +% \end{environment} +% +%^^A % ------------------------------------------------------------ +% \subsection{Predefined start and end styles} +%^^A % ------------------------------------------------------------ +% +% The \code{none} style. +% +% \begin{macrocode} +\sankeyset{ + new start style={none}{}{}, + new end style={none}{}{}, +} +% \end{macrocode} +% +% The \code{simple} style. +% +% \begin{macrocode} +\sankeyset{ + new start style={simple}{ + (\name.left) -- ([xshift=-.5\pgflinewidth]\name.left) + -- ([xshift=-.5\pgflinewidth]\name.right) -- (\name.right) -- cycle + }{ + (\name.left) -- ([xshift=-.5\pgflinewidth]\name.left) + -- ([xshift=-.5\pgflinewidth]\name.right) -- (\name.right) + }, + new end style={simple}{ + (\name.left) -- ([xshift=2mm]\name.center) + -- (\name.right) -- cycle + }{ + (\name.left) -- ([xshift=2mm]\name.center) -- (\name.right) + }, +} +% \end{macrocode} +% +% The \code{arrow} style. +% +% \begin{macrocode} +\sankeyset{ + new start style={arrow}{ + (\name.left) -- ++(-10pt,0) -- ([xshift=-10pt/6]\name.center) + -- ([xshift=-10pt]\name.right) -- (\name.right) -- cycle + }{ + (\name.left) -- ++(-10pt,0) -- ([xshift=-10pt/6]\name.center) + -- ([xshift=-10pt]\name.right) -- (\name.right) + }, + new end style={arrow}{ + (\name.left) -- ([yshift=1mm]\name.left) + -- ([xshift=10pt]\name.center) -- ([yshift=-1mm]\name.right) + -- (\name.right) -- cycle + }{ + (\name.left) -- ([yshift=1mm]\name.left) + -- ([xshift=10pt]\name.center) -- ([yshift=-1mm]\name.right) + -- (\name.right) + }, +} +% \end{macrocode} +% \iffalse +%</sankey> +% \fi +% +%^^A % ------------------------------------------------------------ +% \section{\texttt{tikzlibrarydubins.code.tex}} +%^^A % ------------------------------------------------------------ +% +% Not yet documented nor commented... +% +% \iffalse +%<*tikzlibrarydubins.code.tex> +% \fi +% \begin{macrocode} +\def\tikzlibrarydubins@version{v3.0} +\def\tikzlibrarydubins@date{2021/03/14} + +\usetikzlibrary{calc} +\RequirePackage{etoolbox} +\RequirePackage{xfp} + +\newbool{dubinspathreverse} + +\def\ifpgfmathcond#1{% + \pgfmathparse{(#1)?1:0}% + \ifnumequal{\pgfmathresult}{1}% +} + + +\def\dbp@getxy#1#2#3{% + \tikz@scan@one@point\pgfutil@firstofone(#3)\relax% + \edef#1{\the\pgf@x}% + \edef#2{\the\pgf@y}% +} + +\def\dbp@anglebetween#1#2#3{%macro, s, t + \dbp@getxy\dbp@ax\dbp@ay{#2} + \dbp@getxy\dbp@bx\dbp@by{#3} + \pgfmathsetmacro#1{atan2(\dbp@by-\dbp@ay,\dbp@bx-\dbp@ax)} +} + +\def\dbp@distancebetween#1#2#3{%macro, s, t + \dbp@getxy\dbp@ax\dbp@ay{#2} + \dbp@getxy\dbp@bx\dbp@by{#3} + \edef#1{\fpeval{sqrt(% + (\dbp@bx-\dbp@ax)*(\dbp@bx-\dbp@ax)% + +(\dbp@by-\dbp@ay)*(\dbp@by-\dbp@ay)% + )}}% +} + +\newcommand\dbp@rsr{% s, sa, t, ta, as, len, at, r + let + \p{tr}=([shift={(\dbp@angb-90:\dbp@radius pt)}]\dbp@b), + \n1={\dbp@anga+90}, + \n2={\dbp@angb+90}, + \n3={\n2+\dbp@lastangle} + in + arc(\n1:\n1-\dbp@firstangle:\dbp@rradius pt) + -- ([shift={(\p{tr})}]\n3:\dbp@rradius pt) + arc(\n3:\n2:\dbp@rradius pt) +} + +\newcommand\dbp@lsl{% s, sa, t, ta, as, len, at, r + let + \p{tl}=([shift={(\dbp@angb+90:\dbp@radius pt)}]\dbp@b), + \n1={\dbp@anga-90},\n2={\n1+\dbp@firstangle}, + \n3={\dbp@angb-90},\n4={\n3-\dbp@lastangle} + in + arc(\n1:\n2:\dbp@lradius pt) + -- ([shift={(\p{tl})}]\n4:\dbp@lradius pt) + arc(\n4:\n3:\dbp@lradius pt) +} + +\newcommand\dbp@rsl{% s, sa, t, ta, as, len, at, r + let + \p{tl}=([shift={(\dbp@angb+90:\dbp@radius pt)}]\dbp@b), + \n1={\dbp@anga+90},\n2={\n1-\dbp@firstangle}, + \n3={\dbp@angb-90},\n4={\n3-\dbp@lastangle} + in + arc(\n1:\n2:\dbp@rradius pt) + -- ([shift={(\p{tl})}]\n4:\dbp@lradius pt) + arc(\n4:\n3:\dbp@lradius pt) +} + +\newcommand\dbp@lsr{% s, sa, t, ta, as, len, at, r + let + \p{tr}=([shift={(\dbp@angb-90:\dbp@radius pt)}]\dbp@b), + \n1={\dbp@anga-90},\n2={\n1+\dbp@firstangle}, + \n3={\dbp@angb+90},\n4={\n3+\dbp@lastangle} + in + arc(\n1:\n2:\dbp@lradius pt) + -- ([shift={(\p{tr})}]\n4:\dbp@rradius pt) + arc(\n4:\n3:\dbp@rradius pt) +} + +\newcommand\dbp@lrl{% s, sa, t, ta, as, ai, at, r + let + \n1={\dbp@anga-90},\n2={\n1+\dbp@firstangle}, + \n3={\dbp@angb-90},\n4={\n3-\dbp@lastangle} + in + arc(\n1:\n2:\dbp@lradius pt) + arc(\n2+180:\n2+180-\dbp@midparam:\dbp@rradius pt) + arc(\n4:\n3:\dbp@lradius pt) +} + +\newcommand\dbp@rlr{% s, sa, t, ta, as, ai, at, r + let + \n1={\dbp@anga+90},\n2={\n1-\dbp@firstangle}, + \n3={\dbp@angb+90},\n4={\n3+\dbp@lastangle} + in + arc(\n1:\n2:\dbp@rradius pt) + arc(\n2+180:\n2+180+\dbp@midparam:\dbp@lradius pt) + arc(\n4:\n3:\dbp@rradius pt) +} +\newcommand\dbp@rev@lsl{\dbp@rsr} +\newcommand\dbp@rev@rsr{\dbp@lsl} +\newcommand\dbp@rev@lsr{\dbp@lsr} +\newcommand\dbp@rev@rsl{\dbp@rsl} +\newcommand\dbp@rev@lrl{\dbp@rlr} +\newcommand\dbp@rev@rlr{\dbp@lrl} + + +\newcommand\dubinspath[1]{% + \pgfextra{ + \dubinspathset{#1} + \ifbool{dubinspathreverse}{ + \edef\dbp@newa{\dbp@b} + \edef\dbp@newb{\dbp@a} + \pgfmathsetmacro\dbp@newanga{180+\dbp@angb} + \pgfmathsetmacro\dbp@newangb{180+\dbp@anga} + \edef\dbp@newfirstangle{\dbp@lastangle} + \edef\dbp@newlastangle{\dbp@firstangle} + \edef\dbp@newmethod{rev@\dbp@method} + \edef\dbp@newlradius{\dbp@rradius} + \edef\dbp@newrradius{\dbp@lradius} + \dubinspathset{ + start point=\dbp@newa, + end point=\dbp@newb, + start angle=\dbp@newanga, + end angle=\dbp@newangb, + first angle=\dbp@newfirstangle, + last angle=\dbp@newlastangle, + left and right minimum radii=\dbp@newlradius pt and \dbp@newrradius pt, + method=\dbp@newmethod, + } + }{} + } + \csname dbp@\dbp@method\endcsname% +} + + +%% solution + +\def\dbp@store#1#2{% + \expandafter\xdef\csname dbp@store@#1@#2\endcsname% + {\csname dbp@#2\endcsname}% +} +\def\dbp@get#1#2{% + \csname dbp@store@#1@#2\endcsname% +} + +\def\dbp@setparams#1#2#3#4#5{% + % method, length, fisrt angle, middle param, last angle + \edef\dbp@method{#1} + \edef\dbp@length{#2} + \edef\dbp@firstangle{#3} + \edef\dbp@middleparam{#4} + \edef\dbp@lastangle{#5} + \ifdef{\dbp@storename}{ + \foreach \p in {method,length,firstangle,middleparam,lastangle}{ + \dbp@store{\dbp@storename}{\p} + } + }{} +} + +\def\dbp@updateparams#1#2#3#4#5{ + \ifpgfmathcond{#2<\dbp@length}{ + \dbp@setparams{#1}{#2}{#3}{#4}{#5} + }{} +} + +\tikzset{ + dubins path/.is family, + dubins path, + start point/.store in=\dbp@a, + start angle/.store in=\dbp@anga, + end point/.store in=\dbp@b, + end angle/.store in=\dbp@angb, + store/.store in=\dbp@storename, + use store/.style={ + method=\dbp@get{#1}{method}, + first angle=\dbp@get{#1}{firstangle}, + last angle=\dbp@get{#1}{lastangle}, + middle param=\dbp@get{#1}{middleparam}, + }, + minimum radius/.code={ + \pgfmathsetmacro\dbp@radius{#1} + \pgfmathsetmacro\dbp@rradius{#1} + \pgfmathsetmacro\dbp@lradius{#1} + }, + left and right minimum radii/.code args={#1 and #2}{ + \pgfmathsetmacro\dbp@lradius{#1} + \pgfmathsetmacro\dbp@rradius{#2} + \pgfmathsetmacro\dbp@radius{(\dbp@lradius + \dbp@rradius)/2} + }, + method/.store in=\dbp@method, + first angle/.store in=\dbp@firstangle, + last angle/.store in=\dbp@lastangle, + middle param/.store in=\dbp@midparam, + reverse/.is if=dubinspathreverse, +} + +\newcommand\dubinspathset[1]{\tikzset{dubins path,#1}} + +\newcommand\dubinspathcalc[1]{% + \begingroup + \dubinspathset{#1} + \tikzset{ + declare function={ + angtodist(\dbp@a,\dbp@r)={abs(\dbp@a)*.01745329*\dbp@r}; + modangr(\dbp@a,\dbp@b)={ + ( + Mod(\dbp@a,360)<Mod(\dbp@b,360) + ? + Mod(\dbp@a,360) + : + Mod(\dbp@a,360)-360)+\dbp@b-Mod(\dbp@b,360 + ) + }; + modangl(\dbp@a,\dbp@b)={ + ( + Mod(\dbp@a,360)<Mod(\dbp@b,360) + ? + Mod(\dbp@a,360)+360 + : + Mod(\dbp@a,360))+(\dbp@b)-Mod(\dbp@b,360) + }; + }, + } + + \pgfmathsetmacro\dbp@radius{\dbp@rradius} + \pgfmathsetmacro\dbp@anga{mod((\dbp@anga)+180,360)-180} + \pgfmathsetmacro\dbp@angb{mod((\dbp@angb)+180,360)-180} + \path + let + \p{a}=(\dbp@a), + \p{b}=(\dbp@b), + \p{ar}=($(\p{a}) + (\dbp@anga-90:\dbp@radius pt)$), + \p{al}=($(\p{a}) + (\dbp@anga+90:\dbp@radius pt)$), + \p{br}=($(\p{b}) + (\dbp@angb-90:\dbp@radius pt)$), + \p{bl}=($(\p{b}) + (\dbp@angb+90:\dbp@radius pt)$) + in \pgfextra{ + \pgfinterruptpath + + % RSR (ar and br) + \dbp@anglebetween\dbp@rsrarbr{\p{ar}}{\p{br}} + \dbp@distancebetween\dbp@rsrdarbr{\p{ar}}{\p{br}} + \pgfmathsetmacro\dbp@rsrangone{Mod(\dbp@anga-\dbp@rsrarbr,360)} + \pgfmathsetmacro\dbp@rsrangtwo{Mod(\dbp@rsrarbr-\dbp@angb,360)} + \pgfmathsetmacro\dbp@rsrlen{\dbp@rsrdarbr} + \pgfmathsetmacro\dbp@rsrdist{ + angtodist(\dbp@rsrangone,\dbp@radius) + +\dbp@rsrlen + +angtodist(\dbp@rsrangtwo,\dbp@radius) + } + \dbp@setparams{rsr}{\dbp@rsrdist}{\dbp@rsrangone}{\dbp@rsrlen}{\dbp@rsrangtwo} + + % LSL (al and bl) + \dbp@anglebetween\dbp@lslalbl{\p{al}}{\p{bl}} + \dbp@distancebetween\dbp@lsldalbl{\p{al}}{\p{bl}} + \pgfmathsetmacro{\dbp@lslangone}{mod(\dbp@lslalbl-\dbp@anga+720,360)} + \pgfmathsetmacro{\dbp@lslangtwo}{mod(\dbp@angb-\dbp@lslalbl+720,360)} + \pgfmathsetmacro\dbp@lsllen{\dbp@lsldalbl} + \pgfmathsetmacro\dbp@lsldist{ + angtodist(\dbp@lslangone,\dbp@radius) + +\dbp@lsllen + +angtodist(\dbp@lslangtwo,\dbp@radius) + } + \dbp@updateparams% + {lsl}{\dbp@lsldist}{\dbp@lslangone}{\dbp@lsllen}{\dbp@lslangtwo} + + % RSL (ar and bl) + \dbp@distancebetween\dbp@rsldarbl{\p{ar}}{\p{bl}} + \pgfmathtruncatemacro\dbp@rslok{(\dbp@rsldarbl>=2*\dbp@radius)?1:0} + \ifnumequal{\dbp@rslok}{1}{ + \dbp@anglebetween\dbp@rslarbl{\p{ar}}{\p{bl}} + \pgfmathsetmacro\dbp@rslanglesup{ + asin(\dbp@radius/\dbp@rsldarbl*2)} + \pgfmathsetmacro\dbp@rslangone + {Mod(\dbp@anga-\dbp@rslarbl+\dbp@rslanglesup,360)} + \pgfmathsetmacro\dbp@rslangtwo + {Mod(\dbp@angb-\dbp@rslarbl+\dbp@rslanglesup,360)} + \pgfmathsetmacro\dbp@rsllen{veclen(\dbp@rsldarbl,\dbp@radius)} + \pgfmathsetmacro\dbp@rsldist{ + angtodist(\dbp@rslangone,\dbp@radius) + +\dbp@rsllen + +angtodist(\dbp@rslangtwo,\dbp@radius) + } + + \dbp@updateparams% + {rsl}{\dbp@rsldist}{\dbp@rslangone}{\dbp@rsllen}{\dbp@rslangtwo} + }{} + + % LSR (al and br) + \dbp@distancebetween\dbp@lsrdalbr{\p{al}}{\p{br}} + \pgfmathtruncatemacro\dbp@lsrok{(\dbp@lsrdalbr>=2*\dbp@radius)?1:0} + \ifnumequal{\dbp@lsrok}{1}{ + \dbp@anglebetween\dbp@lsralbr{\p{al}}{\p{br}} + \pgfmathsetmacro\dbp@lsranglesup{ + asin(\dbp@radius/\dbp@lsrdalbr*2)} + \pgfmathsetmacro\dbp@lsrangone + {Mod(\dbp@lsralbr+\dbp@lsranglesup-\dbp@anga,360)} + \pgfmathsetmacro\dbp@lsrangtwo + {Mod(\dbp@lsralbr+\dbp@lsranglesup-\dbp@angb,360)} + \pgfmathsetmacro\dbp@lsrlen{veclen(\dbp@lsrdalbr,\dbp@radius)} + \pgfmathsetmacro\dbp@lsrdist{ + angtodist(\dbp@lsrangone,\dbp@radius) + +\dbp@lsrlen + +angtodist(\dbp@lsrangtwo,\dbp@radius) + } + \dbp@updateparams% + {lsr}{\dbp@lsrdist}{\dbp@lsrangone}{\dbp@lsrlen}{\dbp@lsrangtwo} + }{} + + % LRL (al and bl) + \dbp@distancebetween\dbp@lrldalbl{\p{al}}{\p{bl}} + \pgfmathtruncatemacro\dbp@lrlok{(\dbp@lrldalbl<=4*\dbp@radius)?1:0} + \ifnumequal{\dbp@lrlok}{1}{ + \dbp@anglebetween\dbp@lrlalbl{\p{al}}{\p{bl}} + \pgfmathsetmacro\dbp@lrlangsup{acos(\dbp@lrldalbl/\dbp@radius/4)} + \pgfmathsetmacro\dbp@lrlangone{ + modangl(\dbp@lrlalbl+\dbp@lrlangsup,\dbp@anga-90)-(\dbp@anga-90)} + \pgfmathsetmacro\dbp@lrlangtwo{% + (\dbp@angb-90)-modangr(\dbp@lrlalbl+180-\dbp@lrlangsup,\dbp@angb-90)} + \pgfmathsetmacro\dbp@lrlangthree{360-2*(90-\dbp@lrlangsup)} + \pgfmathsetmacro\dbp@lrldist{ + angtodist(\dbp@lrlangone,\dbp@radius) + +angtodist(\dbp@lrlangthree,\dbp@radius) + +angtodist(\dbp@lrlangtwo,\dbp@radius) + } + \dbp@updateparams% + {lrl}{\dbp@lrldist}{\dbp@lrlangone}{\dbp@lrlangthree}{\dbp@lrlangtwo} + }{} + + % RLR (ar and br) + \dbp@distancebetween\dbp@rlrdarbr{\p{ar}}{\p{br}} + \pgfmathtruncatemacro\dbp@rlrok{(\dbp@rlrdarbr<=4*\dbp@radius)?1:0} + \ifnumequal{\dbp@rlrok}{1}{ + \dbp@anglebetween\dbp@rlrarbr{\p{ar}}{\p{br}} + \pgfmathsetmacro\dbp@rlrangsup{acos(\dbp@rlrdarbr/\dbp@radius/4)} + \pgfmathsetmacro\dbp@rlrangone{ + (\dbp@anga+90)-modangr(\dbp@rlrarbr-\dbp@rlrangsup,\dbp@anga+90)} + \pgfmathsetmacro\dbp@rlrangtwo{% + modangl(\dbp@rlrarbr+180+\dbp@rlrangsup,\dbp@angb+90)-(\dbp@angb+90)} + \pgfmathsetmacro\dbp@rlrangthree{360-2*(90-\dbp@rlrangsup)} + \pgfmathsetmacro\dbp@rlrdist{ + angtodist(\dbp@rlrangone,\dbp@radius) + +angtodist(\dbp@rlrangthree,\dbp@radius) + +angtodist(\dbp@rlrangtwo,\dbp@radius) + } + \dbp@updateparams% + {rlr}{\dbp@rlrdist}{\dbp@rlrangone}{\dbp@rlrangthree}{\dbp@rlrangtwo} + }{} + + \endpgfinterruptpath + }; + \endgroup +} +% \end{macrocode} +% \iffalse +%</tikzlibrarydubins.code.tex> +% \fi +% +% \PrintChanges +% +% \setcounter{IndexColumns}{2} +% \PrintIndex +% +% \Finale +% +% \iffalse +%<*sankeydocpreamble> +\usepackage[paper=a4paper,vmargin=1.5cm,left=4.5cm,right=3.5cm]{geometry} +\usepackage[utf8]{inputenc} +\usepackage{cmap} +\usepackage[T1]{fontenc} +\usepackage{lmodern} +\usepackage[final,protrusion=true,expansion=true]{microtype} +\usepackage{xcolor} +\PassOptionsToPackage{final,colorlinks,linkcolor=red!60!orange!85!black}{hyperref} +\usepackage[numbered]{hypdoc} +\usepackage{fancyvrb} +\usepackage[final]{listings} +\usepackage{enumitem} +\usepackage{bookmark} +\usepackage{siunitx} +\usepackage{footnote} +\usepackage{etoc} +\usepackage{accsupp} +\usepackage{tikz} +\usetikzlibrary{positioning,patterns.meta,fit} +\usepackage[british]{babel} +\usepackage{varioref} +\usepackage{embedfile} +\usepackage{dtx-attach} +\embedfile[mimetype=text/plain]{sankey.ins} +\usepackage{sankey} + +\colorlet{bgcode}{yellow!50!gray!5} +\colorlet{keyword}{blue!50!cyan!50!black} +\colorlet{comment}{red!75!black} + +\newcommand\emptyaccsupp[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}} + +\lstset{ + literate= + {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ú}{{\'u}}1 + {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1 + {à}{{\`a}}1 {è}{{\`e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1 + {À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1 + {ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1 + {Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1 + {â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1 + {Â}{{\^A}}1 {Ê}{{\^E}}1 {Î}{{\^I}}1 {Ô}{{\^O}}1 {Û}{{\^U}}1 + {œ}{{\oe}}1 {Œ}{{\OE}}1 {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1 + {ç}{{\c c}}1 {Ç}{{\c C}}1 {ø}{{\o}}1 {å}{{\r a}}1 {Å}{{\r A}}1 + {€}{{\texteuro}}1 {£}{{\pounds}}1 {°}{{\degres}}1 + {’}{{\textquoteright}}1 {‘}{{\textquoteleft}}1 + {«}{{<<}}1 {»}{{>>}}1 + {—}{{---}}1 {−}{{$-$}}1 + {\^\^A}{{}}0 % verbatim in .dtx file +} + +\lstset{ + fancyvrb=true, + escapechar=`, + extendedchars=true, + fontadjust=true, + columns=fullflexible, + flexiblecolumns=true, + inputencoding=utf8, + keepspaces=true, + backgroundcolor=\color{bgcode}, + basicstyle=\mdseries\ttfamily, + keywordstyle=\color{keyword}, + stringstyle=\ttfamily\color{green!50!black}, + commentstyle=\color{comment}\itshape, + emphstyle=\bfseries\color{red}, + numbersep=5pt, + %numbers=left, + numberstyle=\tiny\emptyaccsupp, + showstringspaces=false, + upquote=true, + aboveskip=.5\parskip, + belowskip=.5\parskip, + framexleftmargin=1pt, + framexrightmargin=1pt, + gobble=2, % \lstlisting code in .dtx +} + +\lstdefinestyle{textsmall}{basicstyle=\color{black}\small\mdseries\ttfamily} +\lstdefinestyle{textfootnotesize}{basicstyle=\color{black}\footnotesize\mdseries\ttfamily} +\lstdefinestyle{textscriptsize}{basicstyle=\color{black}\scriptsize\mdseries\ttfamily} +\lstdefinestyle{texttiny}{basicstyle=\color{black}\tiny\mdseries\ttfamily} + +\lstdefinestyle{LaTeX}{ + language=[LaTeX]TeX, + moretexcs={ + Lab, + LabSet, + Qty, + QtySet, + colorlet, + coordinate, + countries, + country, + countryname, + definecolor, + draw, + endcountry, + fill, + foreach, + hashband, + hdist, + hwidth, + node, + nodename, + path, + sankeyadvance, + sankeydubins, + sankeyend, + sankeyend, + sankeyfork, + sankeynode, + sankeynodealias, + sankeynodeend, + sankeynodestart, + sankeyoutin, + sankeyset, + sankeystart, + sankeyturn, + sankeyturnleft, + sankeyturnleftbackward, + sankeyturnright, + sankeyturnrightbackward, + sisetup, + startcountry, + tikzset, + turnandstop, + usepackage, + vdist, + } +} +\lstdefinestyle{LaTeXsmall}{style=LaTeX,style=textsmall} +\lstdefinestyle{LaTeXfootnotesize}{style=LaTeX,style=textfootnotesize} +\lstdefinestyle{LaTeXscriptsize}{style=LaTeX,style=textscriptsize} +\lstdefinestyle{LaTeXtiny}{style=LaTeX,style=texttiny} + +\def\code{\lstinline[basicstyle=\mdseries\ttfamily\color{red!50!black}]} + +\edef\samplecodename{\jobname-code.vrb} + +\newcommand\constant[1]{\textcolor{violet}{\texttt{#1}}} +\newcommand\ARG[1]{\texttt{\{#1\}}} +\newcommand\OPTARG[1]{\textcolor{green!50!black}{\texttt{[#1]}}} +\newcommand\VAR[1]{\textit{\texttt{\ensuremath{\langle}#1\ensuremath{\rangle}}}} +\newcommand\NOTE[1]{\leavevmode\marginpar{#1}} + +\def\mynobreakpar{\par\nobreak\@afterheading} +\def\docprefix#1{\texttt{\textcolor{gray}{#1}}} +\def\sankeykeysprefix{/sankey} + +\newenvironment{sankeyoption}[5][]{% [prefix] key, val, default, initially + \begingroup + % + \def\keypath{#1}% + \def\key{#2}% + \def\val{#3}% + \def\default{#4}% + \def\initially{#5}% + %\setlength\parindent{\dimexpr.5\parindent\relax}% + % \vspace{.25\baselineskip plus .25\baselineskip minus 0mm} + \parfillskip 0pt plus 1fil% + \leavevmode% + \ttfamily% + \hspace*{-1cm}% + \textcolor{red!75!black}{\texttt{\docprefix{\ifdefempty{\keypath}{\sankeykeysprefix/}{\keypath/}}\key}}% + \ifdefempty{\val}{}{=\val}% + \hfill% + \ifdefempty{\default}{\null}{(default:\,\constant{\default})}% + \ifdefempty{\initially}{\null}{(initially:\,\constant{\initially})}% + \mynobreakpar% + \endgroup% + \parskip=.5\baselineskip plus .25\baselineskip minus .25\baselineskip + \parfillskip=30pt plus 1fil + \itemize[topsep=0pt,partopsep=0pt,itemsep=0pt]\item[] +}{% + \enditemize% +} + +\newcommand\MACRO{\hspace*{-1cm}} + +\newlist{sankeyconstantsdesc}{description}{1} +\setlist[sankeyconstantsdesc]{align=right,labelindent=1.5em,labelsep=.5em,leftmargin=!,font=\normalfont} + +\newlength{\myparskip} +\setlength{\myparskip}{.75\baselineskip plus 8\baselineskip minus .25\baselineskip} +\usepackage[skip=\myparskip]{parskip} +\newenvironment{miniblock}{% + \vspace{.5\parskip}% +}{% +} + +\tikzset{ + every picture/.style={ + execute at end picture={ + \begin{pgfonlayer}{background} + \node[fit=(current bounding box),inner sep=0](bb){}; + \def\rs{5mm} + \draw[gray!25] let + \p{sw}=(bb.south west), \p{ne}=(bb.north east), + \n{maxx}={ceil(\x{ne}/\rs)*\rs}, \n{minx}={floor(\x{sw}/\rs)*\rs}, + \n{maxy}={ceil(\y{ne}/\rs)*\rs}, \n{miny}={floor(\y{sw}/\rs)*\rs} + in (\n{minx},\n{miny}) grid (\n{maxx},\n{maxy}); + \begin{scope}[overlay] + \draw[gray!50,-latex] let + \p{sw}=(bb.south west), \p{ne}=(bb.north east), + \n{maxx}={ceil(\x{ne}/\rs)*\rs}, \n{minx}={floor(\x{sw}/\rs)*\rs}, + \n{maxy}={ceil(\y{ne}/\rs)*\rs}, \n{miny}={floor(\y{sw}/\rs)*\rs} + in (\n{minx},0) -- (\n{maxx}+1mm,0); + \draw[gray!50,-latex] let + \p{sw}=(bb.south west), \p{ne}=(bb.north east), + \n{maxx}={ceil(\x{ne}/\rs)*\rs}, \n{minx}={floor(\x{sw}/\rs)*\rs}, + \n{maxy}={ceil(\y{ne}/\rs)*\rs}, \n{miny}={floor(\y{sw}/\rs)*\rs} + in (0,\n{miny}) -- (0,\n{maxy}+1mm); + \end{scope} + \end{pgfonlayer} + } + } +} + +\def\MacroFont{ + \fontencoding\encodingdefault + \fontfamily\ttdefault + \fontseries\mddefault + \fontshape\shapedefault + \footnotesize% +} +%</sankeydocpreamble> +% \fi +\endinput + +% Local Variables: +% mode: doctex +% LaTeX-verbatim-macros-with-braces-local: ("code") +% TeX-master: t +% End: diff --git a/Master/texmf-dist/source/latex/sankey/sankey.ins b/Master/texmf-dist/source/latex/sankey/sankey.ins new file mode 100644 index 00000000000..ab11ca1dc11 --- /dev/null +++ b/Master/texmf-dist/source/latex/sankey/sankey.ins @@ -0,0 +1,85 @@ +%% +%% Copyright (C) 2016, 2021 by Paul Gaborit +%% +%% This work may be distributed and/or modified under the conditions of +%% the LaTeX Project Public License, either version 1.3 of this license +%% or (at your option) any later version. The latest version of this +%% license is in +%% +%% <http://www.latex-project.org/lppl.txt> +%% +%% and version 1.3 or later is part of all distributions of LaTeX version +%% 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status “maintained”. +%% +%% The Current Maintainer of this work is Paul Gaborit. +%% +%% This work consists of the files sankey.dtx, sankey.ins and the derived +%% files sankey.sty, tikzlibrarydubins.code.tex, sankey-doc-preamble.sty, +%% sankey-example1.tex, sankey-example2.tex, sankey-example3.tex, +%% sankey-example3-variation.tex, sankey-example4.tex, +%% sankey-example-energy.tex +%% + +\input docstrip.tex +\keepsilent + +\usedir{tex/latex/sankey} + +\preamble + +This is a generated file. + +Copyright (C) 2016, 2021 by Paul Gaborit + +This work may be distributed and/or modified under the conditions of the +LaTeX Project Public License, either version 1.3 of this license or (at +your option) any later version. The latest version of this license is +in + +<http://www.latex-project.org/lppl.txt> + +and version 1.3 or later is part of all distributions of LaTeX version +2005/12/01 or later. + +This work has the LPPL maintenance status “maintained”. + +The Current Maintainer of this work is Paul Gaborit. + +This work consists of the files sankey.dtx, sankey.ins and the derived +files sankey.sty, tikzlibrarydubins.code.tex, sankey-doc-preamble.sty, +sankey-example1.tex, sankey-example2.tex, sankey-example3.tex, +sankey-example3-variation.tex, sankey-example4.tex, +sankey-example-energy.tex + +\endpreamble + +\generate{% + \askforoverwritefalse + \file{sankey.sty}{\from{sankey.dtx}{sankey}}% + \file{tikzlibrarydubins.code.tex}{\from{sankey.dtx}{tikzlibrarydubins.code.tex}}% + \file{sankey-example-energy.tex}{\nopreamble\nopostamble\from{sankey.dtx}{example-energy}}% + \file{sankey-example1.tex}{\nopreamble\nopostamble\from{sankey.dtx}{example1}}% + \file{sankey-example2.tex}{\nopreamble\nopostamble\from{sankey.dtx}{example2}}% + \file{sankey-example3.tex}{\nopreamble\nopostamble\from{sankey.dtx}{example3}}% + \file{sankey-example3-variation.tex}{\nopreamble\nopostamble\from{sankey.dtx}{example3-variation}}% + \file{sankey-example4.tex}{\nopreamble\nopostamble\from{sankey.dtx}{example4}}% + \file{sankey-doc-preamble.sty}{\from{sankey.dtx}{sankeydocpreamble}}% +} + +\Msg{*********************************************************} +\Msg{*} +\Msg{* To finish the installation you have to move the} +\Msg{* following file into a directory searched by TeX:} +\Msg{*} +\Msg{* \space\space sankey.sty} +\Msg{* \space\space tikzlibrarydubins.code.tex} +\Msg{*} +\Msg{* To produce the documentation run the file sankey.dtx} +\Msg{* through (pdf)LaTeX.} +\Msg{*} +\Msg{* Happy TeXing!} +\Msg{*********************************************************} + +\endbatchfile
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/sankey/sankey-doc-preamble.sty b/Master/texmf-dist/tex/latex/sankey/sankey-doc-preamble.sty new file mode 100644 index 00000000000..9bfa992cf80 --- /dev/null +++ b/Master/texmf-dist/tex/latex/sankey/sankey-doc-preamble.sty @@ -0,0 +1,226 @@ +\usepackage[paper=a4paper,vmargin=1.5cm,left=4.5cm,right=3.5cm]{geometry} +\usepackage[utf8]{inputenc} +\usepackage{cmap} +\usepackage[T1]{fontenc} +\usepackage{lmodern} +\usepackage[final,protrusion=true,expansion=true]{microtype} +\usepackage{xcolor} +\PassOptionsToPackage{final,colorlinks,linkcolor=red!60!orange!85!black}{hyperref} +\usepackage[numbered]{hypdoc} +\usepackage{fancyvrb} +\usepackage[final]{listings} +\usepackage{enumitem} +\usepackage{bookmark} +\usepackage{siunitx} +\usepackage{footnote} +\usepackage{etoc} +\usepackage{accsupp} +\usepackage{tikz} +\usetikzlibrary{positioning,patterns.meta,fit} +\usepackage[british]{babel} +\usepackage{varioref} +\usepackage{embedfile} +\usepackage{dtx-attach} +\embedfile[mimetype=text/plain]{sankey.ins} +\usepackage{sankey} + +\colorlet{bgcode}{yellow!50!gray!5} +\colorlet{keyword}{blue!50!cyan!50!black} +\colorlet{comment}{red!75!black} + +\newcommand\emptyaccsupp[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}} + +\lstset{ + literate= + {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ú}{{\'u}}1 + {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1 + {à}{{\`a}}1 {è}{{\`e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1 + {À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1 + {ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1 + {Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1 + {â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1 + {Â}{{\^A}}1 {Ê}{{\^E}}1 {Î}{{\^I}}1 {Ô}{{\^O}}1 {Û}{{\^U}}1 + {œ}{{\oe}}1 {Œ}{{\OE}}1 {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1 + {ç}{{\c c}}1 {Ç}{{\c C}}1 {ø}{{\o}}1 {å}{{\r a}}1 {Å}{{\r A}}1 + {€}{{\texteuro}}1 {£}{{\pounds}}1 {°}{{\degres}}1 + {’}{{\textquoteright}}1 {‘}{{\textquoteleft}}1 + {«}{{<<}}1 {»}{{>>}}1 + {—}{{---}}1 {−}{{$-$}}1 + {\^\^A}{{}}0 % verbatim in .dtx file +} + +\lstset{ + fancyvrb=true, + escapechar=`, + extendedchars=true, + fontadjust=true, + columns=fullflexible, + flexiblecolumns=true, + inputencoding=utf8, + keepspaces=true, + backgroundcolor=\color{bgcode}, + basicstyle=\mdseries\ttfamily, + keywordstyle=\color{keyword}, + stringstyle=\ttfamily\color{green!50!black}, + commentstyle=\color{comment}\itshape, + emphstyle=\bfseries\color{red}, + numbersep=5pt, + %numbers=left, + numberstyle=\tiny\emptyaccsupp, + showstringspaces=false, + upquote=true, + aboveskip=.5\parskip, + belowskip=.5\parskip, + framexleftmargin=1pt, + framexrightmargin=1pt, + gobble=2, % \lstlisting code in .dtx +} + +\lstdefinestyle{textsmall}{basicstyle=\color{black}\small\mdseries\ttfamily} +\lstdefinestyle{textfootnotesize}{basicstyle=\color{black}\footnotesize\mdseries\ttfamily} +\lstdefinestyle{textscriptsize}{basicstyle=\color{black}\scriptsize\mdseries\ttfamily} +\lstdefinestyle{texttiny}{basicstyle=\color{black}\tiny\mdseries\ttfamily} + +\lstdefinestyle{LaTeX}{ + language=[LaTeX]TeX, + moretexcs={ + Lab, + LabSet, + Qty, + QtySet, + colorlet, + coordinate, + countries, + country, + countryname, + definecolor, + draw, + endcountry, + fill, + foreach, + hashband, + hdist, + hwidth, + node, + nodename, + path, + sankeyadvance, + sankeydubins, + sankeyend, + sankeyend, + sankeyfork, + sankeynode, + sankeynodealias, + sankeynodeend, + sankeynodestart, + sankeyoutin, + sankeyset, + sankeystart, + sankeyturn, + sankeyturnleft, + sankeyturnleftbackward, + sankeyturnright, + sankeyturnrightbackward, + sisetup, + startcountry, + tikzset, + turnandstop, + usepackage, + vdist, + } +} +\lstdefinestyle{LaTeXsmall}{style=LaTeX,style=textsmall} +\lstdefinestyle{LaTeXfootnotesize}{style=LaTeX,style=textfootnotesize} +\lstdefinestyle{LaTeXscriptsize}{style=LaTeX,style=textscriptsize} +\lstdefinestyle{LaTeXtiny}{style=LaTeX,style=texttiny} + +\def\code{\lstinline[basicstyle=\mdseries\ttfamily\color{red!50!black}]} + +\edef\samplecodename{\jobname-code.vrb} + +\newcommand\constant[1]{\textcolor{violet}{\texttt{#1}}} +\newcommand\ARG[1]{\texttt{\{#1\}}} +\newcommand\OPTARG[1]{\textcolor{green!50!black}{\texttt{[#1]}}} +\newcommand\VAR[1]{\textit{\texttt{\ensuremath{\langle}#1\ensuremath{\rangle}}}} +\newcommand\NOTE[1]{\leavevmode\marginpar{#1}} + +\def\mynobreakpar{\par\nobreak\@afterheading} +\def\docprefix#1{\texttt{\textcolor{gray}{#1}}} +\def\sankeykeysprefix{/sankey} + +\newenvironment{sankeyoption}[5][]{% [prefix] key, val, default, initially + \begingroup + % + \def\keypath{#1}% + \def\key{#2}% + \def\val{#3}% + \def\default{#4}% + \def\initially{#5}% + %\setlength\parindent{\dimexpr.5\parindent\relax}% + % \vspace{.25\baselineskip plus .25\baselineskip minus 0mm} + \parfillskip 0pt plus 1fil% + \leavevmode% + \ttfamily% + \hspace*{-1cm}% + \textcolor{red!75!black}{\texttt{\docprefix{\ifdefempty{\keypath}{\sankeykeysprefix/}{\keypath/}}\key}}% + \ifdefempty{\val}{}{=\val}% + \hfill% + \ifdefempty{\default}{\null}{(default:\,\constant{\default})}% + \ifdefempty{\initially}{\null}{(initially:\,\constant{\initially})}% + \mynobreakpar% + \endgroup% + \parskip=.5\baselineskip plus .25\baselineskip minus .25\baselineskip + \parfillskip=30pt plus 1fil + \itemize[topsep=0pt,partopsep=0pt,itemsep=0pt]\item[] +}{% + \enditemize% +} + +\newcommand\MACRO{\hspace*{-1cm}} + +\newlist{sankeyconstantsdesc}{description}{1} +\setlist[sankeyconstantsdesc]{align=right,labelindent=1.5em,labelsep=.5em,leftmargin=!,font=\normalfont} + +\newlength{\myparskip} +\setlength{\myparskip}{.75\baselineskip plus 8\baselineskip minus .25\baselineskip} +\usepackage[skip=\myparskip]{parskip} +\newenvironment{miniblock}{% + \vspace{.5\parskip}% +}{% +} + +\tikzset{ + every picture/.style={ + execute at end picture={ + \begin{pgfonlayer}{background} + \node[fit=(current bounding box),inner sep=0](bb){}; + \def\rs{5mm} + \draw[gray!25] let + \p{sw}=(bb.south west), \p{ne}=(bb.north east), + \n{maxx}={ceil(\x{ne}/\rs)*\rs}, \n{minx}={floor(\x{sw}/\rs)*\rs}, + \n{maxy}={ceil(\y{ne}/\rs)*\rs}, \n{miny}={floor(\y{sw}/\rs)*\rs} + in (\n{minx},\n{miny}) grid (\n{maxx},\n{maxy}); + \begin{scope}[overlay] + \draw[gray!50,-latex] let + \p{sw}=(bb.south west), \p{ne}=(bb.north east), + \n{maxx}={ceil(\x{ne}/\rs)*\rs}, \n{minx}={floor(\x{sw}/\rs)*\rs}, + \n{maxy}={ceil(\y{ne}/\rs)*\rs}, \n{miny}={floor(\y{sw}/\rs)*\rs} + in (\n{minx},0) -- (\n{maxx}+1mm,0); + \draw[gray!50,-latex] let + \p{sw}=(bb.south west), \p{ne}=(bb.north east), + \n{maxx}={ceil(\x{ne}/\rs)*\rs}, \n{minx}={floor(\x{sw}/\rs)*\rs}, + \n{maxy}={ceil(\y{ne}/\rs)*\rs}, \n{miny}={floor(\y{sw}/\rs)*\rs} + in (0,\n{miny}) -- (0,\n{maxy}+1mm); + \end{scope} + \end{pgfonlayer} + } + } +} + +\def\MacroFont{ + \fontencoding\encodingdefault + \fontfamily\ttdefault + \fontseries\mddefault + \fontshape\shapedefault + \footnotesize% +} diff --git a/Master/texmf-dist/tex/latex/sankey/sankey.sty b/Master/texmf-dist/tex/latex/sankey/sankey.sty index 4c28a1fe0d4..b6734004f77 100644 --- a/Master/texmf-dist/tex/latex/sankey/sankey.sty +++ b/Master/texmf-dist/tex/latex/sankey/sankey.sty @@ -1,722 +1,811 @@ -% Copyright (C) 2016-2021 by Paul Gaborit -% -% This file may be distributed and/or modified -% -% 1. under the LaTeX Project Public License and/or -% -% 2. under the GNU Public License. - -\def\sankey@version{2.0} -\def\sankey@date{2021/01/27} -\ProvidesPackage{sankey}[\sankey@date\space\sankey@version\space sankey package] - +%% +%% This is file `sankey.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% sankey.dtx (with options: `sankey') +%% +%% This is a generated file. +%% +%% Copyright (C) 2016, 2021 by Paul Gaborit +%% +%% This work may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License, either version 1.3 of this license or (at +%% your option) any later version. The latest version of this license is +%% in +%% +%% <http://www.latex-project.org/lppl.txt> +%% +%% and version 1.3 or later is part of all distributions of LaTeX version +%% 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status “maintained”. +%% +%% The Current Maintainer of this work is Paul Gaborit. +%% +%% This work consists of the files sankey.dtx, sankey.ins and the derived +%% files sankey.sty, tikzlibrarydubins.code.tex, sankey-doc-preamble.sty, +%% sankey-example1.tex, sankey-example2.tex, sankey-example3.tex, +%% sankey-example3-variation.tex, sankey-example4.tex, +%% sankey-example-energy.tex +%% +\NeedsTeXFormat{LaTeX2e}[2015/10/01] +\ProvidesPackage{sankey}[2021/03/14 v3.0 to draw Sankey diagrams] \RequirePackage{xparse} +\RequirePackage{etoolbox} \RequirePackage{xfp} \RequirePackage{tikz} -\usetikzlibrary{calc,decorations.markings,dubins} -\usepackage{etoolbox} - -% add a new layer to debug sankey diagrams +\usetikzlibrary{ + calc, + decorations.markings, + dubins +} +%% add a new layer to debug sankey diagrams \pgfdeclarelayer{background} \pgfdeclarelayer{foreground} \pgfdeclarelayer{sankeydebug} \pgfsetlayers{background,main,foreground,sankeydebug} - -% flag to debug sankey diagrams -\newtoggle{sankey debug} -\newtoggle{sankey node start} -\newtoggle{sankey node end} - -% macros to store and to retrieve the orientation and the quantity -% associated with each sankey node - -\def\sankeysetnodeqty#1#2{\expandafter\xdef\csname sankey@node@#1@qty\endcsname{#2}} - -\def\sankeygetnodeqty#1{% - \ifcsmacro{sankey@node@#1@qty}{% - \csname sankey@node@#1@qty\endcsname% - }{% - \PackageWarning{sankey}{Unknown sankey node '#1'}% - }% +\def\snk@newfield#1#2#3#4#5{ + % setter + \def#2##1##2{\expandafter#1\csname #4\endcsname{##2}} + % getter + \def#3##1{% + \ifcsdef{#4}{% + \csname#4\endcsname% + }{% + \PackageError{sankey}{#5}{unknown key with \string#3}% + }% + } } - -\def\sankeysetnodeorient#1#2{\expandafter\xdef\csname sankey@node@#1@orient\endcsname{#2}} - -\def\sankeygetnodeorient#1{% - \ifcsmacro{sankey@node@#1@orient}{% - \csname sankey@node@#1@orient\endcsname% - }{% - \PackageWarning{sankey}{Unknown sankey node '#1'}% - }% +\snk@newfield\xdef\snk@setnodeqty\sankeygetnodeqty% +{@snk@node@qty@#1}{Unknown sankey node '#1'} +\snk@newfield\xdef\snk@setnodeorient\sankeygetnodeorient% +{@snk@node@orient@#1}{Unknown sankey node '#1'} +\snk@newfield\def\snk@setstartfill\snk@getstartfill% +{@snk@start@fill@#1}{Unknown sankey start fill path #1} + +\snk@newfield\def\snk@setstartdraw\snk@getstartdraw% +{@snk@start@draw@#1}{Unknown sankey start draw path #1} +\snk@newfield\def\snk@setendfill\snk@getendfill% +{@snk@end@fill@#1}{Unknown sankey end fill path #1} + +\snk@newfield\def\snk@setenddraw\snk@getenddraw% +{@snk@end@draw@#1}{Unknown sankey end draw path #1} + +\newcommand\snk@ifnodedefined[3]{% + \ifcsdef{@snk@node@qty@#1}{#2}{#3}% +} +\newcommand\snk@errorifnotdefined[1]{% + \snk@ifnodedefined{#1}{}% + {\PackageError{sankey}{Unknown sankey node '#1'}{}}% } - -\def\sankeysetstartfill#1#2{\expandafter\gdef\csname sankey@start@fill@#1\endcsname{#2}} -\def\sankeysetstartdraw#1#2{\expandafter\gdef\csname sankey@start@draw@#1\endcsname{#2}} -\def\sankeysetendfill#1#2{\expandafter\gdef\csname sankey@end@fill@#1\endcsname{#2}} -\def\sankeysetenddraw#1#2{\expandafter\gdef\csname sankey@end@draw@#1\endcsname{#2}} -% -\def\sankeygetstartfill#1{\csname sankey@start@fill@#1\endcsname} -\def\sankeygetstartdraw#1{\csname sankey@start@draw@#1\endcsname} -\def\sankeygetendfill#1{\csname sankey@end@fill@#1\endcsname} -\def\sankeygetenddraw#1{\csname sankey@end@draw@#1\endcsname} - -% new shape \pgfdeclareshape{sankey node}{ \inheritsavedanchors[from=rectangle] \inheritanchor[from=rectangle]{center} - %\inheritanchorborder[from=rectangle] + \inheritanchorborder[from=rectangle] \anchor{left}{\pgf@process{\northeast}} \anchor{right}{\pgf@process{\southwest}} + % compatibility with 'fit' library + \inheritanchor[from=rectangle]{west} + \inheritanchor[from=rectangle]{east} + \inheritanchor[from=rectangle]{north} + \inheritanchor[from=rectangle]{south} + \inheritanchor[from=rectangle]{north west} + \inheritanchor[from=rectangle]{south east} + \inheritanchor[from=rectangle]{north east} + \inheritanchor[from=rectangle]{south west} } - -% pgfkeys family 'sankey' \pgfkeys{/sankey/.is family} - \NewDocumentCommand\sankeyset{m}{\pgfkeys{sankey,#1}} - \sankeyset{ + ratio quantity/.code={\edef\snk@totalqty{\fpeval{#1}}}, + ratio quantity/.value required, ratio length/.code={ - \pgfmathsetmacro\sankeytotallen{#1} - \edef\sankeytotallen{\sankeytotallen pt} + \pgfmathsetmacro\snk@totallen{#1} + \edef\snk@totallen{\snk@totallen 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, +} +\sankeyset{ + rotate/.code={\edef\snk@rotate{\fpeval{#1}}}, + rotate/.value required, +} +\sankeyset{ + minimum radius/.code={ + \pgfmathsetmacro\snk@minradius{#1} + \edef\snk@minradius{\snk@minradius pt} + }, minimum radius/.value required, - outin steps/.estore in=\sankeystepoutin, +} +\sankeyset{ + outin steps/.estore in=\snk@stepoutin, outon steps/.value required, - % +} +\newtoggle{sankey debug} +\sankeyset{ debug/.is choice, debug/true/.code={\toggletrue{sankey debug}}, debug/false/.code={\togglefalse{sankey debug}}, debug/.default=true, - % +} +\sankeyset{ start style/.is choice, - % end style/.is choice, - % default values - default parameters/.style={ - % default values + % to define new start and end styles + new start style/.code n args={3}{% name, fill path, draw path + \snk@setstartfill{#1}{#2} + \snk@setstartdraw{#1}{#3} + \sankeyset{start style/#1/.code={\def\snk@startstyle{#1}}} + }, + new end style/.code n args={3}{% name, fill path, draw path + \snk@setendfill{#1}{#2} + \snk@setenddraw{#1}{#3} + \sankeyset{end style/#1/.code={\def\snk@endstyle{#1}}} + }, +} +\sankeyset{ + debug color/.style={/utils/exec={\colorlet{debug color}{#1}}}, + @initial options/.style={ ratio=1cm/10, minimum radius=5mm,% outin steps=10, debug=false, start style=none, end style=none, - }, - % 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}% + rotate=0, + % default fill/draw styles, + fill/.style={line width=0pt,fill=white}, + draw/.style={draw=black,line width=.4pt}, + % debug color used by all debug macros + debug color=red!75!black, + % debug line between left and right anchors + debug line/.style={overlay,draw=debug color,|-|}, + % debug line between center and label + debug normal/.style={overlay,draw=debug color}, + % debug node label + debug label/.style={ + overlay, + draw, + font=\ttfamily\tiny, + text=debug color,text opacity=1, + inner sep=.1em, + fill=white,fill opacity=1, + rounded corners=.1em, + node contents={\name}, }, - 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, + every node/.style={}, }, + every diagram/.style={}, } -% 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={}, +\sankeyset{node parameters/.is family} +\sankeyset{node parameters, + name/.estore in=\name, + name/.value required, + quantity/.code={\edef\qty{\fpeval{#1}}}, + quantity/.value required, + angle/.code={\edef\orient{\snk@normalize@angle{#1}}}, + angle/.value required, + at/.code={\snk@getpos\pos{#1}}, + at/.value required, +} +\sankeyset{node parameters, + as/.style={ + name=#1, + quantity=\sankeygetnodeqty{#1}, + angle=\sankeygetnodeorient{#1}, + at={#1.center}, }, - 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, + as/.value required, +} +\sankeyset{node parameters, + anchor/.is choice, + anchor/left/.code={\def\snk@anchor{left}}, + anchor/right/.code={\def\snk@anchor{right}}, + anchor/center/.code={\def\snk@anchor{center}}, + anchor/.value required, +} +\newtoggle{sankey node start} +\newtoggle{sankey node end} +\sankeyset{node parameters, + start/.is choice, + start/true/.code={\toggletrue{sankey node start}}, + start/false/.code={\togglefalse{sankey node start}}, + start/.default=true, + % + end/.is choice, + end/true/.code={\toggletrue{sankey node end}}, + end/false/.code={\togglefalse{sankey node end}}, + end/.default=true, +} +\sankeyset{node parameters, + forked/.estore in=\snk@listofforks, + forked/.value required, + fork anchor/.estore in=\snk@forkanchor, + fork anchor/.value required, +} +\sankeyset{node parameters, + @initial parameters/.style={ + start=false, + end=false, + forked=, + fork anchor=, + anchor=center, + at={0,0}, + angle=0, }, } - \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}}} + % sankey node TikZ style + @sankey node/.style n args={3}{% name, pos, anchor + shape=sankey node, + inner sep=0, + minimum height={\sankeyqtytolen{\sankeygetnodeqty{#1}}}, + minimum width=0, + draw=none, + line width=0pt, + fill=none, + node contents={}, + rotate=\sankeygetnodeorient{#1}+\snk@rotate, + at={(#2)}, + name=#1, + anchor=#3, }, } - -% 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 +\NewDocumentEnvironment{sankeydiagram}{O{}}{ + \def\snk@getpos##1##2{% + \tikz@scan@one@point\pgfutil@firstofone(##2)\relax% + \edef##1{\the\pgf@x,\the\pgf@y}% } - - \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 + \def\snk@modulo##1##2{\fpeval{##1-(floor((##1)/(##2),0)*##2)}} + \def\snk@normalize@angle##1{% + \fpeval{\snk@modulo{(##1)+180}{360}-180}% } - - \newcommand\sankeymakenode{ - \begingroup - \sankeymakenodenodebug{} + \def\snk@show@debug##1{% node name \iftoggle{sankey debug}{ + \begingroup + \edef\name{##1} + \edef\qty{\sankeygetnodeqty{\name}} + \edef\orient{\sankeygetnodeorient{\name}} \begin{pgfonlayer}{sankeydebug} - \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} + \pgfmathsetmacro{\snk@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}}; + -- ($(\name.center)!\snk@len pt!90:(\name.right)$) + node[/sankey/debug label,rotate=\orient+90+\snk@rotate,anchor=north]; \end{pgfonlayer} + \endgroup }{} + } + \def\snk@makeforkednode{ + \begingroup + \ifdefempty{\snk@listofforks}{ + \ifdefempty{\snk@forkanchor}{}{ + \PackageWarning{sankey}% + {Can't use 'fork anchor' key without 'forked' key} + } + }{ + \def\snk@tot{0} + \def\snk@added@values{} + \sankeyset{ + @add forked node/.code args={####1/####2}{ + \coordinate (####2) at ($(\name.left)% + !\fpeval{(\snk@tot+.5*(####1))/\qty}% + !(\name.right)$); + \edef\snk@orient{\orient} + \sankeynode[debug=false] + {name=####2,quantity=####1,at=####2,angle=\snk@orient} + \edef\snk@tot{\fpeval{\snk@tot+####1}} + \edef\snk@added@values{\snk@added@values+####1} + }, + @add forked node/.list/.expand once=\snk@listofforks, + } + \edef\snk@diff{\fpeval{abs(\qty-\snk@tot)}} + \ifnumequal{\snk@diff}{0}{}{ + \PackageWarning{sankey}% + {^^J*** Warning: bad sankey fork: % + \qty\space!=\space\snk@added@values(=\snk@tot)% + ^^J\snk@listofforks} + } + \ifdefempty{\snk@forkanchor}{ + \edef\snk@forkanchor{\name.\snk@anchor} + }{} + \snk@getpos\snk@c{$(\snk@forkanchor) - (\pos)$} + \sankeynode{as=\name,at={$(\name) - (\snk@c)$}} + \foreach \snk@subnodeqty/\snk@subnodename in \snk@listofforks { + \sankeynode{as=\snk@subnodename,at={$(\snk@subnodename) - (\snk@c)$}} + } + } \endgroup } - - \newcommand\sankeynodenodebug[1]{ + \def\snk@makenode{ \begingroup - \sankeyset{node parameters,##1} - %\typeout{sankeynodenodebug: '\name' at(\pos) angle(\orient) qty(\qty)} - \sankeymakenodenodebug{} + \snk@setnodeqty{\name}{\qty} + \edef\orient{\snk@normalize@angle{\orient}} + \snk@setnodeorient{\name}{\orient} + \ifundef{\snk@anchor}{\def\snk@anchor{center}}{} + \node[/sankey/@sankey node={\name}{\pos}{\snk@anchor}]; \endgroup } - - % ============================================================ - % user commands - % ============================================================ - - \NewDocumentCommand\sankeydubins{O{}mm}{% options, sn, en + \def\snk@filldrawstart{ + \begin{scope}[shift={(\name)},rotate=\orient] + \path[/sankey/fill] \snk@getstartfill{\snk@startstyle}; + \path[/sankey/draw] \snk@getstartdraw{\snk@startstyle}; + \end{scope} + } + \def\snk@filldrawend{ + \begin{scope}[shift={(\name)},rotate=\sankeygetnodeorient{\name}] + \path[/sankey/fill] \snk@getendfill{\snk@endstyle}; + \path[/sankey/draw] \snk@getenddraw{\snk@endstyle}; + \end{scope} + } + \def\snk@checkquantities##1##2##3{ \begingroup - \sankeyset{##1} - \pgfmathsetmacro\startangle{\sankeygetnodeorient{##2}} - \pgfmathsetmacro\endangle{\sankeygetnodeorient{##3}} - \edef\sqty{\sankeygetnodeqty{##2}} - \edef\eqty{\sankeygetnodeqty{##3}} - \ifdefstrequal{\sqty}{\eqty}{}{ + \edef\snk@qtyi{\sankeygetnodeqty{##1}} + \edef\snk@qtyii{\sankeygetnodeqty{##2}} + \ifdefstrequal{\snk@qtyi}{\snk@qtyii}{}{ \PackageError{sankey}% - {^^J*** \string\sankeyoutin: quantities differ between ##2 (\sqty) and ##3 (\eqty)^^J}% + {^^J*** \string##3: quantities differ between % + ##1 (\snk@qtyi) and ##2 (\snk@qtyii)% + ^^J}% {The quantities of the two Sankey nodes must be equal.} } + \endgroup + } + \NewDocumentCommand\sankeydubins{O{}mm}{% options, sn, en + \snk@errorifnotdefined{##2} + \snk@errorifnotdefined{##3} + \snk@checkquantities{##2}{##3}{\sankeydubins} + \begingroup + \sankeyset{##1} \pgfmathsetmacro\qty{\sankeygetnodeqty{##2}} - \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, + start point=##2.center,start angle=\sankeygetnodeorient{##2}, + end point=##3.center,end angle=\sankeygetnodeorient{##3}, + minimum radius=\snk@minradius + .5 * \sankeyqtytolen{\qty} pt, }, } \dubinspathcalc{sankey,store=sankey} - \dubinspathset{ left border/.style={ sankey, use store=sankey, - left and right minimum radii= - {\sankeyminradius} and {\sankeyminradius + \width pt}, + left and right minimum radii={\snk@minradius} + and {\snk@minradius + \sankeyqtytolen{\qty} pt}, }, right border/.style={ sankey, use store=sankey, left and right minimum radii= - {\sankeyminradius + \width pt} and {\sankeyminradius}, + {\snk@minradius + \sankeyqtytolen{\qty} pt} + and {\snk@minradius}, }, } - - \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} - }; + % fill the region + \path[/sankey/fill] (##2.left) \dubinspath{left border} + -- (##3.left) -- (##3.right) \dubinspath{right border,reverse} + -- (##2.right) -- cycle; + % draw left and right borders + \path[/sankey/draw] (##2.left) \dubinspath{left border} + (##2.right) \dubinspath{right border}; \endgroup } - - \NewDocumentCommand\sankeyoutin{O{}mm}{% options, sn, en + \snk@errorifnotdefined{##2} + \snk@errorifnotdefined{##3} + \snk@checkquantities{##2}{##3}{\sankeyoutin} \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={ + \edef\qty{\sankeygetnodeqty{##2}} + \pgfmathsetmacro\snk@len{\sankeyqtytolen{\qty}/2} + \edef\snk@step{\fpeval{1/\snk@stepoutin}} + \edef\snk@laststep{\inteval{\snk@stepoutin-1}} + \path[overlay,decorate,decoration={ markings, - mark=between positions \mystep and \mybound step \mystep with { - \def\sankeyoutinmidptname{sankeyoutinmidpt \pgfkeysvalueof{/pgf/decoration/mark info/sequence number}} + mark=between positions \snk@step and {\fpeval{1-.5*\snk@step}} + step \snk@step with { + \edef\snk@outinmidptname{% + snk@outinmidpt-% + \pgfkeysvalueof{/pgf/decoration/mark info/sequence number}% + } \path - (0,0) coordinate(\sankeyoutinmidptname) - (0,-\mylength pt) coordinate (\sankeyoutinmidptname\space r) - (0,\mylength pt) coordinate (\sankeyoutinmidptname\space l) + (0,0) coordinate(\snk@outinmidptname) + (0,-\snk@len pt) coordinate (\snk@outinmidptname-r) + (0,\snk@len pt) coordinate (\snk@outinmidptname-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} + }] + (##2.center) + to[out=\sankeygetnodeorient{##2},in=\sankeygetnodeorient{##3}+180] + (##3.center); + \foreach \snk@ptnum in {1,...,\snk@laststep}{ + \edef\snk@outinmidptname{snk@outinmidpt-\snk@ptnum} + \dbp@anglebetween\snk@outinmidptangle% + {\snk@outinmidptname-r}{\snk@outinmidptname-l} + \sankeynode[debug=false]{% + name=\snk@outinmidptname, + quantity=\qty, + angle=\snk@outinmidptangle-90,% + at=\snk@outinmidptname% + } + } + \sankeynode[debug=false]{% + name={snk@outinmidpt-0}, + quantity=\sankeygetnodeqty{##2}, + angle=\sankeygetnodeorient{##2},% + at={##2}% + } + \sankeynode[debug=false]{% + name={snk@outinmidpt-\snk@stepoutin}, + quantity={\sankeygetnodeqty{##3}}, + angle={\sankeygetnodeorient{##3}},% + at={##3}% } - \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) + (snk@outinmidpt-0.left) + \foreach \snk@curpt + [remember=\snk@curpt as \snk@prevpt (initially 0)] + in {1,...,\snk@stepoutin}{ + to[out=\sankeygetnodeorient{snk@outinmidpt-\snk@prevpt}, + in=\sankeygetnodeorient{snk@outinmidpt-\snk@curpt}+180] + (snk@outinmidpt-\snk@curpt.left) } -- - (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) + (snk@outinmidpt-\snk@stepoutin.right) + \foreach \snk@curpt + [remember=\snk@curpt as \snk@prevpt (initially \snk@stepoutin)] + in {\snk@laststep,...,0}{ + to[out=\sankeygetnodeorient{snk@outinmidpt-\snk@prevpt}+180, + in=\sankeygetnodeorient{snk@outinmidpt-\snk@curpt}] + (snk@outinmidpt-\snk@curpt.right) } -- cycle; - \path[/sankey/draw,looseness=1] - (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) + (snk@outinmidpt-0.left) + \foreach \snk@curpt + [remember=\snk@curpt as \snk@prevpt (initially 0)] + in {1,...,\snk@stepoutin}{ + to[out=\sankeygetnodeorient{snk@outinmidpt-\snk@prevpt}, + in=\sankeygetnodeorient{snk@outinmidpt-\snk@curpt}+180] + (snk@outinmidpt-\snk@curpt.left) } - ; - + (snk@outinmidpt-\snk@stepoutin.right) + \foreach \snk@curpt + [remember=\snk@curpt as \snk@prevpt (initially \snk@stepoutin)] + in {\snk@laststep,...,0}{ + to[out=\sankeygetnodeorient{snk@outinmidpt-\snk@prevpt}+180, + in=\sankeygetnodeorient{snk@outinmidpt-\snk@curpt}] + (snk@outinmidpt-\snk@curpt.right) + }; \endgroup } - \NewDocumentCommand\sankeynodealias{mm}{%name, alias - \path [late options={name=##1,alias=##2}]; - \sankeysetnodeqty{##2}{\sankeygetnodeqty{##1}} - \sankeysetnodeorient{##2}{\sankeygetnodeorient{##1}} + \snk@errorifnotdefined{##1} + \path[late options={name=##1,alias=##2}]; + \snk@setnodeqty{##2}{\sankeygetnodeqty{##1}} + \snk@setnodeorient{##2}{\sankeygetnodeorient{##1}} } - - \newcommand\sankeynode[2][]{ + \NewDocumentCommand\sankeynode{O{}m}{% options, node parameters \begingroup \sankeyset{##1} - \sankeyset{node parameters,##2} - %\typeout{sankeynode: '\name' at(\pos) angle(\orient) qty(\qty)} - \sankeymakenode{} + \sankeyset{node parameters,@initial parameters,/sankey/every node,##2} + \snk@makenode{} + \snk@makeforkednode{} + \iftoggle{sankey node start}{\snk@filldrawstart}{} + \iftoggle{sankey node end}{\snk@filldrawend}{} + \snk@show@debug{\name} \endgroup } - - \def\sankeyfilldrawstart{ - \begin{scope}[shift={(\name)},rotate=\orient] - \path[/sankey/fill] \sankeygetstartfill{\sankeystartstyle}; - \path[/sankey/draw] \sankeygetstartdraw{\sankeystartstyle}; - \end{scope} - } - - \NewDocumentCommand\sankeystart{O{}m}{ + \NewDocumentCommand\sankeystart{O{}m}{% options, name + \snk@errorifnotdefined{##2} \begingroup \sankeyset{##1} \edef\name{##2} \edef\orient{\sankeygetnodeorient{##2}} \edef\qty{\sankeygetnodeqty{##2}} - \sankeyfilldrawstart + \snk@filldrawstart \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 + \NewDocumentCommand\sankeynodestart{O{}m}{% option, node parameters + \sankeynode[##1]{start,##2} } - - \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 + \NewDocumentCommand\sankeyend{O{}m}{%options, name + \snk@errorifnotdefined{##2} \begingroup \sankeyset{##1} \edef\name{##2} \edef\orient{\sankeygetnodeorient{##2}} \edef\qty{\sankeygetnodeqty{##2}} - \sankeyfilldrawend + \snk@filldrawend \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\sankeynodeend{O{}m}{% options, node parameters + \sankeynode[##1]{end,##2} } - - - - \NewDocumentCommand\sankeyadvance{sO{}mm}{% *(reverse), options, name, distance + \NewDocumentCommand\sankeyadvance{sO{}mm}{% + %params: *(reverse), options, name, distance + \snk@errorifnotdefined{##3} \begingroup \sankeyset{##2} - \def\newname{##3} - \def\oldname{##3-old} - \sankeynodealias{\newname}{\oldname} - % \typeout{*** sankeyadvance: ok (\oldname => \newname)} + \edef\name{##3} + \edef\snk@oldname{##3-old} + \sankeynodealias{\name}{\snk@oldname} \IfBooleanTF{##1}{ - % reverse advance + % move backward \sankeynode{ - at={$(\oldname.center)!##4!90:(\oldname.left)$}, - angle=\sankeygetnodeorient{\oldname}, - quantity=\sankeygetnodeqty{\oldname}, - name=\newname, + at={$(\snk@oldname.center)!##4!90:(\snk@oldname.left)$}, + angle=\sankeygetnodeorient{\snk@oldname}, + quantity=\sankeygetnodeqty{\snk@oldname}, + name=\name, } \path[/sankey/fill] - (\newname.left) -- (\oldname.left) - -- - (\oldname.right) -- (\newname.right) - -- cycle; + (\name.left) -- (\snk@oldname.left) + -- (\snk@oldname.right) -- (\name.right) -- cycle; \path[/sankey/draw] - (\newname.left) -- (\oldname.left) - (\oldname.right) -- (\newname.right); - \endgroup + (\name.left) -- (\snk@oldname.left) + (\snk@oldname.right) -- (\name.right); }{ - % advance + % move forward \sankeynode{ - at={$(\oldname.center)!##4!-90:(\oldname.left)$}, - angle=\sankeygetnodeorient{\oldname}, - quantity=\sankeygetnodeqty{\oldname}, - name=\newname, + at={$(\snk@oldname.center)!##4!-90:(\snk@oldname.left)$}, + angle=\sankeygetnodeorient{\snk@oldname}, + quantity=\sankeygetnodeqty{\snk@oldname}, + name=\name, } \path[/sankey/fill] - (\oldname.left) -- (\newname.left) - -- - (\newname.right) -- (\oldname.right) - -- cycle; + (\snk@oldname.left) -- (\name.left) + -- (\name.right) -- (\snk@oldname.right) -- cycle; \path[/sankey/draw] - (\oldname.left) -- (\newname.left) - (\newname.right) -- (\oldname.right); - \endgroup + (\snk@oldname.left) -- (\name.left) + (\name.right) -- (\snk@oldname.right); } + \snk@show@debug{\name} + \endgroup } - - \NewDocumentCommand\sankeyturn{sO{}mm}{% *(reverse), options, name, angle + \NewDocumentCommand\sankeyturnright{sO{}mm}{ + % *(reverse), options, name, angle + \snk@errorifnotdefined{##3} \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} - }; - } + \IfBooleanTF{##1} + {\edef\snk@angle{\fpeval{-1*##4}}} + {\edef\snk@angle{\fpeval{1*##4}}} + \edef\snk@anglesign{\fpeval{sign(\snk@angle)}} + \ifnumgreater{\snk@anglesign}{-1}{ + \sankeyset{##2} + \edef\name{##3} + \edef\snk@oldname{##3-old} + \sankeynodealias{\name}{\snk@oldname} + \edef\qty{\sankeygetnodeqty{\name}} + \edef\orient{\snk@normalize@angle{\sankeygetnodeorient{\name}-\snk@angle}} + \snk@getpos\snk@c{$(\name.right)!-\snk@minradius!(\name.left)$} + \snk@getpos\pos{$(\snk@c)!1!-\snk@angle:(\name.center)$} + \snk@makenode{} + % fill the region + \path[/sankey/fill] let + \p1=(\snk@oldname.left),\p2=(\snk@oldname.right), + \p3=(\name.left),\p4=(\name.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, + \n{minr}={\snk@minradius} + in + (\p1) arc(\orient+\snk@angle+90:\orient+90:\n{maxr}) -- (\p3) -- + (\p4) arc(\orient+90:\orient+\snk@angle+90:\n{minr}) -- (\p2) -- cycle; + % draw left and right borders + \path[/sankey/draw] let + \p1=(\snk@oldname.left),\p2=(\snk@oldname.right), + \p3=(\name.left),\p4=(\name.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, + \n{minr}={\snk@minradius} + in + (\p1) arc(\orient+\snk@angle+90:\orient+90:\n{maxr}) + (\p4) arc(\orient+90:\orient+\snk@angle+90:\n{minr}); + \snk@show@debug{\name} }{ - % 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} - }; - } + \sankeyturnrightbackward[##2]{##3}{-1*\snk@angle} } \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} - }; + \NewDocumentCommand\sankeyturnrightbackward{sO{}mm}{ + % *(reverse), options, name, angle + \snk@errorifnotdefined{##3} + \begingroup + \IfBooleanTF{##1} + {\edef\snk@angle{\fpeval{-1*##4}}} + {\edef\snk@angle{\fpeval{1*##4}}} + \edef\snk@anglesign{\fpeval{sign(\snk@angle)}} + \ifnumgreater{\snk@anglesign}{-1}{ + \sankeyset{##2} + \edef\name{##3} + \edef\snk@oldname{##3-old} + \sankeynodealias{\name}{\snk@oldname} + \edef\qty{\sankeygetnodeqty{\name}} + \edef\orient{\snk@normalize@angle{\sankeygetnodeorient{\name}+\snk@angle}} + \snk@getpos\snk@c{$(\name.right)!-\snk@minradius!(\name.left)$} + \snk@getpos\pos{$(\snk@c)!1!\snk@angle:(\name.center)$} + \snk@makenode{} + % fill the region + \path[/sankey/fill] let + \p1=(\name.left),\p2=(\name.right), + \p3=(\snk@oldname.left),\p4=(\snk@oldname.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius} + in + (\p1) arc(\orient+90:\orient-\snk@angle+90:\n{maxr}) -- (\p3) -- + (\p4) arc(\orient-\snk@angle+90:\orient+90:\n{minr}) -- (\p2) -- cycle; + % draw left and right borders + \path[/sankey/draw] let + \p1=(\name.left),\p2=(\name.right), + \p3=(\snk@oldname.left),\p4=(\snk@oldname.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius} + in + (\p1) arc(\orient+90:\orient-\snk@angle+90:\n{maxr}) + (\p4) arc(\orient-\snk@angle+90:\orient+90:\n{minr}); + \snk@show@debug{\name} + }{ + \sankeyturnright[##2]{##3}{-1*\snk@angle} } - \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} + \endgroup + } + \NewDocumentCommand\sankeyturnleft{sO{}mm}{ + % *(reverse), options, name, angle + \snk@errorifnotdefined{##3} + \begingroup + \IfBooleanTF{##1} + {\edef\snk@angle{\fpeval{-1*##4}}} + {\edef\snk@angle{\fpeval{1*##4}}} + \edef\snk@anglesign{\fpeval{sign(\snk@angle)}} + \ifnumgreater{\snk@anglesign}{-1}{ + \sankeyset{##2} + \edef\name{##3} + \edef\snk@oldname{##3-old} + \sankeynodealias{\name}{\snk@oldname} + \edef\qty{\sankeygetnodeqty{\name}} + \edef\orient{\snk@normalize@angle{\sankeygetnodeorient{\name}+\snk@angle}} + \snk@getpos\snk@c{$(\name.left)!-\snk@minradius!(\name.right)$} + \snk@getpos\pos{$(\snk@c)!1!\snk@angle:(\name.center)$} + \snk@makenode{} + % fill the region + \path[/sankey/fill] let + \p1=(\snk@oldname.left),\p2=(\snk@oldname.right), + \p3=(\name.left),\p4=(\name.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius} + in + (\p1) arc(\orient-\snk@angle-90:\orient-90:\n{minr}) -- (\p3) -- + (\p4) arc(\orient-90:\orient-\snk@angle-90:\n{maxr}) -- (\p2) -- cycle; + % draw left and right borders + \path[/sankey/draw] let + \p1=(\snk@oldname.left),\p2=(\snk@oldname.right), + \p3=(\name.left),\p4=(\name.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius} + in + (\p1) arc(\orient-\snk@angle-90:\orient-90:\n{minr}) + (\p4) arc(\orient-90:\orient-\snk@angle-90:\n{maxr}); + \snk@show@debug{\name} + }{ + \sankeyturnleftbackward[##2]{##3}{-1*\snk@angle} } + \endgroup } - - \def\sankeyqtytolen##1{\fpeval{(##1)/\sankeytotalqty*\sankeytotallen}} - + \NewDocumentCommand\sankeyturnleftbackward{sO{}mm}{ + % *(reverse), options, name, angle + \snk@errorifnotdefined{##3} + \begingroup + \IfBooleanTF{##1} + {\edef\snk@angle{\fpeval{-1*##4}}} + {\edef\snk@angle{\fpeval{1*##4}}} + \edef\snk@anglesign{\fpeval{sign(\snk@angle)}} + \ifnumgreater{\snk@anglesign}{-1}{ + \sankeyset{##2} + \edef\name{##3} + \edef\snk@oldname{##3-old} + \sankeynodealias{\name}{\snk@oldname} + \edef\qty{\sankeygetnodeqty{\name}} + \edef\orient{\snk@normalize@angle{\sankeygetnodeorient{\name}-\snk@angle}} + \snk@getpos\snk@c{$(\name.left)!-\snk@minradius!(\name.right)$} + \snk@getpos\pos{$(\snk@c)!1!-\snk@angle:(\name.center)$} + \snk@makenode{} + % fill the region + \path[/sankey/fill] let + \p1=(\name.left),\p2=(\name.right), + \p3=(\snk@oldname.left),\p4=(\snk@oldname.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius} + in + (\p1) arc(\orient-90:\orient+\snk@angle-90:\n{minr}) -- (\p3) -- + (\p4) arc(\orient+\snk@angle-90:\orient-90:\n{maxr}) -- (\p2) -- cycle; + % draw left and right borders + \path[/sankey/draw] let + \p1=(\name.left),\p2=(\name.right), + \p3=(\snk@oldname.left),\p4=(\snk@oldname.right), + \n1={\sankeyqtytolen{\qty}}, + \n{maxr}={\snk@minradius+\n1}, \n{minr}={\snk@minradius} + in + (\p1) arc(\orient-90:\orient+\snk@angle-90:\n{minr}) + (\p4) arc(\orient+\snk@angle-90:\orient-90:\n{maxr}); + \snk@show@debug{\name} + }{ + \sankeyturnleft[##2]{##3}{-1*\snk@angle} + } + \endgroup + } + \NewDocumentCommand\sankeyturn{sO{}mm}{% + % *(reverse), options, name, angle + \snk@errorifnotdefined{##3} + \begingroup + \edef\snk@anglesign{\fpeval{sign(##4)}} + \IfBooleanTF{##1}{ + \ifnumgreater{\snk@anglesign}{-1} + {\sankeyturnleftbackward[##2]{##3}{##4}} + {\sankeyturnrightbackward[##2]{##3}{-1*##4}} + }{ + \ifnumgreater{\snk@anglesign}{-1} + {\sankeyturnleft[##2]{##3}{##4}} + {\sankeyturnright[##2]{##3}{-1*##4}} + } + \endgroup + } + \NewDocumentCommand\sankeyfork{O{}mm}{%options, name, list of forks + \snk@errorifnotdefined{##2} + \begingroup + \sankeyset{##1} + \sankeynode[debug=false]{as={##2},forked={##3}} + \foreach \qty/\snk@subnodename in {##3}{\sankeynode{as={\snk@subnodename}}} + \endgroup + } + \def\sankeyqtytolen##1{\fpeval{(##1)/\snk@totalqty*\snk@totallen}} \sankeyset{ - % % default values, - % /tikz/declare function={ - % % sankeyqtytolen(\qty)=\qty/\sankeytotalqty*\sankeytotallen; - % % sankeylentoqty(\len)=\len/\sankeytotallen*\sankeytotalqty; - % },% - default parameters,% + @initial options, + every diagram, % user values #1} - - %\typeout{sankeytotallen: \sankeytotallen} - - #2 % body of sankeydiagram environment } - - +{} % empty but mandatory ! :-) \sankeyset{ - % none style new start style={none}{}{}, new end style={none}{}{}, - % simple style +} +\sankeyset{ new start style={simple}{ - (\name.left) -- ([xshift=-.5\pgflinewidth]\name.left) -- ([xshift=-.5\pgflinewidth]\name.right) -- (\name.right) -- cycle + (\name.left) -- ([xshift=-.5\pgflinewidth]\name.left) + -- ([xshift=-.5\pgflinewidth]\name.right) -- (\name.right) -- cycle }{ - (\name.left) -- ([xshift=-.5\pgflinewidth]\name.left) -- ([xshift=-.5\pgflinewidth]\name.right) -- (\name.right) + (\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) -- cycle }{ - (\name.left) -- ([xshift=2mm]\name.center) -- (\name.right) + (\name.left) -- ([xshift=2mm]\name.center) -- (\name.right) }, - % arrow style +} +\sankeyset{ new start style={arrow}{ - (\name.left) -- ++(-10pt,0) - -- ([xshift=-10pt/6]\name.center) - -- ([xshift=-10pt]\name.right) - -- (\name.right) -- cycle + (\name.left) -- ++(-10pt,0) -- ([xshift=-10pt/6]\name.center) + -- ([xshift=-10pt]\name.right) -- (\name.right) -- cycle }{ - (\name.left) -- ++(-10pt,0) - -- ([xshift=-10pt/6]\name.center) - -- ([xshift=-10pt]\name.right) - -- (\name.right) + (\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 + -- ([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) + -- ([xshift=10pt]\name.center) -- ([yshift=-1mm]\name.right) + -- (\name.right) }, -}
\ No newline at end of file +} +\endinput +%% +%% End of file `sankey.sty'. diff --git a/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex b/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex index da1dc120dca..291bcd771fe 100644 --- a/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex +++ b/Master/texmf-dist/tex/latex/sankey/tikzlibrarydubins.code.tex @@ -1,15 +1,40 @@ -% 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. +%% +%% This is file `tikzlibrarydubins.code.tex', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% sankey.dtx (with options: `tikzlibrarydubins.code.tex') +%% +%% This is a generated file. +%% +%% Copyright (C) 2016, 2021 by Paul Gaborit +%% +%% This work may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License, either version 1.3 of this license or (at +%% your option) any later version. The latest version of this license is +%% in +%% +%% <http://www.latex-project.org/lppl.txt> +%% +%% and version 1.3 or later is part of all distributions of LaTeX version +%% 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status “maintained”. +%% +%% The Current Maintainer of this work is Paul Gaborit. +%% +%% This work consists of the files sankey.dtx, sankey.ins and the derived +%% files sankey.sty, tikzlibrarydubins.code.tex, sankey-doc-preamble.sty, +%% sankey-example1.tex, sankey-example2.tex, sankey-example3.tex, +%% sankey-example3-variation.tex, sankey-example4.tex, +%% sankey-example-energy.tex +%% +\def\tikzlibrarydubins@version{v3.0} +\def\tikzlibrarydubins@date{2021/03/14} \usetikzlibrary{calc} - \RequirePackage{etoolbox} -\RequirePackage{etextools} \RequirePackage{xfp} \newbool{dubinspathreverse} @@ -19,29 +44,28 @@ \ifnumequal{\pgfmathresult}{1}% } -\def\anglebetween#1#2#3{%macro, s, t - \path let - \p{s}=(#2), \p{t}=(#3), - \n{angle}={atan2(\y{t}-\y{s},\x{t}-\x{s})} - in \pgfextra { - \pgfmathsetmacro#1{\n{angle}} - \aftergroup@def#1 - }; +\def\dbp@getxy#1#2#3{% + \tikz@scan@one@point\pgfutil@firstofone(#3)\relax% + \edef#1{\the\pgf@x}% + \edef#2{\the\pgf@y}% } -\def\distancebetween#1#2#3{%macro, s, t - \path let - \p{s}=(#2), \p{t}=(#3), - %\n{dist}={veclen(\x{t}-\x{s},\y{t}-\y{s}))} - \n{dist}={\fpeval{sqrt((\x{t}-\x{s})*(\x{t}-\x{s})+(\y{t}-\y{s})*(\y{t}-\y{s}))}} - in \pgfextra { - %\typeout{n{dist}:\n{dist}} - \pgfmathsetmacro#1{\n{dist}} - \aftergroup@def#1 - }; +\def\dbp@anglebetween#1#2#3{%macro, s, t + \dbp@getxy\dbp@ax\dbp@ay{#2} + \dbp@getxy\dbp@bx\dbp@by{#3} + \pgfmathsetmacro#1{atan2(\dbp@by-\dbp@ay,\dbp@bx-\dbp@ax)} } -\newcommand\dubinspath@rsr{% s, sa, t, ta, as, len, at, r +\def\dbp@distancebetween#1#2#3{%macro, s, t + \dbp@getxy\dbp@ax\dbp@ay{#2} + \dbp@getxy\dbp@bx\dbp@by{#3} + \edef#1{\fpeval{sqrt(% + (\dbp@bx-\dbp@ax)*(\dbp@bx-\dbp@ax)% + +(\dbp@by-\dbp@ay)*(\dbp@by-\dbp@ay)% + )}}% +} + +\newcommand\dbp@rsr{% s, sa, t, ta, as, len, at, r let \p{tr}=([shift={(\dbp@angb-90:\dbp@radius pt)}]\dbp@b), \n1={\dbp@anga+90}, @@ -53,7 +77,7 @@ arc(\n3:\n2:\dbp@rradius pt) } -\newcommand\dubinspath@lsl{% s, sa, t, ta, as, len, at, r +\newcommand\dbp@lsl{% s, sa, t, ta, as, len, at, r let \p{tl}=([shift={(\dbp@angb+90:\dbp@radius pt)}]\dbp@b), \n1={\dbp@anga-90},\n2={\n1+\dbp@firstangle}, @@ -64,7 +88,7 @@ arc(\n4:\n3:\dbp@lradius pt) } -\newcommand\dubinspath@rsl{% s, sa, t, ta, as, len, at, r +\newcommand\dbp@rsl{% s, sa, t, ta, as, len, at, r let \p{tl}=([shift={(\dbp@angb+90:\dbp@radius pt)}]\dbp@b), \n1={\dbp@anga+90},\n2={\n1-\dbp@firstangle}, @@ -75,7 +99,7 @@ arc(\n4:\n3:\dbp@lradius pt) } -\newcommand\dubinspath@lsr{% s, sa, t, ta, as, len, at, r +\newcommand\dbp@lsr{% s, sa, t, ta, as, len, at, r let \p{tr}=([shift={(\dbp@angb-90:\dbp@radius pt)}]\dbp@b), \n1={\dbp@anga-90},\n2={\n1+\dbp@firstangle}, @@ -86,7 +110,7 @@ arc(\n4:\n3:\dbp@rradius pt) } -\newcommand\dubinspath@lrl{% s, sa, t, ta, as, ai, at, r +\newcommand\dbp@lrl{% s, sa, t, ta, as, ai, at, r let \n1={\dbp@anga-90},\n2={\n1+\dbp@firstangle}, \n3={\dbp@angb-90},\n4={\n3-\dbp@lastangle} @@ -96,7 +120,7 @@ arc(\n4:\n3:\dbp@lradius pt) } -\newcommand\dubinspath@rlr{% s, sa, t, ta, as, ai, at, r +\newcommand\dbp@rlr{% s, sa, t, ta, as, ai, at, r let \n1={\dbp@anga+90},\n2={\n1-\dbp@firstangle}, \n3={\dbp@angb+90},\n4={\n3+\dbp@lastangle} @@ -105,77 +129,68 @@ arc(\n2+180:\n2+180+\dbp@midparam:\dbp@lradius pt) arc(\n4:\n3:\dbp@rradius pt) } -\newcommand\dubinspath@rev@lsl{\dubinspath@rsr} -\newcommand\dubinspath@rev@rsr{\dubinspath@lsl} -\newcommand\dubinspath@rev@lsr{\dubinspath@lsr} -\newcommand\dubinspath@rev@rsl{\dubinspath@rsl} -\newcommand\dubinspath@rev@lrl{\dubinspath@rlr} -\newcommand\dubinspath@rev@rlr{\dubinspath@lrl} - +\newcommand\dbp@rev@lsl{\dbp@rsr} +\newcommand\dbp@rev@rsr{\dbp@lsl} +\newcommand\dbp@rev@lsr{\dbp@lsr} +\newcommand\dbp@rev@rsl{\dbp@rsl} +\newcommand\dbp@rev@lrl{\dbp@rlr} +\newcommand\dbp@rev@rlr{\dbp@lrl} \newcommand\dubinspath[1]{% \pgfextra{ \dubinspathset{#1} \ifbool{dubinspathreverse}{ - \edef\newa{\dbp@b} - \edef\newb{\dbp@a} - \pgfmathsetmacro\newanga{180+\dbp@angb} - \pgfmathsetmacro\newangb{180+\dbp@anga} - \edef\newfirstangle{\dbp@lastangle} - \edef\newlastangle{\dbp@firstangle} - \edef\newmethod{rev@\dbp@method} - \edef\newlradius{\dbp@rradius} - \edef\newrradius{\dbp@lradius} + \edef\dbp@newa{\dbp@b} + \edef\dbp@newb{\dbp@a} + \pgfmathsetmacro\dbp@newanga{180+\dbp@angb} + \pgfmathsetmacro\dbp@newangb{180+\dbp@anga} + \edef\dbp@newfirstangle{\dbp@lastangle} + \edef\dbp@newlastangle{\dbp@firstangle} + \edef\dbp@newmethod{rev@\dbp@method} + \edef\dbp@newlradius{\dbp@rradius} + \edef\dbp@newrradius{\dbp@lradius} \dubinspathset{ - start point=\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, + start point=\dbp@newa, + end point=\dbp@newb, + start angle=\dbp@newanga, + end angle=\dbp@newangb, + first angle=\dbp@newfirstangle, + last angle=\dbp@newlastangle, + left and right minimum radii=\dbp@newlradius pt and \dbp@newrradius pt, + method=\dbp@newmethod, } }{} - %\typeout{dbp@lradius:\dbp@lradius} - %\typeout{dbp@rradius:\dbp@rradius} } - \csname dubinspath@\dbp@method\endcsname% + \csname dbp@\dbp@method\endcsname% } +%% solution -% solution -% \xdef\dubinspathmethod{} % type of dubins path -% \xdef\dubinspathlength{} % lenght (pt) -% \xdef\dubinspathfirstangle{} % first angle -% \xdef\dubinspathmiddleparam{} % intermediate angle or straight distance -% \xdef\dubinspathlastangle{} % last angle - -\def\dubinspathstore#1#2{% - \expandafter\xdef\csname dubinspath@store@#1@#2\endcsname% - {\csname dubinspath#2\endcsname}% +\def\dbp@store#1#2{% + \expandafter\xdef\csname dbp@store@#1@#2\endcsname% + {\csname dbp@#2\endcsname}% } -\def\dubinspathget#1#2{% - \csname dubinspath@store@#1@#2\endcsname% +\def\dbp@get#1#2{% + \csname dbp@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} +\def\dbp@setparams#1#2#3#4#5{% + % method, length, fisrt angle, middle param, last angle + \edef\dbp@method{#1} + \edef\dbp@length{#2} + \edef\dbp@firstangle{#3} + \edef\dbp@middleparam{#4} + \edef\dbp@lastangle{#5} \ifdef{\dbp@storename}{ \foreach \p in {method,length,firstangle,middleparam,lastangle}{ - \dubinspathstore{\dbp@storename}{\p} + \dbp@store{\dbp@storename}{\p} } }{} } -\def\dubinspathupdateparams#1#2#3#4#5{ - \ifpgfmathcond{#2<\dubinspathlength}{ - \dubinspathsetparams{#1}{#2}{#3}{#4}{#5} +\def\dbp@updateparams#1#2#3#4#5{ + \ifpgfmathcond{#2<\dbp@length}{ + \dbp@setparams{#1}{#2}{#3}{#4}{#5} }{} } @@ -188,10 +203,10 @@ end angle/.store in=\dbp@angb, store/.store in=\dbp@storename, use store/.style={ - method=\dubinspathget{#1}{method}, - first angle=\dubinspathget{#1}{firstangle}, - last angle=\dubinspathget{#1}{lastangle}, - middle param=\dubinspathget{#1}{middleparam}, + method=\dbp@get{#1}{method}, + first angle=\dbp@get{#1}{firstangle}, + last angle=\dbp@get{#1}{lastangle}, + middle param=\dbp@get{#1}{middleparam}, }, minimum radius/.code={ \pgfmathsetmacro\dbp@radius{#1} @@ -217,145 +232,155 @@ \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) + angtodist(\dbp@a,\dbp@r)={abs(\dbp@a)*.01745329*\dbp@r}; + modangr(\dbp@a,\dbp@b)={ + ( + Mod(\dbp@a,360)<Mod(\dbp@b,360) + ? + Mod(\dbp@a,360) + : + Mod(\dbp@a,360)-360)+\dbp@b-Mod(\dbp@b,360 + ) }; - modangl(\a,\b)={ - (Mod(\a,360)<Mod(\b,360)?Mod(\a,360)+360:Mod(\a,360))+(\b)-Mod(\b,360) + modangl(\dbp@a,\dbp@b)={ + ( + Mod(\dbp@a,360)<Mod(\dbp@b,360) + ? + Mod(\dbp@a,360)+360 + : + Mod(\dbp@a,360))+(\dbp@b)-Mod(\dbp@b,360) }; }, } - - \pgfmathsetmacro\radius{\dbp@rradius} - \pgfmathsetmacro\anga{mod((\dbp@anga)+180,360)-180} - \pgfmathsetmacro\angb{mod((\dbp@angb)+180,360)-180} - %\typeout{radius:\radius,anga:\anga,angb:\angb} + + \pgfmathsetmacro\dbp@radius{\dbp@rradius} + \pgfmathsetmacro\dbp@anga{mod((\dbp@anga)+180,360)-180} + \pgfmathsetmacro\dbp@angb{mod((\dbp@angb)+180,360)-180} \path let \p{a}=(\dbp@a), \p{b}=(\dbp@b), - \p{ar}=($(\p{a}) + (\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)$) + \p{ar}=($(\p{a}) + (\dbp@anga-90:\dbp@radius pt)$), + \p{al}=($(\p{a}) + (\dbp@anga+90:\dbp@radius pt)$), + \p{br}=($(\p{b}) + (\dbp@angb-90:\dbp@radius pt)$), + \p{bl}=($(\p{b}) + (\dbp@angb+90:\dbp@radius pt)$) in \pgfextra{ \pgfinterruptpath - % RSR (ar 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) + % RSR (ar and br) + \dbp@anglebetween\dbp@rsrarbr{\p{ar}}{\p{br}} + \dbp@distancebetween\dbp@rsrdarbr{\p{ar}}{\p{br}} + \pgfmathsetmacro\dbp@rsrangone{Mod(\dbp@anga-\dbp@rsrarbr,360)} + \pgfmathsetmacro\dbp@rsrangtwo{Mod(\dbp@rsrarbr-\dbp@angb,360)} + \pgfmathsetmacro\dbp@rsrlen{\dbp@rsrdarbr} + \pgfmathsetmacro\dbp@rsrdist{ + angtodist(\dbp@rsrangone,\dbp@radius) + +\dbp@rsrlen + +angtodist(\dbp@rsrangtwo,\dbp@radius) } - \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) + \dbp@setparams{rsr}{\dbp@rsrdist}{\dbp@rsrangone}{\dbp@rsrlen}{\dbp@rsrangtwo} + + % LSL (al and bl) + \dbp@anglebetween\dbp@lslalbl{\p{al}}{\p{bl}} + \dbp@distancebetween\dbp@lsldalbl{\p{al}}{\p{bl}} + \pgfmathsetmacro{\dbp@lslangone}{mod(\dbp@lslalbl-\dbp@anga+720,360)} + \pgfmathsetmacro{\dbp@lslangtwo}{mod(\dbp@angb-\dbp@lslalbl+720,360)} + \pgfmathsetmacro\dbp@lsllen{\dbp@lsldalbl} + \pgfmathsetmacro\dbp@lsldist{ + angtodist(\dbp@lslangone,\dbp@radius) + +\dbp@lsllen + +angtodist(\dbp@lslangtwo,\dbp@radius) } - \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) + \dbp@updateparams% + {lsl}{\dbp@lsldist}{\dbp@lslangone}{\dbp@lsllen}{\dbp@lslangtwo} + + % RSL (ar and bl) + \dbp@distancebetween\dbp@rsldarbl{\p{ar}}{\p{bl}} + \pgfmathtruncatemacro\dbp@rslok{(\dbp@rsldarbl>=2*\dbp@radius)?1:0} + \ifnumequal{\dbp@rslok}{1}{ + \dbp@anglebetween\dbp@rslarbl{\p{ar}}{\p{bl}} + \pgfmathsetmacro\dbp@rslanglesup{ + asin(\dbp@radius/\dbp@rsldarbl*2)} + \pgfmathsetmacro\dbp@rslangone + {Mod(\dbp@anga-\dbp@rslarbl+\dbp@rslanglesup,360)} + \pgfmathsetmacro\dbp@rslangtwo + {Mod(\dbp@angb-\dbp@rslarbl+\dbp@rslanglesup,360)} + \pgfmathsetmacro\dbp@rsllen{veclen(\dbp@rsldarbl,\dbp@radius)} + \pgfmathsetmacro\dbp@rsldist{ + angtodist(\dbp@rslangone,\dbp@radius) + +\dbp@rsllen + +angtodist(\dbp@rslangtwo,\dbp@radius) } - \dubinspathupdateparams{rsl}{\rsldist}{\rslangone}{\rsllen}{\rslangtwo} + \dbp@updateparams% + {rsl}{\dbp@rsldist}{\dbp@rslangone}{\dbp@rsllen}{\dbp@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) + % LSR (al and br) + \dbp@distancebetween\dbp@lsrdalbr{\p{al}}{\p{br}} + \pgfmathtruncatemacro\dbp@lsrok{(\dbp@lsrdalbr>=2*\dbp@radius)?1:0} + \ifnumequal{\dbp@lsrok}{1}{ + \dbp@anglebetween\dbp@lsralbr{\p{al}}{\p{br}} + \pgfmathsetmacro\dbp@lsranglesup{ + asin(\dbp@radius/\dbp@lsrdalbr*2)} + \pgfmathsetmacro\dbp@lsrangone + {Mod(\dbp@lsralbr+\dbp@lsranglesup-\dbp@anga,360)} + \pgfmathsetmacro\dbp@lsrangtwo + {Mod(\dbp@lsralbr+\dbp@lsranglesup-\dbp@angb,360)} + \pgfmathsetmacro\dbp@lsrlen{veclen(\dbp@lsrdalbr,\dbp@radius)} + \pgfmathsetmacro\dbp@lsrdist{ + angtodist(\dbp@lsrangone,\dbp@radius) + +\dbp@lsrlen + +angtodist(\dbp@lsrangtwo,\dbp@radius) } - \dubinspathupdateparams{lsr}{\lsrdist}{\lsrangone}{\lsrlen}{\lsrangtwo} + \dbp@updateparams% + {lsr}{\dbp@lsrdist}{\dbp@lsrangone}{\dbp@lsrlen}{\dbp@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) + + % LRL (al and bl) + \dbp@distancebetween\dbp@lrldalbl{\p{al}}{\p{bl}} + \pgfmathtruncatemacro\dbp@lrlok{(\dbp@lrldalbl<=4*\dbp@radius)?1:0} + \ifnumequal{\dbp@lrlok}{1}{ + \dbp@anglebetween\dbp@lrlalbl{\p{al}}{\p{bl}} + \pgfmathsetmacro\dbp@lrlangsup{acos(\dbp@lrldalbl/\dbp@radius/4)} + \pgfmathsetmacro\dbp@lrlangone{ + modangl(\dbp@lrlalbl+\dbp@lrlangsup,\dbp@anga-90)-(\dbp@anga-90)} + \pgfmathsetmacro\dbp@lrlangtwo{% + (\dbp@angb-90)-modangr(\dbp@lrlalbl+180-\dbp@lrlangsup,\dbp@angb-90)} + \pgfmathsetmacro\dbp@lrlangthree{360-2*(90-\dbp@lrlangsup)} + \pgfmathsetmacro\dbp@lrldist{ + angtodist(\dbp@lrlangone,\dbp@radius) + +angtodist(\dbp@lrlangthree,\dbp@radius) + +angtodist(\dbp@lrlangtwo,\dbp@radius) } - \dubinspathupdateparams{lrl}{\lrldist}{\lrlangone}{\lrlangthree}{\lrlangtwo} + \dbp@updateparams% + {lrl}{\dbp@lrldist}{\dbp@lrlangone}{\dbp@lrlangthree}{\dbp@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) + % RLR (ar and br) + \dbp@distancebetween\dbp@rlrdarbr{\p{ar}}{\p{br}} + \pgfmathtruncatemacro\dbp@rlrok{(\dbp@rlrdarbr<=4*\dbp@radius)?1:0} + \ifnumequal{\dbp@rlrok}{1}{ + \dbp@anglebetween\dbp@rlrarbr{\p{ar}}{\p{br}} + \pgfmathsetmacro\dbp@rlrangsup{acos(\dbp@rlrdarbr/\dbp@radius/4)} + \pgfmathsetmacro\dbp@rlrangone{ + (\dbp@anga+90)-modangr(\dbp@rlrarbr-\dbp@rlrangsup,\dbp@anga+90)} + \pgfmathsetmacro\dbp@rlrangtwo{% + modangl(\dbp@rlrarbr+180+\dbp@rlrangsup,\dbp@angb+90)-(\dbp@angb+90)} + \pgfmathsetmacro\dbp@rlrangthree{360-2*(90-\dbp@rlrangsup)} + \pgfmathsetmacro\dbp@rlrdist{ + angtodist(\dbp@rlrangone,\dbp@radius) + +angtodist(\dbp@rlrangthree,\dbp@radius) + +angtodist(\dbp@rlrangtwo,\dbp@radius) } - \dubinspathupdateparams{rlr}{\rlrdist}{\rlrangone}{\rlrangthree}{\rlrangtwo} + \dbp@updateparams% + {rlr}{\dbp@rlrdist}{\dbp@rlrangone}{\dbp@rlrangthree}{\dbp@rlrangtwo} }{} \endpgfinterruptpath }; \endgroup } - -%%% Local Variables: -%%% mode: latex -%%% TeX-master: t -%%% End: +\endinput +%% +%% End of file `tikzlibrarydubins.code.tex'. |