From 787b1d312f205766480ce986a9f98548cc396dae Mon Sep 17 00:00:00 2001
From: Karl Berry <karl@freefriends.org>
Date: Mon, 19 Jun 2017 21:07:40 +0000
Subject: spectralsequences (19jun17)

git-svn-id: svn://tug.org/texlive/trunk@44639 c570f23f-e606-0410-a88d-b1316a301751
---
 .../latex/spectralsequences/sseqdrawing.code.tex   | 990 +++++++++++++++++++++
 1 file changed, 990 insertions(+)
 create mode 100644 Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex

(limited to 'Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex')

diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex
new file mode 100644
index 00000000000..098e73f9110
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex
@@ -0,0 +1,990 @@
+%%
+%% Package: spectralsequences.sty version 1.0
+%% Author: Hood Chatham
+%% Email: hood@mit.edu
+%% Date: 2017-06-18
+%% License: Latex Project Public License
+%%
+%% File: sseqdrawing.code.tex
+%%
+%%    Defines the macros that draw the features of the spectral sequence (at least, those that aren't drawn by tikz).
+%%    Everything here has to be super optimized, because like 90% of the execution time is in these functions.
+%%    In particular, tikz is a horrible performance hole that must be avoided at all costs. For example, the code
+%%    the code to produce the axis ticks used to use the tikz \node command, and in the file example_KF3n.tex drawing
+%%    the axes ticks was taking about 1/3 of the compile time (a little under 1s out of a 3.2)
+%%
+
+
+
+%%%
+%%% Draw axes and clip
+%%%
+\def\sseq@handlexaxis{
+    \ifsseq@drawxaxis
+        \bgroup
+        \ifsseq@borderxaxis\else
+            \let\sseq@ymin\sseq@yaxisorigin % Warning: this is a stupid, lazy hack.
+        \fi
+        \sseq@drawxaxis
+        \ifsseq@drawxaxisticks
+            \sseq@drawxticks
+        \fi
+        \egroup
+    \fi
+}
+\def\sseq@handleyaxis{
+    \ifsseq@drawyaxis
+        \bgroup
+        \ifsseq@borderyaxis\else
+            \let\sseq@xmin\sseq@xaxisorigin % Warning: this is a stupid, lazy hack.
+        \fi
+        \sseq@drawyaxis
+        \ifsseq@drawyaxisticks
+            \sseq@drawyticks
+        \fi
+        \egroup
+    \fi
+}
+\def\sseq@drawxaxis{
+    \bgroup
+    \pgftransformreset
+    \sseq@globaldetonetransform
+    %
+    \bgroup
+    \pgftransformxshift{\sseq@xaxis@end@extend}\pgftransformyshift{-\sseq@xaxisgap}
+    \sseq@globalscaletransform
+    \pgfpathmoveto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}}
+    \egroup
+    \bgroup
+    \pgftransformxshift{-\sseq@yaxisgap}
+    %\pgftransformxshift{-\sseq@ylabelgap}
+    \pgftransformxshift{-\sseq@xaxis@start@extend}
+    \pgftransformyshift{-\sseq@xaxisgap}
+    \sseq@globalscaletransform
+    \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
+    \egroup
+    \egroup
+    \pgfusepath{stroke}
+}
+\def\sseq@drawyaxis{
+    \bgroup
+    \pgftransformreset
+    \sseq@globaldetonetransform
+    \bgroup
+    \pgftransformyshift{\sseq@yaxis@end@extend}\pgftransformxshift{-\sseq@yaxisgap}
+    \sseq@globalscaletransform
+    \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}}
+    \egroup
+    \bgroup
+    \pgftransformyshift{-\sseq@xaxisgap}
+    %\pgftransformyshift{-\sseq@xlabelgap}
+    \pgftransformyshift{-\sseq@yaxis@start@extend}
+    \pgftransformxshift{-\sseq@yaxisgap}
+    \sseq@globalscaletransform
+    \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
+    \egroup
+    \egroup
+    \pgfusepath{stroke}%
+}
+\def\sseq@drawxticks{
+    \sseq@tempy=\sseq@ymin\relax
+    \sseq@tempx=\sseq@xmax\relax
+    \advance\sseq@tempx\@ne\relax
+    \edef\sseq@temp{\the\sseq@tempx}%
+    \sseq@tempx=\sseq@xmin\relax
+    \loop
+        \bgroup
+        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}
+        \pgftransformresetnontranslations
+        \sseq@globaldetonetransform
+        \pgftransformyshift{-\sseq@xlabelgap}\pgftransformyshift{-\sseq@xaxisgap}
+        \pgftransformresetnontranslations
+        \ifsseq@rotatelabels\sseq@globalrotatetransform\fi
+        \sseq@xtickstyle
+        \tikz@options
+        \pgftext{\hbox{$\sseq@xtickfn{\the\sseq@tempx}$}}
+        \egroup
+        \advance\sseq@tempx\sseq@xtickstep\relax
+    \ifnum\sseq@tempx<\sseq@temp\repeat
+}
+\def\sseq@drawyticks{
+    \sseq@tempx=\sseq@xmin\relax
+    \sseq@tempy=\sseq@ymax\relax
+    \advance\sseq@tempy\@ne\relax
+    \edef\sseq@tempmax{\the\sseq@tempy}
+    \sseq@tempy=\sseq@ymin\relax
+    \loop
+        \bgroup
+        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}
+        \pgftransformresetnontranslations
+        \sseq@globaldetonetransform
+        \pgftransformxshift{-\sseq@ylabelgap}\pgftransformxshift{-\sseq@yaxisgap}
+        \pgftransformresetnontranslations
+        \ifsseq@rotatelabels\sseq@globalrotatetransform\fi
+        \sseq@ytickstyle
+        \tikz@options
+        \pgftext{\hbox{$\sseq@ytickfn{\the\sseq@tempy}$}}
+        \egroup
+        \advance\sseq@tempy\sseq@ytickstep\relax
+    \ifnum\sseq@tempy<\sseq@tempmax\repeat
+}
+\def\sseq@setupclip{
+    %\clip(\sseq@xmin-0.4,\sseq@ymin-0.4) rectangle (\sseq@xmax+0.5,\sseq@ymax+0.5);%
+    \ifsseq@clip
+        \ifx\sseq@customclip\pgfutil@empty
+            \bgroup
+            \pgftransformreset
+            \sseq@globaldetonetransform
+            \ifsseq@borderyaxis
+                \def\xmin{\pgftransformxshift{-\sseq@yaxisgap}\pgftransformxshift{\sseq@yclip@axisgap}}
+            \else
+                \def\xmin{\pgftransformxshift{-\sseq@xaxis@start@extend}\pgftransformxshift{-\sseq@clip@padding@left}}
+            \fi
+            \ifsseq@borderxaxis
+                \def\ymin{\pgftransformyshift{-\sseq@xaxisgap}\pgftransformyshift{\sseq@xclip@axisgap}}
+            \else
+                \def\ymin{\pgftransformyshift{-\sseq@yaxis@start@extend}\pgftransformyshift{-\sseq@clip@padding@bottom}}
+            \fi
+            \def\xmax{\pgftransformxshift{\sseq@xaxis@end@extend}\pgftransformxshift{\sseq@clip@padding@right}}
+            \def\ymax{\pgftransformyshift{\sseq@yaxis@end@extend}\pgftransformyshift{\sseq@clip@padding@top}}
+            \bgroup
+            \xmin\ymin\sseq@globalscaletransform
+            \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
+            \egroup
+            \bgroup
+            \xmin\ymax\sseq@globalscaletransform
+            \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}}
+            \egroup
+            \bgroup
+            \xmax\ymax\sseq@globalscaletransform
+            \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymax cm}}
+            \egroup
+            \bgroup
+            \xmax\ymin\sseq@globalscaletransform
+            \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}}
+            \egroup
+            \egroup
+            \pgfpathclose
+            \pgfgetpath\sseq@theclippath % This stores the clipping so I can find intersections later
+            \pgfusepath{discard}% This has to be after the egroup or else the clipping gets screwed up
+            \bgroup
+                %\sseq@globalscaletransform
+                \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
+                \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}}
+                \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymax cm}}
+                \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}}
+                \pgfpathclose
+            \egroup
+            \pgfgetpath\sseq@therangepath % Only for deciding whether to draw "tricky edges"
+            \pgfusepath{discard}
+        \else
+            \def\sseq@temp{\path[name path=temp]}
+            \@xptwo\sseq@temp\@xp\@gobble\sseq@customclip
+            \pgfgetpath\sseq@theclippath
+            \let\sseq@theclippath\tikz@intersect@path@name@temp
+        \fi
+    \else
+        \let\sseq@theclippath\relax
+    \fi
+}
+\def\sseq@useclip{\ifx\sseq@theclippath\relax\else\pgfsetpath\sseq@theclippath\pgfusepath{clip}\fi}
+\def\sseq@grid@chess{
+ \bgroup
+ \pgfscope
+ \sseq@useclip
+ \pgflowlevelsynccm
+ \pgfsetlinewidth{1cm}
+ \pgfsetdash{{1cm}{1cm}}{1cm}
+ \pgfsetcolor{lightgray}
+ \pgfpathgrid[stepx=2cm,stepy=2cm]{\pgfpoint{-0.5cm}{-0.5cm}}{\pgfpoint{\sseq@xmax cm+0.499cm}{\sseq@ymax cm+0.499cm}}
+ \pgfusepath{stroke}
+ \endpgfscope
+ \egroup
+}
+\def\sseq@grid@crossword{
+ \bgroup
+ \pgfscope
+ \pgfsetlinewidth{\the\sseq@gridstrokethickness}
+ \sseq@useclip
+ \pgftransformxshift{-0.5cm}
+ \pgftransformyshift{-0.5cm}
+ \pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-1cm}{-1cm}}{\pgfpoint{\xmax cm+0.99cm}{\ymax cm+0.99cm}}
+ \pgfusepath{stroke}
+ \endpgfscope
+ \egroup
+}
+\def\sseq@grid@go{
+ \bgroup
+ \pgfscope
+ \sseq@useclip
+ \pgfsetlinewidth{\the\sseq@gridstrokethickness}
+ \pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-1cm}{-1cm}}{\pgfpoint{\xmax cm+0.5cm}{\ymax cm+0.5cm}}
+ \pgfusepath{stroke}
+ \endpgfscope
+ \egroup
+}
+\def\sseq@grid@none{}
+\def\sseq@grid@dots{
+ \bgroup
+ \pgfscope
+ \pgfgettransform\sseq@savetransform
+ \pgftransformreset
+ \sseq@globalscaletransform
+ \pgfgettransformentries{\sseq@a}{\sseq@b}{\sseq@c}{\sseq@d}{\sseq@u}{\sseq@v}
+ \pgfsettransform\sseq@savetransform
+ \sseq@useclip
+ \pgftransformxshift{-1.5cm}
+ \pgftransformyshift{-0.5cm}
+ \pgfsetdash{{1pt}{\sseq@a*1cm-1pt}}{0.5cm+.5pt}
+ \pgfsetlinewidth{1pt}
+ \sseq@tempy=\sseq@ymin\relax
+ \advance\sseq@tempy\m@ne
+ \loop
+ \advance\sseq@tempy\@ne
+ \pgfpathmoveto{\pgfpoint{\sseq@xmin cm+0.5cm/\sseq@a}{\the\sseq@tempy cm}}
+ \pgfpathlineto{\pgfpoint{\sseq@xmax cm+1.01cm }{\the\sseq@tempy cm}}
+ \ifnum\sseq@tempy<\sseq@ymax\repeat
+ %\pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-0.5cm}{-0.5cm}}{\pgfpoint{\xmax cm-0.5cm}{\ymax cm-0.5cm}}
+ \pgfusepath{stroke}
+ \endpgfscope
+ \egroup
+}
+%%%
+%%% Draw Classes
+%%%
+%%% Class offsets
+\sseqnewclasspattern{standard}{
+    (0,0);
+    (-0.13,0)(0.13,0);
+    (-0.2,0)(0,0)(0.2,0);
+    (-0.13,-0.13)(0.13,-0.13)(-0.13,0.13)(0.13,0.13);
+    (-0.16,-0.16)(0.16,-0.16)(-0.16,0.16)(0.16,0.16)(0,0);
+    (-0.13,-0.2)(-0.13,0)(-0.13,0.2)(0.13,-0.2)(0.13,0)(0.13,0.2);
+}
+\sseqnewclasspattern{linear}{
+    (0,0);
+    (-0.13,0)(0.13,0);
+    (-0.2,0)(0,0)(0.2,0);
+    (-0.3,0)(-0.1,0)(0.1,0)(0.3,0);
+    (-0.4,0)(-0.2,0)(0,0)(0.2,0)(0.4,0);
+    (-0.5,0)(-0.3,0)(-0.1,0)(0.1,0)(0.3,0)(0.5,0);
+}
+\def\sseq@offset#1#2{
+    \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{0\csname sseq@\sseq@classpattern xoffset#1/#2\endcsname cm}{0\csname sseq@\sseq@classpattern yoffset#1/#2\endcsname cm}}}
+}
+\def\sseq@class@getparts#1(#2,#3,#4)[#5].{
+    \sseq@seterrorannotation@drawing{#1}{#2}{#3}{#4}{#5}
+    \def\sseq@thisclassname{class.(#2,#3,#4)}
+    \def\sseq@thisnodename{sseq{#2,#3,#4}}
+    \def\sseq@thispos{(#2,#3)}
+    \def\sseq@thisposnum{#4}
+    \def\sseq@thisclassnum{#5}
+}
+
+\def\sseqtooltip#1#2{%
+    \edef\temp{\detokenize\@xpthree{#2}}%
+    \edef\temp{\@xp\sseqtooltip@replaceslashes\@xp{\temp}}%
+    \sseq@eval{\@nx\pdftooltip{\unexpanded{#1}}{\temp}}%
+}
+\bgroup\lccode`\!=`\\\lowercase{\egroup
+\def\sseqtooltip@replaceslashes#1{\sseqtooltip@replaceslashes@#1!\sseq@nil}
+\def\sseqtooltip@replaceslashes@#1!#2{%
+    #1%
+    \ifx\sseq@nil#2\@xp\@gobble\else
+        \@nx\@nx\@nx\textbackslash
+        \@xp\sseqtooltip@replaceslashes@
+    \fi#2%
+}
+}
+
+% #1 -- the name of the node object
+\def\sseq@class@drawnode#1{%
+    \begingroup
+    \sseq@class@getparts#1.
+    \sseq@tempx=\sseq@obj{\sseq@thisclassname.x}\relax
+    \sseq@tempy=\sseq@obj{\sseq@thisclassname.y}\relax
+    \sseq@needstikzfalse
+    \sseq@options@firstpassmode
+        \sseq@thesseqstyle
+        \sseq@theclassstyle
+        \ifnum\sseq@obj{#1.page}=\sseq@infinitycount
+            \sseq@thepermanentcyclestyle
+        \else
+            \sseq@thetransientcyclestyle
+            \ifsseq@thispage
+                \sseq@thethispagecyclestyle
+            \fi
+        \fi
+        \the\sseq@scope@toks
+        \sseq@obj{#1.needstikz}
+%
+    \sseq@outofrangetrue
+    \ifnum\sseq@tempx<\sseq@xmaxpp\relax\ifnum\sseq@tempx>\sseq@xminmm\relax\ifnum\sseq@tempy<\sseq@ymaxpp\relax\ifnum\sseq@tempy>\sseq@yminmm\relax
+        \sseq@outofrangefalse
+        \pgfscope
+        \let\tikz@options\pgfutil@empty
+        \let\tikz@alias=\pgfutil@empty
+        \def\pgfkeysdefaultpath{/sseqpages/class/}
+        \sseq@options@secondpassmode
+            \sseq@thesseqstyle
+            \sseq@theclassstyle
+            \ifnum\sseq@obj{#1.page}=\sseq@infinitycount
+                \sseq@thepermanentcyclestyle
+            \else
+                \sseq@thetransientcyclestyle
+                \ifsseq@thispage
+                    \sseq@thethispagecyclestyle
+                \fi
+            \fi
+            \the\sseq@scope@toks
+            \sseq@obj{#1.options}%
+        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}
+        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{-\the\sseq@x cm}{-\the\sseq@y cm}}}
+        \iftikz@fullytransformed\pgfgettransform{\savetransform}\fi
+        \pgftransformresetnontranslations
+        \sseq@globalrotatetransform
+        \sseq@classplacementtransform
+        \sseq@obj@ifdef{#1.offset}{\sseq@obj{#1.offset}}{%
+            \sseq@offset{\sseq@thisposnum}{\sseq@obj{partcoord.\sseq@thispos.numnodes}}%
+        }%
+        \iftikz@fullytransformed\pgfsettransform{\savetransform}\else\pgftransformresetnontranslations\ifsseq@rotatelabels\sseq@globalrotatetransform\fi\fi
+        \tikz@options
+        \ifsseq@needstikz
+            \let\sseq@mode\tikz@mode
+            \tikzset{every text node part/.code/.expand once={\sseq@globalrotatetransform\sseq@obj{#1.nodetext.options}}}%
+            \sseq@eval{%
+                \@nx\node[/utils/exec={\let\@nx\tikz@mode\@nx\sseq@mode},
+                    /handlers/first char syntax/the character "/.initial=\@nx\sseq@handlequote
+                ] (\sseq@thisnodename) {\unexpanded\@xpthree{\sseq@obj{#1.nodetext}}}
+                [every text node part/.code={}]
+                \@nx\sseq@obj{#1.labelnodes};
+            }%
+        \else
+            \tikz@node@textfont
+            \edef\sseq@classnodetextoptions{\@xptwo\@nx\sseq@obj{#1.nodetext.options}}
+            \edef\sseq@classnodetext{\@xptwo\@nx\sseq@obj{#1.nodetext}}
+            \sseq@setnodetext
+            \let\tikz@fig@name\sseq@thisnodename
+            \pgfmultipartnode{\tikz@shape}{\tikz@anchor}{\tikz@fig@name}{\sseq@drawnode}%
+            \tikz@alias
+            \sseq@obj{#1.labelnodes}
+        \fi
+        \sseq@obj@ifdef{#1.tooltip}{
+            \pgfpointanchor{\sseq@thisnodename}{west}
+            \pgf@xa=\pgf@x
+            \pgfpointanchor{\sseq@thisnodename}{south}
+            \pgf@ya=\pgf@y
+%
+            \pgf@process{\pgfpointdiff{\pgfpointtransformed{\pgfpointanchor{\sseq@thisnodename}{west}}}{\pgfpointtransformed{\pgfpointanchor{\sseq@thisnodename}{east}}}}
+            \pgf@xb=\pgf@x
+            \pgf@process{\pgfpointdiff{\pgfpointtransformed{\pgfpointanchor{\sseq@thisnodename}{south}}}{\pgfpointtransformed{\pgfpointanchor{\sseq@thisnodename}{north}}}}
+            \pgf@yb=\pgf@y
+%
+            \setbox\tikz@tempbox=\hbox{
+                \pgfinterruptpicture
+                \sseqtooltip{\rule{\pgf@xb}{0pt}\rule{0pt}{\pgf@yb}}{\sseq@obj{#1.tooltip}}
+                \endpgfinterruptpicture
+            }
+            {%
+                \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}%
+                \pgfapproximatenonlineartransformation%
+                \pgfqboxsynced{\tikz@tempbox}%
+            }%
+        }{}
+        \endpgfscope
+    \fi\fi\fi\fi
+    \ifsseq@outofrange
+        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}%
+        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{-\the\sseq@x cm}{-\the\sseq@y cm}}}
+        \pgftransformresetnontranslations
+        \sseq@globalrotatetransform
+        \sseq@classplacementtransform
+        \sseq@offset{\sseq@thisposnum}{\sseq@obj{partcoord.\sseq@thispos.numnodes}}
+        \pgfcoordinate{\sseq@thisnodename}{\pgfpointorigin}%
+    \fi
+    \endgroup
+}
+\def\sseq@setnodetext{%
+    \setbox\pgfnodeparttextbox=\hbox{%
+        \pgfscope%
+        \tikzset{every text node part/.try}%
+        \sseq@classnodetextoptions
+        \ifx\tikz@textopacity\pgfutil@empty%
+        \else%
+         \pgfsetfillopacity{\tikz@textopacity}%
+          \pgfsetstrokeopacity{\tikz@textopacity}%
+        \fi%
+        \pgfinterruptpicture
+      \ifx\tikz@text@width\pgfutil@empty%
+        \tikz@textfont%
+      \else%
+        \begingroup%
+        	\pgfmathsetlength{\pgf@x}{\tikz@text@width}%
+          \pgfutil@minipage[t]{\pgf@x}\leavevmode\hbox{}%
+            \tikz@textfont%
+            \tikz@text@action%
+      \fi%
+        \ifx\tikz@textcolor\pgfutil@empty%
+        \else%
+          \pgfutil@colorlet{.}{\tikz@textcolor}%
+        \fi%
+        \pgfsetcolor{.}%
+          \tikz@atbegin@node%
+          \sseq@classnodetext%
+          \tikz@atend@node%
+           \ifx\tikz@text@width\pgfutil@empty%
+           \else%
+              \pgfutil@endminipage%
+            \endgroup%
+          \fi%
+          \endpgfinterruptpicture
+      \endpgfscope%
+    }%
+    \ifx\tikz@text@width\pgfutil@empty%
+    \else%
+      \pgfmathsetlength{\pgf@x}{\tikz@text@width}%
+      \wd\pgfnodeparttextbox=\pgf@x%
+    \fi%
+    \ifx\tikz@text@height\pgfutil@empty%
+    \else%
+      \pgfmathsetlength{\pgf@x}{\tikz@text@height}%
+      \ht\pgfnodeparttextbox=\pgf@x%
+    \fi%
+    \ifx\tikz@text@depth\pgfutil@empty%
+    \else%
+      \pgfmathsetlength{\pgf@x}{\tikz@text@depth}%
+      \dp\pgfnodeparttextbox=\pgf@x%
+    \fi%
+}
+\def\sseq@drawnode{%
+  \pgfutil@tempdima=\pgflinewidth%
+  {%
+    \tikz@mode%
+    %\iftikz@mode@clip \sseq@error@internal{Clip shouldn't happen here, but this error should be caught earlier}{}\fi %
+    \iftikz@mode@draw%
+        \iftikz@mode@double%
+        % Change line width
+            \begingroup%
+            \pgfsys@beginscope%
+            \tikz@double@setup%
+        \fi%
+    \fi%
+    %
+    % Step 10: Do stroke/fill as needed
+    %
+    \sseq@eval{\noexpand\pgfusepath{%
+        \iftikz@mode@fill fill,\fi%
+        \iftikz@mode@draw draw,\fi%
+    }}%
+    %
+    % Step 11: Double stroke, if necessary
+    %
+    \iftikz@mode@draw%
+        \iftikz@mode@double%
+            \pgfsys@endscope%
+            \endgroup%
+        \fi%
+    \fi
+  }%
+  \global\pgflinewidth=\pgfutil@tempdima%
+}
+
+%%%
+%%% Drawing edges
+%%%
+\def\sseq@ifinrange(#1){\sseq@ifinrange@#1,\sseq@nil}
+\def\sseq@ifinrange@#1,#2,#3\sseq@nil{%
+    \sseq@tempx=#1\relax\sseq@tempy=#2\relax
+    \sseq@outofrangetrue
+    \ifnum\sseq@tempx<\sseq@xmaxpp\relax\ifnum\sseq@tempx>\sseq@xminmm\relax\ifnum\sseq@tempy<\sseq@ymaxpp\relax\ifnum\sseq@tempy>\sseq@yminmm\relax
+    \sseq@outofrangefalse
+    \fi\fi\fi\fi
+    \ifsseq@outofrange
+        \@xp\pgfutil@secondoftwo
+    \else
+        \@xp\pgfutil@firstoftwo
+    \fi
+}
+
+\def\sseq@fullcoord@to@partialcoord(#1){\sseq@fullcoord@to@partialcoord@#1,\@nil}
+\def\sseq@fullcoord@to@partialcoord@#1,#2,#3\@nil{{#1cm}{#2cm}}
+% #1 -- source (full)
+% #2 -- target (full)
+% #3 -- which type of edge (either "structline" or "differential")
+% #4 -- options
+\def\sseq@drawedge(#1)(#2)#3#4{%
+    \begingroup\pgfscope
+    \def\sseq@edgetype{#3}
+    \let\sseq@edgesourceanchor\pgfutil@empty
+    \let\sseq@edgetargetanchor\pgfutil@empty
+%
+    \sseq@needstikzfalse
+    \def\pgfkeysdefaultpath{/sseqpages/#3/}%
+    \sseq@options@bothpassmode
+    \sseq@thesseqstyle
+    \sseq@theedgestyle\csname sseq@the#3style\endcsname\the\sseq@scope@toks
+    #4%
+    \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{-\the\sseq@x cm}{-\the\sseq@y cm}}}%
+    % First calculate actual start and end of the edge
+    \let\tempaf\pgfutil@empty
+    \ifx\sseq@edgesourceanchor\pgfutil@empty % Check that the source doesn't have a specified anchor
+        \def\tempa{\pgfpointanchor{sseq{#1}}{center}}% if so, start by taking the center of that coordinate
+    \else
+        \edef\tempa{\@nx\pgfpointanchor{sseq{#1}}{\sseq@edgesourceanchor}} % If it has an anchor, use that
+        \let\tempaf\tempa
+    \fi
+    \ifx\sseq@edgetargetanchor\pgfutil@empty % check that the target doesn't have a specified anchor
+        \def\tempb{\pgfpointshapeborder{sseq{#2}}{\tempa}}% if so, our end point is the point on the boundary of node b that is in the direction of our initial start coordinate
+    \else
+        \edef\tempb{\@nx\pgfpointanchor{sseq{#2}}{\sseq@edgetargetanchor}}% If it has a specified anchor, use that
+    \fi
+    \let\tempbf\tempb
+    \ifx\tempaf\pgfutil@empty%
+        \def\tempaf{\pgfpointshapeborder{sseq{#1}}{\tempb}}%
+    \fi
+%
+    \tikz@options
+    \tikz@mode
+    \def\temparrowstartspec{}%
+    \def\temparrowendspec{}%
+    \pgfcoordinate{tempa}{\tempaf}%
+    \pgfcoordinate{tempb}{\tempbf}%
+    \pgftransformreset
+    \sseq@ifinrange(#1){\sseq@ifinrange(#2){\sseq@outofrangefalse}{\sseq@outofrangetrue}}{\sseq@outofrangetrue}%
+    \ifsseq@outofrange
+        \sseq@handleoffpageedge{#1}{#2}{#3}%
+    \fi
+    \ifsseq@drawedge
+        % TODO: should some sort of transformation manipulation be here? Maybe allow user to specify preference?
+        % Don't draw dots on very short segments
+        \pgfpointdiff{\tempbf}{\tempaf}
+        \pgfmathveclen{\pgf@x}{\pgf@y}%
+        \@xp\pgfmathint\@xp{\pgfmathresult}%
+        \ifnum\pgfmathresult<10\relax%%17? % TODO: Fix this predicate
+            \tikzset{every text node part/.append code={\pgfsetcolor{white}}}% I wonder why this is here...
+            \ifx\temparrowstartspec\pgfutil@empty
+            \else
+                \def\temparrowstartspec{\pgfsetarrowsstart{}}%
+            \fi
+            \ifx\temparrowendspec\pgfutil@empty
+            \else
+                \def\temparrowendspec{\pgfsetarrowsend{}}%
+            \fi
+        \fi
+        \ifsseq@needstikz
+            \draw[/sseqpages,
+                /utils/exec={\sseq@thesseqstyle\sseq@theedgestyle\csname sseq@the#3style\endcsname\the\sseq@scope@toks
+                             \temparrowstartspec\temparrowendspec #4}%
+            ]  (tempa) to (tempb);%
+        \else
+            \temparrowstartspec
+            \temparrowendspec
+            \pgfpathmoveto{\pgfpointanchor{tempa}{center}}%
+            \pgfpathlineto{\pgfpointanchor{tempb}{center}}%
+            \sseq@eval{\noexpand\pgfusepath{%
+                \iftikz@mode@fill fill,\fi
+                \iftikz@mode@draw draw,\fi
+            }}%
+        \fi
+    \fi
+    \sseq@breakpoint
+    \endpgfscope\endgroup
+}
+
+% TODO: this macro is super expensive. Make it faster (avoid
+\def\sseq@handleoffpageedge#1#2#3{
+    \pgfpathmoveto{\tempaf}%
+    \pgfpathlineto{\tempbf}%
+    \pgfgetpath\thispath
+    \pgfusepath{discard}%
+    \pgfintersectionofpaths{\pgfsetpath\sseq@theclippath}{\pgfsetpath\thispath}%
+    \ifcase\pgfintersectionsolutions\relax
+        % No intersections, but one or both endpoints may be out of range but still in clipping region due to scaling. Add ellipses as appropriate.
+        \sseq@ifinrange(#1){% If the first endpoint is in range, the second must be out of range b/c sseq@outofrange is true.
+            %\edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@#3@spec\endcsname}}
+        }{%
+            \sseq@ifinrange(#2){%
+                \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@#3@spec\endcsname}}
+            }{\sseq@drawedge@handletrickyedge}% uh-oh, both ends are out of range
+        }%
+    \or
+        \sseq@ifinrange(#1){% If the startpoint is in range, the intersection must be the end.
+            \def\tempbf{\pgfpointintersectionsolution{1}}
+            \edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@#3@spec\endcsname}}
+            \pgfcoordinate{tempb}{\tempbf}
+        }{%
+            \sseq@ifinrange(#2){% If the startpoint is out of range and the endpoint is in range, the intersection must be the start
+                \def\tempaf{\pgfpointintersectionsolution{1}}%
+                \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@#3@spec\endcsname}}%
+                \pgfcoordinate{tempa}{\tempaf}%
+            }{\sseq@drawedge@handletrickyedge}% Uh-oh, both ends are out of range.
+        }
+    \or% an orphan
+        \ifsseq@draworphanedges
+            \sseq@drawedge@handleorphan
+        \else
+            \sseq@drawedgefalse % Don't draw "orphaned edges"
+        \fi
+    \else
+        \sseq@error{clip-not-convex}%
+        \sseq@breakfifi
+    \fi
+}
+
+\def\sseq@drawedge@handletrickyedge{%
+    \ifsseq@draworphanedges
+        \pgfintersectionofpaths{\pgfsetpath\sseq@therangepath}{\pgfsetpath\thispath}%
+        \ifnum\pgfintersectionsolutions=\z@
+            \sseq@drawedgefalse % don't draw orphan edges that never intersect actual range
+        \else% Now we have to make a line through tempa and tempb long enough so that it intersects the original clip area twice.
+            \pgfmathanglebetweenpoints{\pgfpointanchor{tempa}{center}}{\pgfpointanchor{tempb}{center}}%
+            \edef\tempangle{\pgfmathresult}
+            \pgfpathmoveto{\pgfpointadd{\pgfpointanchor{tempa}{center}}{\pgfpointpolar{\tempangle}{100cm}}}% a really long line
+            \pgfpathlineto{\pgfpointadd{\pgfpointanchor{tempa}{center}}{\pgfpointpolar{\tempangle}{-100cm}}}%
+            \pgfgetpath\thispath
+            \pgfusepath{discard}
+            \pgfintersectionofpaths{\pgfsetpath\sseq@theclippath}{\pgfsetpath\thispath}
+            \sseq@drawedge@handleorphan
+        \fi
+    \else
+        \sseq@drawedgefalse
+    \fi
+}
+
+
+\def\sseq@drawedge@handleorphan{%
+    \def\tempaf{\pgfpointintersectionsolution{1}}%
+    \def\tempbf{\pgfpointintersectionsolution{2}}%
+    \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@\sseq@edgetype @spec\endcsname}}%
+    \edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@\sseq@edgetype @spec\endcsname}}%
+    \pgfcoordinate{tempa}{\tempaf}%
+    \pgfcoordinate{tempb}{\tempbf}%
+}
+
+
+%
+% #1 -- first coordinate
+% #2 -- second coordinate
+% #3 -- uid
+\def\sseq@circleclass@draw#1#2#3{
+    \begingroup
+        \pgfmathanglebetweenpoints{\pgfpointanchor{sseq{#2}}{center}}{\pgfpointanchor{sseq{#3}}{center}}
+        \let\tempangle\pgfmathresult
+        \let\tikz@lib@fit@scan@handle\sseq@fit@tikz@lib@fit@scan@handle % install fit modifications.
+        \let\tikz@calc@anchor\sseq@fit@tikz@calc@anchor
+        \sseq@tempiftrue
+        \node[
+            rotate fit=\tempangle,
+            /utils/exec={\sseq@thesseqstyle\sseq@thecircleclassstyle\the\sseq@scope@toks\sseq@savedoptioncode
+                \sseq@obj{#1.options}
+                \sseq@obj{#1.fitnodes}
+                \@xp\pgfkeysalso\@xp{\romannumeral0\sseq@obj{#1.tikzprimoptions}}
+            }
+        ] {};
+    \endgroup
+}
+% Modifies tikz commands \tikz@lib@fit@scan@handle from \pgf\frontendlayer\tikz\libraries\tikzlibraryfit.code.tex line 81 and
+% \tikz@calc@anchor from \pgf\frontendlayer\tikz\tikz.code.tex line 5164
+% make it so that fit silently ignores nodes that are not defined.
+% This is copied with modification from \pgf\frontendlayer\tikz\libraries\tikzlibraryfit.code.tex line 81
+\def\sseq@fit@tikz@lib@fit@scan@handle#1{%
+  \ifsseq@tempif % this has been set in the following macro to be true if there is a node with the given name. If it's not true, ignore this.
+      \iftikz@shapeborder%
+        % Ok, fit all four external anchors, if they exist
+        \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{west}}%
+        \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{east}}%
+        \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{north}}%
+        \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{south}}%
+      \else%
+        \tikz@lib@fit@adjust{#1}%
+      \fi%
+  \fi
+  \sseq@tempiftrue
+  \tikz@lib@fit@scan%
+}
+
+% This is copied with modification from \pgf\frontendlayer\tikz\tikz.code.tex line 5164
+\def\sseq@fit@tikz@calc@anchor#1.#2\tikz@stop{%
+  \pgfutil@ifundefined{pgf@sh@ns@#1}{\sseq@tempiffalse}{%If the node doesn't exist, don't throw an error but record that we should skip it
+    \pgfpointanchor{\tikz@pp@name{#1}}{#2}%
+  }%s
+}
+
+
+%% New shapes and arrows
+%% These use lots of keys with spaces so it's convenient to turn off ExplSyntax.
+
+% Stolen from: https://tex.stackexchange.com/a/24621
+\pgfqkeys{/pgf}{
+    ellipse ratio/.code={\pgfkeyssetvalue{/pgf/ellipse ratio}{#1}},
+    ellipse ratio/.initial=1
+}
+\pgfdeclareshape{newellipse}
+{
+  \inheritsavedanchors[from=ellipse]
+  \inheritanchorborder[from=ellipse]
+  \savedanchor\radius{%
+    %
+    % Caculate ``height radius''
+    %
+    \pgf@y=.5\ht\pgfnodeparttextbox%
+    \advance\pgf@y by.5\dp\pgfnodeparttextbox%
+    \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/inner ysep}}%
+    \advance\pgf@y by\pgf@yb%
+    %
+    % Caculate ``width radius''
+    %
+    \pgf@x=.5\wd\pgfnodeparttextbox%
+    \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}%
+    \advance\pgf@x by\pgf@xb%
+    %
+    % Adjust
+    %
+    \pgfkeysgetvalue{/pgf/ellipse ratio}{\ratioscale}
+    \pgfmathsetmacro\widthfactor{sqrt(\ratioscale^2+1)/\ratioscale}
+    \pgfmathsetmacro\heightfactor{sqrt(\ratioscale^2+1)}
+    \pgf@x=\widthfactor\pgf@x%
+    \pgf@y=\heightfactor\pgf@y%
+    %
+    % Adjust height, if necessary
+    %
+    \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/minimum height}}%
+    \ifdim\pgf@y<.5\pgf@yc%
+      \pgf@y=.5\pgf@yc%
+    \fi%
+    %
+    % Adjust width, if necessary
+    %
+    \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/minimum width}}%
+    \ifdim\pgf@x<.5\pgf@xc%
+      \pgf@x=.5\pgf@xc%
+    \fi%
+    %
+    % Add outer sep
+    %
+    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
+    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
+    \advance\pgf@x by\pgf@xb%
+    \advance\pgf@y by\pgf@yb%
+  }
+
+  \inheritanchor[from=ellipse]{center}
+  \inheritanchor[from=ellipse]{mid}
+  \inheritanchor[from=ellipse]{base}
+  \inheritanchor[from=ellipse]{north}
+  \inheritanchor[from=ellipse]{south}
+  \inheritanchor[from=ellipse]{west}
+  \inheritanchor[from=ellipse]{mid west}
+  \inheritanchor[from=ellipse]{base west}
+  \inheritanchor[from=ellipse]{north west}
+  \inheritanchor[from=ellipse]{south west}
+  \inheritanchor[from=ellipse]{east}
+  \inheritanchor[from=ellipse]{mid east}
+  \inheritanchor[from=ellipse]{base east}
+  \inheritanchor[from=ellipse]{north east}
+  \inheritanchor[from=ellipse]{south east}
+
+  \inheritbackgroundpath[from=ellipse]
+}
+
+%%
+%%
+%% n concentric circles
+%%
+
+\tikzset{circlen/.code={\def\circlen@n{#1}\pgfkeysalso{shape=circlen@shape}}}
+\pgfdeclareshape{circlen@shape}
+{
+  \savedanchor\centerpoint{%
+    \pgf@x=.5\wd\pgfnodeparttextbox%
+    \pgf@y=.5\ht\pgfnodeparttextbox%
+    \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
+  }
+
+  \saveddimen\radius{%
+    %
+    % Caculate ``height radius''
+    %
+    \pgf@ya=.5\ht\pgfnodeparttextbox%
+    \advance\pgf@ya by.5\dp\pgfnodeparttextbox%
+    \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/inner ysep}}%
+    \advance\pgf@ya by\pgf@yb%
+    %
+    % Caculate ``width radius''
+    %
+    \pgf@xa=.5\wd\pgfnodeparttextbox%
+    \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}%
+    \advance\pgf@xa by\pgf@xb%
+    %
+    % Calculate length of radius vector:
+    %
+    \pgf@process{\pgfpointnormalised{\pgfqpoint{\pgf@xa}{\pgf@ya}}}%
+    \ifdim\pgf@x>\pgf@y%
+        \c@pgf@counta=\pgf@x%
+        \ifnum\c@pgf@counta=\z@%
+        \else%
+          \divide\c@pgf@counta by 255\relax%
+          \pgf@xa=16\pgf@xa\relax%
+          \divide\pgf@xa by\c@pgf@counta%
+          \pgf@xa=16\pgf@xa\relax%
+        \fi%
+      \else%
+        \c@pgf@counta=\pgf@y%
+        \ifnum\c@pgf@counta=\z@%
+        \else%
+          \divide\c@pgf@counta by 255\relax%
+          \pgf@ya=16\pgf@ya\relax%
+          \divide\pgf@ya by\c@pgf@counta%
+          \pgf@xa=16\pgf@ya\relax%
+        \fi%
+    \fi%
+    \pgf@x=\pgf@xa%
+    %
+    % If necessary, adjust radius so that the size requirements are
+    % met:
+    %
+    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/minimum width}}%
+    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/minimum height}}%
+    \ifdim\pgf@x<.5\pgf@xb%
+        \pgf@x=.5\pgf@xb%
+    \fi%
+    \ifdim\pgf@x<.5\pgf@yb%
+        \pgf@x=.5\pgf@yb%
+    \fi%
+    %
+    % Now, add larger of outer sepearations.
+    %
+    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
+    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
+    \ifdim\pgf@xb<\pgf@yb%
+      \advance\pgf@x by\pgf@yb%
+    \else%
+      \advance\pgf@x by\pgf@xb%
+    \fi%
+    \pgf@xb=2pt
+    \multiply\pgf@xb\circlen@n
+    \advance\pgf@x\pgf@xb
+    \advance\pgf@x-2pt\relax
+  }
+
+  %
+  % Anchors
+  %
+  \anchor{center}{\centerpoint}
+  \anchor{mid}{\centerpoint\pgfmathsetlength\pgf@y{.5ex}}
+  \anchor{base}{\centerpoint\pgf@y=0pt}
+  \anchor{north}{\centerpoint\advance\pgf@y by\radius}
+  \anchor{south}{\centerpoint\advance\pgf@y by-\radius}
+  \anchor{west}{\centerpoint\advance\pgf@x by-\radius}
+  \anchor{east}{\centerpoint\advance\pgf@x by\radius}
+  \anchor{mid west}{\centerpoint\advance\pgf@x by-\radius\pgfmathsetlength\pgf@y{.5ex}}
+  \anchor{mid east}{\centerpoint\advance\pgf@x by\radius\pgfmathsetlength\pgf@y{.5ex}}
+  \anchor{base west}{\centerpoint\advance\pgf@x by-\radius\pgf@y=0pt}
+  \anchor{base east}{\centerpoint\advance\pgf@x by\radius\pgf@y=0pt}
+  \anchor{north west}{
+    \centerpoint
+    \pgf@xa=\radius
+    \advance\pgf@x by-0.707107\pgf@xa
+    \advance\pgf@y by0.707107\pgf@xa
+  }
+  \anchor{south west}{
+    \centerpoint
+    \pgf@xa=\radius
+    \advance\pgf@x by-0.707107\pgf@xa
+    \advance\pgf@y by-0.707107\pgf@xa
+  }
+  \anchor{north east}{
+    \centerpoint
+    \pgf@xa=\radius
+    \advance\pgf@x by0.707107\pgf@xa
+    \advance\pgf@y by0.707107\pgf@xa
+  }
+  \anchor{south east}{
+    \centerpoint
+    \pgf@xa=\radius
+    \advance\pgf@x by0.707107\pgf@xa
+    \advance\pgf@y by-0.707107\pgf@xa
+  }
+  \anchorborder{
+    \pgf@xa=\pgf@x%
+    \pgf@ya=\pgf@y%
+    \edef\pgf@marshal{%
+      \noexpand\pgfpointborderellipse
+      {\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}
+      {\noexpand\pgfqpoint{\radius}{\radius}}%
+    }%
+    \pgf@marshal%
+    \pgf@xa=\pgf@x%
+    \pgf@ya=\pgf@y%
+    \centerpoint%
+    \advance\pgf@x by\pgf@xa%
+    \advance\pgf@y by\pgf@ya%
+  }
+
+  %
+  % Background path
+  %
+  \behindbackgroundpath{
+    \pgfutil@tempdima=\radius%
+    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
+    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
+    \ifdim\pgf@xb<\pgf@yb%
+      \advance\pgfutil@tempdima by-\pgf@yb%
+    \else%
+      \advance\pgfutil@tempdima by-\pgf@xb%
+    \fi%
+    \sseq@tempcount=\@ne
+    \loop
+    \pgfpathcircle{\centerpoint}{\pgfutil@tempdima}%
+    \advance\pgfutil@tempdima-2pt\relax
+    \advance\sseq@tempcount\@ne
+    \ifnum\sseq@tempcount<\circlen@n \repeat
+    \tikz@mode
+    \sseq@eval{\noexpand\pgfusepath{
+        \iftikz@mode@draw draw,\fi
+    }}
+  }
+  \backgroundpath{%
+    \pgfutil@tempdima=\radius%
+    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
+    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
+    \ifdim\pgf@xb<\pgf@yb%
+      \advance\pgfutil@tempdima by-\pgf@yb%
+    \else%
+      \advance\pgfutil@tempdima by-\pgf@xb%
+    \fi%
+    \advance\pgfutil@tempdima2pt\relax
+    \pgfutil@tempdimb=-2pt\relax
+    \multiply\pgfutil@tempdimb\circlen@n
+    \advance\pgfutil@tempdima\pgfutil@tempdimb\relax
+    \pgfpathcircle{\centerpoint}{\pgfutil@tempdima}
+  }
+}
+
+
+
+% For out of bounds edges:
+
+\pgfdeclarearrow{
+    name = ...,
+    parameters = { \the\pgfarrowlength\the\pgflinewidth},
+    setup code = {
+        % The different end values:
+        \pgfarrowssetlineend{-\pgfarrowlength}
+        \pgfarrowssetbackend{-0.6\pgfarrowlength}
+        % The hull
+        \pgfarrowshullpoint{-\pgfarrowlength}{0pt}
+        \pgfarrowshullpoint{\pgfarrowlength}{0pt}
+        % Saves: Only the length:
+        \pgfarrowssavethe\pgfarrowlength
+        \pgfarrowssavethe\pgflinewidth
+    },
+    drawing code = {
+        \pgfpathcircle{\pgfpoint{-0.7\pgfarrowlength}{0pt}}{1.5\pgflinewidth}
+        \pgfpathcircle{\pgfpoint{-0.4\pgfarrowlength}{0pt}}{1.5\pgflinewidth}
+        \pgfpathcircle{\pgfpoint{-0.1\pgfarrowlength}{0pt}}{1.5\pgflinewidth}
+        \pgfpathclose
+        \pgfusepathqfill
+    },
+    defaults = { length = 0.3cm }
+} 
\ No newline at end of file
-- 
cgit v1.2.3

