From ff587f620cc7c6d0068c33b27a8e554bce2b08fe Mon Sep 17 00:00:00 2001
From: Karl Berry <karl@freefriends.org>
Date: Thu, 3 Aug 2017 21:07:30 +0000
Subject: spectralsequences (3aug17)

git-svn-id: svn://tug.org/texlive/trunk@44942 c570f23f-e606-0410-a88d-b1316a301751
---
 .../latex/spectralsequences/sseqdrawing.code.tex   | 924 +++++++++++++++------
 1 file changed, 691 insertions(+), 233 deletions(-)

(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
index 098e73f9110..c8bba066b23 100644
--- a/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex
+++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences.sty version 1.0
+%% Package: spectralsequences v1.1.0
 %% Author: Hood Chatham
 %% Email: hood@mit.edu
-%% Date: 2017-06-18
+%% Date: 2017-08-02
 %% License: Latex Project Public License
 %%
 %% File: sseqdrawing.code.tex
@@ -14,165 +14,314 @@
 %%    the axes ticks was taking about 1/3 of the compile time (a little under 1s out of a 3.2)
 %%
 
+% Only for integer valued coordinates...
+\def\sseq@qpointxy#1#2{\pgfqpointxy{\numexpr#1+\sseq@xoffset\relax}{\numexpr#2+\sseq@yoffset\relax}}
 
+\def\sseq@transform@xymirror{
+    \pgfsetxvec{\pgfqpoint{1cm}{0cm}}
+    \pgfsetyvec{\pgfqpoint{0cm}{1cm}}
+    \pgftransformcm{0}{1}{1}{0}{\pgfpointxy{\sseq@xoffset*\sseq@xscale }{\sseq@yoffset*\sseq@yscale}} % Reflect x and y axes,
+    \pgftransformshift{\pgfpointxy{-\sseq@xoffset*\sseq@yscale}{-\sseq@yoffset*\sseq@xscale}}    % but we need to conjugate by a shift of (xoffset,yoffset)
+    \pgfsetyvec{\pgfqpoint{0cm}{\sseq@xscale cm}}
+    \pgfsetxvec{\pgfqpoint{\sseq@yscale cm}{0cm}}
+}
+
+
+\def\sseq@setlayoutparameter#1#2{\@xp\let\csname sseq@#1\@xp\endcsname\csname sseq@#1@#2\endcsname}
+\def\sseq@setlayoutparameters{
+    \sseq@setlayoutparameter{yaxisorigin}{x\sseq@xaxistype}
+    \sseq@setlayoutparameter{drawyaxis}{x\sseq@xaxistype}
+    \sseq@setlayoutparameter{yaxisstartoffset}{x\sseq@xaxistype}
+    \sseq@setlayoutparameter{yaxisendoffset}{x\sseq@xaxistype}
+    \sseq@setlayoutparameter{bottomgridpadding}{x\sseq@xaxistype}
+    \sseq@setlayoutparameter{topgridpadding}{x\sseq@xaxistype}
+    \sseq@setlayoutparameter{bottomclippadding}{x\sseq@xaxistype}
+    \sseq@setlayoutparameter{topclippadding}{x\sseq@xaxistype}
+    \sseq@setlayoutparameter{xlabelposition}{x\sseq@xaxistype}
+%
+    \sseq@setlayoutparameter{xaxisorigin}{y\sseq@yaxistype}
+    \sseq@setlayoutparameter{drawxaxis}{y\sseq@xaxistype}
+    \sseq@setlayoutparameter{xaxisstartoffset}{y\sseq@yaxistype}
+    \sseq@setlayoutparameter{xaxisendoffset}{y\sseq@yaxistype}
+    \sseq@setlayoutparameter{leftgridpadding}{y\sseq@yaxistype}
+    \sseq@setlayoutparameter{rightgridpadding}{y\sseq@yaxistype}
+    \sseq@setlayoutparameter{leftclippadding}{y\sseq@yaxistype}
+    \sseq@setlayoutparameter{rightclippadding}{y\sseq@yaxistype}
+    \sseq@setlayoutparameter{ylabelposition}{y\sseq@xaxistype}
+}
+
+% The appropriate one of these is chosen by the "axis type" keys in sseqkeys.
+
+% Used to determine axis and ticks placement
+\def\sseq@xaxisorigin@yborder{\sseq@xmin}
+\def\sseq@xaxisorigin@yframe{\sseq@xmin}
+\def\sseq@xaxisorigin@ycenter{\sseq@xaxisorigin@center@}
+\def\sseq@yaxisorigin@xborder{\sseq@ymin}
+\def\sseq@yaxisorigin@xframe{\sseq@ymin}
+\def\sseq@yaxisorigin@xcenter{\sseq@yaxisorigin@center@}
+
+% Used to determine clipping and grid boundaries
+\def\sseq@leftgridpadding@yborder{\dimexpr\sseq@yaxisgap-\sseq@yclip@axisgap\relax}
+\def\sseq@rightgridpadding@yborder{\sseq@xaxis@end@extend}
+\def\sseq@leftgridpadding@ycenter{\sseq@xaxis@start@extend}
+\def\sseq@rightgridpadding@ycenter{\sseq@xaxis@end@extend}
+\def\sseq@leftgridpadding@yframe{\dimexpr\sseq@yaxisgap-\sseq@yclip@axisgap\relax}
+\def\sseq@rightgridpadding@yframe{5cm} % Just make it big enough to push off the end of the clip
+\def\sseq@leftgridpadding@ynone{\sseq@yaxisgap}
+\def\sseq@rightgridpadding@ynone{\sseq@yaxisgap}
+
+
+\def\sseq@bottomgridpadding@xborder{\dimexpr\sseq@xaxisgap-\sseq@xclip@axisgap\relax}
+\def\sseq@topgridpadding@xborder{\sseq@yaxis@end@extend}
+\def\sseq@bottomgridpadding@xcenter{\sseq@yaxis@start@extend}
+\def\sseq@topgridpadding@xcenter{\sseq@yaxis@end@extend}
+\def\sseq@bottomgridpadding@xframe{\dimexpr\sseq@xaxisgap-\sseq@xclip@axisgap\relax}
+\def\sseq@topgridpadding@xframe{5cm}
+\def\sseq@bottomgridpadding@xnone{\sseqxaxisgap}
+\def\sseq@topgridpadding@xnone{\sseq@xaxisgap}
+
+\def\sseq@leftclippadding@yborder{\dimexpr-\sseq@yaxisgap+\sseq@yclip@axisgap\relax}
+\def\sseq@rightclippadding@yborder{\dimexpr\sseq@xaxis@end@extend+\sseq@clip@padding@right\relax}
+\def\sseq@leftclippadding@ycenter{\dimexpr-\sseq@xaxis@start@extend-\sseq@clip@padding@left\relax}
+\def\sseq@rightclippadding@ycenter{\dimexpr\sseq@xaxis@end@extend+\sseq@clip@padding@right\relax}
+\def\sseq@leftclippadding@yframe{\dimexpr-\sseq@yaxisgap+\sseq@yclip@axisgap\relax}
+\def\sseq@rightclippadding@yframe{\dimexpr\sseq@yaxisgap-\sseq@yclip@axisgap\relax}
+\def\sseq@leftclippadding@ynone{\dimexpr-\sseq@yaxisgap-\sseq@clip@padding@left\relax}
+\def\sseq@rightclippadding@ynone{\dimexpr\sseq@yaxisgap+\sseq@clip@padding@right\relax}
+
+\def\sseq@bottomclippadding@xborder{\dimexpr-\sseq@xaxisgap+\sseq@xclip@axisgap\relax}
+\def\sseq@topclippadding@xborder{\dimexpr\sseq@yaxis@end@extend+\sseq@clip@padding@top\relax}
+\def\sseq@bottomclippadding@xcenter{\dimexpr-\sseq@yaxis@start@extend-\sseq@clip@padding@bottom\relax}
+\def\sseq@topclippadding@xcenter{\dimexpr\sseq@yaxis@end@extend+\sseq@clip@padding@top\relax}
+\def\sseq@bottomclippadding@xframe{\dimexpr-\sseq@xaxisgap+\sseq@xclip@axisgap\relax}
+\def\sseq@topclippadding@xframe{\dimexpr\sseq@xaxisgap-\sseq@xclip@axisgap\relax}
+\def\sseq@bottomclippadding@xnone{\dimexpr-\sseq@xaxisgap-\sseq@clip@padding@bottom\relax}
+\def\sseq@topclippadding@xnone{\dimexpr\sseq@xaxisgap+\sseq@clip@padding@top\relax}
+
+% Used to figure out how much further beyond (min -- max) to draw axes
+\def\sseq@xaxisstartoffset@yborder{\dimexpr\sseq@xaxis@tail+\sseq@yaxisgap\relax}
+\def\sseq@xaxisendoffset@yborder{\sseq@xaxis@end@extend}
+\def\sseq@xaxisstartoffset@ycenter{\sseq@xaxis@start@extend}
+\def\sseq@xaxisendoffset@ycenter{\sseq@xaxis@end@extend}
+\def\sseq@xaxisstartoffset@yframe{\sseq@yaxisgap}
+\def\sseq@xaxisendoffset@yframe{\sseq@yaxisgap}
 
+\def\sseq@yaxisstartoffset@xborder{\dimexpr\sseq@yaxis@tail+\sseq@xaxisgap\relax}
+\def\sseq@yaxisendoffset@xborder{\sseq@yaxis@end@extend}
+\def\sseq@yaxisstartoffset@xcenter{\sseq@yaxis@start@extend}
+\def\sseq@yaxisendoffset@xcenter{\sseq@yaxis@end@extend}
+\def\sseq@yaxisstartoffset@xframe{\sseq@xaxisgap}
+\def\sseq@yaxisendoffset@xframe{\sseq@xaxisgap}
+
+\def\sseq@xlabelposition@xborder{(0,-\sseq@xaxisstartoffset)}
+\def\sseq@xlabelposition@xcenter{(-\sseq@yaxisgap,-\sseq@xaxisstartoffset-5pt)}
+\def\sseq@xlabelposition@xframe{(0,-\sseq@xaxisgap-\sseq@xlabelgap-10pt)}
+\def\sseq@xlabelposition@xnone{(0,0)}
+
+\def\sseq@ylabelposition@yborder{(0,\sseq@yaxisstartoffset)}
+\def\sseq@ylabelposition@ycenter{(-\sseq@xaxisgap,\sseq@yaxisstartoffset+5pt)}
+\def\sseq@ylabelposition@yframe{(0,\sseq@yaxisgap+\sseq@ylabelgap+10pt)}
+\def\sseq@ylabelposition@ynone{(0,0)}
 %%%
 %%% 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
+    \bgroup
+    \sseq@drawxaxis
+    \ifsseq@drawxaxisticks
+        \sseq@drawxticks
     \fi
+    \egroup
 }
 \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
+    \bgroup
+    \sseq@drawyaxis
+    \ifsseq@drawyaxisticks
+        \sseq@drawyticks
     \fi
+    \egroup
 }
-\def\sseq@drawxaxis{
-    \bgroup
-    \pgftransformreset
-    \sseq@globaldetonetransform
-    %
+
+% Draws an x axis. Use with \sseq@transform@xymirror to draw y axis.
+% #1 -- horizontal start offset
+% #2 -- horizontal end offset
+% #3 -- vertical offset
+% #4 -- start value
+% #5 -- end value
+% #6 -- vertical value
+\def\sseq@drawaxis@generic#1#2#3#4#5#6{
     \bgroup
-    \pgftransformxshift{\sseq@xaxis@end@extend}\pgftransformyshift{-\sseq@xaxisgap}
-    \sseq@globalscaletransform
-    \pgfpathmoveto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}}
+    \pgftransformshift{\pgfqpoint{#2}{#3}}
+    \pgfpathmoveto{\sseq@qpointxy{#5}{#6}}
     \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
+    \pgftransformshift{\pgfqpoint{#1}{#3}}
+    \pgfpathlineto{\sseq@qpointxy{#4}{#6}}
     \egroup
+}
+
+\def\sseq@drawxaxis@ynone{
+    \sseq@drawxaxisticksfalse
+}
+\def\sseq@drawyaxis@xnone{
+    \sseq@drawyaxisticksfalse
+}
+
+\def\sseq@drawxaxis@yborder{
+    \sseq@drawaxis@generic{-\sseq@xaxisstartoffset}{\sseq@xaxisendoffset}{-\sseq@xaxisgap}{\sseq@xmin}{\sseq@xmax}{\sseq@yaxisorigin}
     \pgfusepath{stroke}
 }
-\def\sseq@drawyaxis{
-    \bgroup
-    \pgftransformreset
-    \sseq@globaldetonetransform
+\let\sseq@drawxaxis@ycenter\sseq@drawxaxis@yborder
+
+\def\sseq@drawxaxis@yframe{
+    \sseq@drawaxis@generic{-\sseq@xaxisstartoffset}{\sseq@xaxisendoffset}{-\sseq@xaxisgap}{\sseq@xmin}{\sseq@xmax}{\sseq@ymin}
+    \sseq@drawaxis@generic{-\sseq@xaxisstartoffset}{\sseq@xaxisendoffset}{ \sseq@xaxisgap}{\sseq@xmin}{\sseq@xmax}{\sseq@ymax}
+    \pgfusepath{stroke}
+}
+\def\sseq@drawyaxis@xborder{
     \bgroup
-    \pgftransformyshift{\sseq@yaxis@end@extend}\pgftransformxshift{-\sseq@yaxisgap}
-    \sseq@globalscaletransform
-    \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}}
+    \sseq@transform@xymirror
+    \sseq@drawaxis@generic{-\sseq@yaxisstartoffset}{\sseq@yaxisendoffset}{-\sseq@yaxisgap}{\sseq@ymin}{\sseq@ymax}{\sseq@xaxisorigin}
+    \pgfusepath{stroke}%
     \egroup
+}
+\let\sseq@drawyaxis@xcenter\sseq@drawyaxis@xborder
+\def\sseq@drawyaxis@xframe{
     \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
+    \sseq@transform@xymirror
+    \sseq@drawaxis@generic{-\sseq@yaxisstartoffset}{\sseq@yaxisendoffset}{-\sseq@yaxisgap}{\sseq@ymin}{\sseq@ymax}{\sseq@xmin}
+    \sseq@drawaxis@generic{-\sseq@yaxisstartoffset}{\sseq@yaxisendoffset}{ \sseq@yaxisgap}{\sseq@ymin}{\sseq@ymax}{\sseq@xmax}
     \pgfusepath{stroke}%
+    \egroup
 }
-\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
+
+\ExplSyntaxOn
+\def\sseq@intdivceiling#1#2{%
+    \ifnum#1>\z@ % \int_div_truncate:nn rounds towards 0. We want \int_div_ceiling
+        \int_div_truncate:nn{#1+#2-1}{#2} % if positive, use ceil(p/q)=floor((p+q-1)/q) for p,q integers
+    \else
+        \int_div_truncate:nn{#1}{#2} % if we are negative, towards 0 is ceiling
+    \fi
+}
+\def\sseq@intdivfloor#1#2{%
+    \ifnum#1<\z@ % \int_div_truncate:nn rounds towards 0. We want \int_div_floor
+        \int_div_truncate:nn{#1-#2+1}{#2} % if we are negative, use floor(p/q) = ceil(p-q+1/q) for p,q integers
+    \else
+        \int_div_truncate:nn{#1}{#2} % if positive, towards 0 is floor
+    \fi
+}
+\ExplSyntaxOff
+
+% #1 -- xmin
+% #2 -- xmax
+% #3 -- step
+% #4 -- offset
+% #5 -- ymin
+% #6 -- xaxisgap
+% #7 -- code
+\def\sseq@tickloop@generic#1#2#3#4#5#6#7{
+    \sseq@tempx=\numexpr % min
+        \sseq@intdivceiling{#1}{#3} * #3
+        -
+        \sseq@intdivceiling{#4}{#3} * #3 + #4
+    \relax
+    \ifnum\sseq@tempx<#1\relax
+        \advance\sseq@tempx#3\relax
+    \fi
+    \sseq@tempxb=\numexpr#2+1\relax % max
     \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
+        \pgftransformshift{\sseq@qpointxy{\sseq@tempx}{#5}}%
+        \pgftransformshift{\pgfqpoint{0pt}{#6}}
+        #7
+        \egroup
+        \advance\sseq@tempx#3\relax
+    \ifnum\sseq@tempx<\sseq@tempxb\repeat
+}
+
+
+\def\sseq@drawxticks{%
+    \sseq@tickloop@generic{\sseq@xmin}{\sseq@xmax}{\sseq@xtickstep}{\sseq@xtickstepoffset}{\sseq@yaxisorigin}{-\sseq@xaxisgap}{
         \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
+        \pgftransformshift{\pgfqpoint{0pt}{-\sseq@ylabelgap}}
+        \pgftext{\hbox{$\sseq@xtickfn{\the\sseq@tempx}$}}%
+    }
+    \ifnum\sseq@xmajortickstep>\z@
+        \sseq@tickloop@generic{\sseq@xmin}{\sseq@xmax}{\sseq@xmajortickstep}{\sseq@xtickstepoffset}{\sseq@yaxisorigin}{-\sseq@xaxisgap}{
+            \pgfpathmoveto{\pgfpointorigin}
+            \pgfpathlineto{\pgfpoint{0}{-0.4*\sseq@xaxisgap}}
+        }
+    \fi
+    \ifnum\sseq@xminortickstep>\z@
+        \sseq@tickloop@generic{\sseq@xmin}{\sseq@xmax}{\sseq@xminortickstep}{\sseq@xtickstepoffset}{\sseq@yaxisorigin}{-\sseq@xaxisgap}{
+            \pgfpathmoveto{\pgfpointorigin}
+            \pgfpathlineto{\pgfpoint{0}{-0.2*\sseq@xaxisgap}}
+        }
+    \fi
+    \pgfusepath{stroke}
+}
+\def\sseq@drawyticks{%
+    \sseq@transform@xymirror
+    \sseq@tickloop@generic{\sseq@ymin}{\sseq@ymax}{\sseq@ytickstep}{\sseq@ytickstepoffset}{\sseq@xaxisorigin}{-\sseq@yaxisgap}{
         \sseq@ytickstyle
         \tikz@options
-        \pgftext{\hbox{$\sseq@ytickfn{\the\sseq@tempy}$}}
-        \egroup
-        \advance\sseq@tempy\sseq@ytickstep\relax
-    \ifnum\sseq@tempy<\sseq@tempmax\repeat
+        \pgftransformshift{\pgfqpoint{0pt}{-\sseq@ylabelgap}}
+        \pgftransformresetnontranslations
+        \pgftext{\hbox{$\sseq@ytickfn{\the\sseq@tempx}$}}%
+    }
+    \ifnum\sseq@ymajortickstep>\z@
+        \sseq@tickloop@generic{\sseq@ymin}{\sseq@ymax}{\sseq@ymajortickstep}{\sseq@ytickstepoffset}{\sseq@xaxisorigin}{-\sseq@yaxisgap}{
+            \pgfpathmoveto{\pgfpointorigin}
+            \pgfpathlineto{\pgfpoint{0}{-0.4*\sseq@yaxisgap}}
+        }
+    \fi
+    \ifnum\sseq@yminortickstep>\z@
+        \sseq@tickloop@generic{\sseq@ymin}{\sseq@ymax}{\sseq@yminortickstep}{\sseq@ytickstepoffset}{\sseq@xaxisorigin}{-\sseq@yaxisgap}{
+            \pgfpathmoveto{\pgfpointorigin}
+            \pgfpathlineto{\pgfpoint{0}{-0.2*\sseq@yaxisgap}}
+        }
+    \fi
+    \pgfusepath{stroke}
 }
+
+
 \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}}
+            \def\xmin{\pgftransformshift{\pgfqpoint{\sseq@leftclippadding}{0pt}}}
+            \def\ymin{\pgftransformshift{\pgfqpoint{0pt}{\sseq@bottomclippadding}}}
+            \def\xmax{\pgftransformshift{\pgfqpoint{\sseq@rightclippadding}{0pt}}}
+            \def\ymax{\pgftransformshift{\pgfqpoint{0pt}{\sseq@topclippadding}}}
             \bgroup
-            \xmin\ymin\sseq@globalscaletransform
-            \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
+            \xmin\ymin
+            \pgfpathmoveto{\pgfqpointxy{\numexpr\sseq@xmin+\sseq@xoffset\relax}{\numexpr\sseq@ymin+\sseq@yoffset\relax}}
             \egroup
             \bgroup
-            \xmin\ymax\sseq@globalscaletransform
-            \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}}
+            \xmin\ymax
+            \pgfpathlineto{\pgfqpointxy{\numexpr\sseq@xmin+\sseq@xoffset\relax}{\numexpr\sseq@ymax+\sseq@yoffset\relax}}
             \egroup
             \bgroup
-            \xmax\ymax\sseq@globalscaletransform
-            \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymax cm}}
+            \xmax\ymax
+            \pgfpathlineto{\pgfqpointxy{\numexpr\sseq@xmax+\sseq@xoffset\relax}{\numexpr\sseq@ymax+\sseq@yoffset\relax}}
             \egroup
             \bgroup
-            \xmax\ymin\sseq@globalscaletransform
-            \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}}
+            \xmax\ymin
+            \pgfpathlineto{\pgfqpointxy{\numexpr\sseq@xmax+\sseq@xoffset\relax}{\numexpr\sseq@ymin+\sseq@yoffset\relax}}
             \egroup
             \egroup
             \pgfpathclose
-            \pgfgetpath\sseq@theclippath % This stores the clipping so I can find intersections later
+            \pgfgetpath\sseq@theclippath % This stores the clipping so I can apply it 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}}
+                \pgfpathmoveto{\pgfqpointxy{\numexpr\sseq@xmin+\sseq@xoffset\relax}{\numexpr\sseq@ymin+\sseq@yoffset\relax}}
+                \pgfpathlineto{\pgfqpointxy{\numexpr\sseq@xmin+\sseq@xoffset\relax}{\numexpr\sseq@ymax+\sseq@yoffset\relax}}
+                \pgfpathlineto{\pgfqpointxy{\numexpr\sseq@xmax+\sseq@xoffset\relax}{\numexpr\sseq@ymax+\sseq@yoffset\relax}}
+                \pgfpathlineto{\pgfqpointxy{\numexpr\sseq@xmax+\sseq@xoffset\relax}{\numexpr\sseq@ymin+\sseq@yoffset\relax}}
                 \pgfpathclose
             \egroup
             \pgfgetpath\sseq@therangepath % Only for deciding whether to draw "tricky edges"
@@ -188,66 +337,194 @@
     \fi
 }
 \def\sseq@useclip{\ifx\sseq@theclippath\relax\else\pgfsetpath\sseq@theclippath\pgfusepath{clip}\fi}
+
+
+% sets \pgf@xa and \pgf@ya equal to the coordinates of (1,1), sets \pgf@xb and \pgf@xb equal to (x grid step, y grid step)
+\def\sseq@grid@setstepandgridstep{
+    \pgf@process{\pgfqpointxy{1}{1}}
+    \pgf@xa=\pgf@x
+    \pgf@ya=\pgf@y
+    \pgf@process{\pgfqpointxy{\sseq@xgridstep}{\sseq@ygridstep}}
+    \pgf@xb=\pgf@x
+    \pgf@yb=\pgf@y
+}
+
+% #1 -- macro to store result in
+% #2 -- "x" or "y" as appropriate
+% #3 -- length (with units)
+% #4 -- fraction of gridstep
+% If #2 is x, then it either sets #1 to #3/(x scale) or xgridstep*#4, whichever is smaller
+% The output is intended for use with \pgfpointxy.
+\def\sseq@grid@atmostgridstep#1#2#3#4{
+    \ifdim#3<\dimexpr\csname pgf@#2b\endcsname*#4\relax
+        \pgfmathparse{#3/\csname pgf@#2a\endcsname}
+        \let#1\pgfmathresult
+    \else
+        \edef#1{\csname sseq@#2gridstep\endcsname*#4}
+    \fi
+}
+
+% This grid was a huge pain in the ass to get right...
 \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
+    \bgroup
+    \pgfscope
+    % Pad on the right and top by either the grid padding, or the remaining piece of the checkerboard before it would start a new square
+    % (it looks ugly to have a tiny sliver). Annoyingly, mod returns its result with the same sign as its input, so in order to reduce mod
+    % \sseq@xgridstep and get a positive result, we have to do it twice. The 0.5cm*scale here matches the -0.5 in the \pgfpathgrid call.
+    \pgfmathsetmacro\sseq@rightpadding{min(
+        \sseq@rightgridpadding,
+        1cm*  mod(mod(-\sseq@xmax,\sseq@xgridstep)+\sseq@xgridstep,\sseq@xgridstep)+0.5cm*\sseq@xscale-0.05cm
+    )}
+    \pgfmathsetmacro\sseq@toppadding{min(
+        \sseq@topgridpadding,
+        1cm * mod(mod(-\sseq@ymax,\sseq@ygridstep)+\sseq@ygridstep,\sseq@ygridstep)+0.5cm*\sseq@yscale-0.02cm
+    )}
+    % Because of complicated aliasing issues that arise when misusing the \pgfgrid command in this way,
+    % it's more convenient to add a clip than to actually stop things in the right place.
+    \clip        (\sseq@xmin-\sseq@xoffset,\sseq@ymin-\sseq@yoffset) ++ (-0.48, -0.48)
+        rectangle ([shift={(\sseq@rightpadding pt,\sseq@toppadding pt)}]\sseq@xmax,\sseq@ymax);
+%
+    \sseq@useclip
+    \pgfsetcolor{\sseq@gridcolor}
+    \pgfsetstrokeopacity{0.3} % We don't set low opacity for the other grids, but this one is visible even if it is very faint.
+    \sseq@grid@setstepandgridstep
+%
+%  Use ifdim with cm to compare real scalars b/c tex is dumb.
+    % okay, now we need to be careful in order to avoid overflows. The hack we are using requires that the xvec and the yvec are equal
+    % because we can't apply these via lowlevelsynccm. However, xvec and yvec are the things that prevent overflows.
+    % What we need to do is set them both equal to the smaller value. Now the scale factor determines the size of the squares,
+    % so we mix in the grid steps. We also need to scale the larger scaled coordinate by the ratio of the two scales.
+    \ifdim\sseq@xscale cm<\sseq@yscale cm\relax
+        % x is smaller so set both x and y vecs to \sseq@xscale cm.
+        \pgfsetxvec{\pgfpoint{\sseq@xscale cm}{0cm}}
+        \pgfsetyvec{\pgfpoint{0cm}{\sseq@xscale cm}}
+        \def\sseq@xadjustscale{\sseq@xgridstep}
+        \def\sseq@yadjustscale{\sseq@yscale/\sseq@xscale*\sseq@ygridstep}
+        \def\sseq@stepscale{\sseq@xscale}
+    \else
+        \pgfsetxvec{\pgfpoint{\sseq@yscale cm}{0cm}}
+        \pgfsetyvec{\pgfpoint{0cm}{\sseq@yscale cm}}
+        \def\sseq@xadjustscale{(\sseq@xscale/\sseq@yscale*\sseq@xgridstep)}
+        \def\sseq@yadjustscale{\sseq@ygridstep}
+        \def\sseq@stepscale{\sseq@yscale}
+    \fi
+    \pgftransformxscale{\sseq@xadjustscale}
+    \pgftransformyscale{\sseq@yadjustscale}
+    % Now we have to put in some ridiculously complicated shift in order to get the bottom corner in the right place.
+    % I found this formula mostly by trial and error.
+    % The basic idea that we should be making something divisible by twice the grid step (which is the actual period of our grid)
+    % is reasonable enough, but what the heck are these other two terms for? I don't know either, thank god it works.
+    \pgftransformshift{\pgfpointxy{
+            floor((\sseq@xgridstep-1)/2)/\sseq@xgridstep
+            + \ifodd\sseq@xgridstep\space 0 \else 0.5/\sseq@xgridstep\fi
+            + mod(1+\sseq@xmin/\sseq@xgridstep,2*\sseq@xgridstep)
+        }{
+            floor((\sseq@ygridstep-1)/2)/\sseq@ygridstep
+            + \ifodd\sseq@ygridstep\space 0\else 0.5/\sseq@ygridstep\fi
+            + mod(1+\sseq@ymin/\sseq@ygridstep,2*\sseq@ygridstep)
+        }
+    }
+    % We use lowlevelsynccm to make the scale adjust the line width. Normally scaling doesn't affect line width, text size, etc, which is sensible.
+    % When you apply \pgflowlevelsynccm, pgf loses track of the coordinate matrix and it gets indiscriminately applied to everything.
+    % This is good for us, because we're doing this absurd thing where we make a checkerboard by drawing a really really fat line.
+    \pgflowlevelsynccm
+    \pgfsetlinewidth{1cm*\sseq@stepscale}
+    \pgfsetdash{{1cm*\sseq@stepscale}{1cm*\sseq@stepscale}}{1cm*\sseq@stepscale}
+%
+    % Naturally some trial and error occurred here too.
+    % Note the huge multiples of \sseq@xgridstep I added in -- they probably aren't necessary, but I don't understand what's going on so whatever.
+    % The basic idea is that things need to be divisible by twice the grid step. The part I added in the shift above
+    % was the remainder when you divide \sseq@xmin by twice the grid step, now we need to add in the multiple of twice the grid step.
+    % The -0.5 is ensuring that the checkerboard boundaries lie at half-integer coordinates (I think).
+    \pgfpathgrid[stepx= 2cm*\sseq@stepscale,stepy=2cm*\sseq@stepscale]
+    { \pgfpointxy
+        { -0.5 + \sseq@intdivfloor{\numexpr\sseq@xmin - \sseq@xgridstep\relax}{2*\sseq@xgridstep}*2*\sseq@xgridstep + \sseq@xoffset - 50*\sseq@xgridstep }
+        { -0.5 + \sseq@intdivfloor{\numexpr\sseq@ymin - \sseq@ygridstep\relax}{2*\sseq@ygridstep}*2*\sseq@ygridstep + \sseq@yoffset - 50*\sseq@ygridstep}
+    }{ \pgfpointxy
+        { \sseq@xmax + \sseq@xoffset + 50*\sseq@xgridstep }
+        { \sseq@ymax + \sseq@yoffset + 50*\sseq@ygridstep  }
+    }
+    \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
+    \bgroup
+    \pgfscope
+    \sseq@useclip
+    \pgfsetcolor{\sseq@gridcolor}
+    \pgfsetlinewidth{\the\sseq@gridstrokethickness}
+    \sseq@grid@setstepandgridstep
+%
+    % We don't want the grid to end with an extra line, so extend it by one half the step distance or
+    % \sseq@---gridpadding, whichever is shorter.
+    \sseq@grid@atmostgridstep\sseq@xminpadding{x}{\sseq@leftgridpadding}{1/2}
+    \sseq@grid@atmostgridstep\sseq@xmaxpadding{x}{\sseq@rightgridpadding}{1/2}
+    \sseq@grid@atmostgridstep\sseq@yminpadding{y}{\sseq@bottomgridpadding}{1/2}
+    \sseq@grid@atmostgridstep\sseq@ymaxpadding{y}{\sseq@topgridpadding}{1/2}
+%
+    \pgftransformshift{\pgfpointxy{-\sseq@xgridstep/2}{-\sseq@ygridstep/2}}
+    \pgfpathgrid[stepx=\pgf@xb,stepy=\pgf@yb]
+    { \pgfpointxy
+        { \sseq@xmin - \sseq@xminpadding + 0.01 + \sseq@xoffset + \sseq@xgridstep/2 }
+        { \sseq@ymin - \sseq@yminpadding + 0.01 + \sseq@yoffset + \sseq@ygridstep/2 } }
+    { \pgfpointxy
+        { \sseq@xmax + \sseq@xmaxpadding - 0.01 + \sseq@xoffset + \sseq@xgridstep/2 }
+        { \sseq@ymax + \sseq@ymaxpadding - 0.01 + \sseq@yoffset + \sseq@ygridstep/2 } }
+    \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
+    \bgroup
+    \pgfscope
+    \sseq@useclip
+    \pgfsetcolor{\sseq@gridcolor}
+    \pgfsetlinewidth{\the\sseq@gridstrokethickness}
+    \sseq@grid@setstepandgridstep
+%
+    % We don't want the grid to end with an extra line, so extend it by one step distance or
+    % \sseq@---gridpadding, whichever is shorter.
+    \sseq@grid@atmostgridstep\sseq@xminpadding{x}{\sseq@leftgridpadding}{1}
+    \sseq@grid@atmostgridstep\sseq@xmaxpadding{x}{\sseq@rightgridpadding}{1}
+    \sseq@grid@atmostgridstep\sseq@yminpadding{y}{\sseq@bottomgridpadding}{1}
+    \sseq@grid@atmostgridstep\sseq@ymaxpadding{y}{\sseq@topgridpadding}{1}
+%
+    \pgfpathgrid[stepx=\pgf@xb,stepy=\pgf@yb]
+    { \pgfpointxy
+        { \sseq@xmin - \sseq@xminpadding + 0.01 + \sseq@xoffset }
+        { \sseq@ymin - \sseq@yminpadding + 0.01 + \sseq@yoffset } }
+    { \pgfpointxy
+        { \sseq@xmax + \sseq@xmaxpadding - 0.01 + \sseq@xoffset }
+        { \sseq@ymax + \sseq@ymaxpadding - 0.01 + \sseq@yoffset }
+    }
+    \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
+    \bgroup
+    \pgfscope
+    \pgfgettransform\sseq@savetransform
+    \pgfgettransformentries{\sseq@a}{\sseq@b}{\sseq@c}{\sseq@d}{\sseq@u}{\sseq@v}
+    \pgfsettransform\sseq@savetransform
+    \sseq@useclip
+    \pgftransformshift{\pgfqpoint{-1.5cm}{-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{\pgfpointxy{\sseq@xmin + 0.5/\sseq@a}{\the\sseq@tempy}}
+    \pgfpathlineto{\pgfpointxy{\sseq@xmax + 1.01 }{\the\sseq@tempy}}
+    \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
@@ -261,6 +538,7 @@
     (-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);
@@ -270,15 +548,21 @@
     (-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}}}
+    \sseq@eval{\@nx\pgftransformshift{
+        \@nx\pgfqpointxy
+            { \csname sseq@\sseq@classpattern xoffset#1/#2\endcsname }
+            { \csname sseq@\sseq@classpattern yoffset#1/#2\endcsname }
+    }}
 }
 \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}
+    \edef\sseq@thisposnum{\sseq@obj{class.(#2,#3,#4).n}}
     \def\sseq@thisclassnum{#5}
+    \sseq@tempx=#2\relax
+    \sseq@tempy=#3\relax
 }
 
 \def\sseqtooltip#1#2{%
@@ -298,11 +582,14 @@
 }
 
 % #1 -- the name of the node object
+% Someday I should document this horrible mess of code here
+\newif\ifsseq@permanentcycle
+\newcount\sseq@totalclassesdrawn
+\AtEndDocument{\message{Total classes: \the\sseq@totalclassesdrawn}}
 \def\sseq@class@drawnode#1{%
+    \global\advance\sseq@totalclassesdrawn\@ne
     \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
@@ -318,7 +605,7 @@
         \the\sseq@scope@toks
         \sseq@obj{#1.needstikz}
 %
-    \sseq@outofrangetrue
+    \sseq@outofrangetrue\relax % Mysterious that we need this \relax here...
     \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
@@ -329,17 +616,19 @@
             \sseq@thesseqstyle
             \sseq@theclassstyle
             \ifnum\sseq@obj{#1.page}=\sseq@infinitycount
+                \sseq@permanentcycletrue % This is to communicate with family style code...
                 \sseq@thepermanentcyclestyle
             \else
+                \sseq@permanentcyclefalse
                 \sseq@thetransientcyclestyle
                 \ifsseq@thispage
                     \sseq@thethispagecyclestyle
                 \fi
             \fi
+            \def\sseq@collections@featuretype{class}
             \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}}}
+        \pgftransformshift{\pgfqpointxy{\numexpr\sseq@tempx +\sseq@xoffset-\sseq@x\relax}{\numexpr\sseq@tempy + \sseq@yoffset-\sseq@y\relax}}
         \iftikz@fullytransformed\pgfgettransform{\savetransform}\fi
         \pgftransformresetnontranslations
         \sseq@globalrotatetransform
@@ -351,24 +640,23 @@
         \tikz@options
         \ifsseq@needstikz
             \let\sseq@mode\tikz@mode
-            \tikzset{every text node part/.code/.expand once={\sseq@globalrotatetransform\sseq@obj{#1.nodetext.options}}}%
+            \tikzset{every text node part/.code/.expand once={\sseq@globalrotatetransform\sseq@obj@ifdef{#1.nodetext.options}{\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};
+                ] (\sseq@thisnodename) {\sseq@obj@ifdef{#1.nodetext}{\unexpanded\@xpthree{\sseq@obj{#1.nodetext}}}{}}
+                [every text node part/.code={}];
             }%
         \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
+            \edef\sseq@classnodetextoptions{\sseq@obj@ifdef{#1.nodetext.options}{\@xptwo\@nx\sseq@obj{#1.nodetext.options}}{}}
+            \edef\sseq@classnodetext{\sseq@obj@ifdef{#1.nodetext}{\@xptwo\@nx\sseq@obj{#1.nodetext}}{}}
+            \sseq@setnodetext{\sseq@classnodetext}{\sseq@classnodetextoptions}
             \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{#1.labelnodes}
         \sseq@obj@ifdef{#1.tooltip}{
             \pgfpointanchor{\sseq@thisnodename}{west}
             \pgf@xa=\pgf@x
@@ -386,7 +674,7 @@
                 \endpgfinterruptpicture
             }
             {%
-                \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}%
+                \pgftransformshift{\pgfqpoint{\pgf@xa}{\pgf@ya}}%
                 \pgfapproximatenonlineartransformation%
                 \pgfqboxsynced{\tikz@tempbox}%
             }%
@@ -394,8 +682,7 @@
         \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}}}
+        \sseq@eval{\@nx\pgftransformshift{\@nx\pgfqpointxy{\numexpr\sseq@tempx+\sseq@xoffset-\sseq@x\relax}{\numexpr\sseq@tempy+\sseq@yoffset-\sseq@y\relax}}}%
         \pgftransformresetnontranslations
         \sseq@globalrotatetransform
         \sseq@classplacementtransform
@@ -404,11 +691,14 @@
     \fi
     \endgroup
 }
-\def\sseq@setnodetext{%
+
+% #1 -- label text
+% #2 -- options
+\def\sseq@setnodetext#1#2{%
     \setbox\pgfnodeparttextbox=\hbox{%
         \pgfscope%
+        #2
         \tikzset{every text node part/.try}%
-        \sseq@classnodetextoptions
         \ifx\tikz@textopacity\pgfutil@empty%
         \else%
          \pgfsetfillopacity{\tikz@textopacity}%
@@ -430,7 +720,7 @@
         \fi%
         \pgfsetcolor{.}%
           \tikz@atbegin@node%
-          \sseq@classnodetext%
+          #1%
           \tikz@atend@node%
            \ifx\tikz@text@width\pgfutil@empty%
            \else%
@@ -489,6 +779,51 @@
   \global\pgflinewidth=\pgfutil@tempdima%
 }
 
+%%% Labels
+
+% #1 -- label text
+% #2 -- options
+\def\sseq@drawlabel#1#2{
+    \bgroup\pgfscope
+    \def\tikz@mode{}
+    \let\sseq@tikz@transform@save\tikz@transform
+    \pgfkeyssetvalue{/pgf/inner xsep}{2pt}
+    \pgfkeyssetvalue{/pgf/inner ysep}{2pt}
+    \def\tikz@shape{rectangle}
+    \let\tikz@transform\empty % The next line was set up to fix the classlabelstyle glitch
+    \sseq@options@secondpassmode
+    \sseq@thesseqstyle\sseq@thelabelstyle\sseq@theclasslabelstyle#2
+    \tikz@options
+    \pgftransformreset
+    \pgftransformshift{\tikz@node@at}
+    \tikz@lib@pos@call
+    \tikz@transform
+    \tikz@mode
+    \let\tikz@transform\sseq@tikz@transform@save
+    \sseq@setnodetext{\sseq@labeltextfn{#1}}{}
+    \pgfmultipartnode{\tikz@shape}{\tikz@anchor}{label}{\sseq@drawnode}%
+    \ifsseq@pin
+        \def\sseq@pinoptions{}
+        \let\tikz@options\empty
+        \let\tikz@mode\empty
+        \sseq@thepinstyle
+        #2
+        \sseq@pinoptions
+        \tikz@options
+        \tikz@mode
+        \sseq@drawedge@findsourcetarget{\tikz@fig@name}{}{label}{}
+        \pgfpathmoveto{\sseq@sourcecoord}%
+        \pgfpathlineto{\sseq@targetcoord}%
+        \sseq@eval{\noexpand\pgfusepath{%
+            draw
+            \iftikz@mode@fill fill,\fi
+            \iftikz@mode@draw draw,\fi
+        }}%
+    \fi
+    \endpgfscope\egroup
+}
+
+
 %%%
 %%% Drawing edges
 %%%
@@ -506,6 +841,34 @@
     \fi
 }
 
+% #1 -- source node
+% #2 -- source anchor
+% #3 -- target node
+% #4 -- target anchor
+% Calculate actual start and end of the edge (node borders), return the results stored in \sseq@sourcecoord, \sseq@targetcoord
+\def\sseq@drawedge@findsourcetarget#1#2#3#4{
+    \edef\sseq@edgesourceanchor{#2}
+    \edef\sseq@edgetargetanchor{#4}
+    \let\tempaf\pgfutil@empty
+    \ifx\sseq@edgesourceanchor\pgfutil@empty % Check that the source doesn't have a specified anchor
+        \def\tempa{\pgfpointanchor{#1}{center}}% if so, start by taking the center of that coordinate
+    \else
+        \edef\tempa{\@nx\pgfpointanchor{#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{#3}{\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{#3}{\sseq@edgetargetanchor}}% If it has a specified anchor, use that
+    \fi
+    \let\tempbf\tempb
+    \ifx\tempaf\pgfutil@empty%
+        \def\tempaf{\pgfpointshapeborder{#1}{\tempb}}%
+    \fi
+    \let\sseq@sourcecoord\tempaf
+    \let\sseq@targetcoord\tempbf
+}
+
 \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)
@@ -514,7 +877,15 @@
 % #4 -- options
 \def\sseq@drawedge(#1)(#2)#3#4{%
     \begingroup\pgfscope
+    % If either class is part of a family we aren't drawing, don't draw the edge either.
+    \expandafter\ifx\csname pgf@sh@pi@sseq{#1}\endcsname\pgfpictureid\else
+        \@xp\sseq@break
+    \fi    
+    \expandafter\ifx\csname pgf@sh@pi@sseq{#2}\endcsname\pgfpictureid\else
+        \@xp\sseq@break
+    \fi    
     \def\sseq@edgetype{#3}
+    \let\sseq@collections@featuretype\sseq@edgetype
     \let\sseq@edgesourceanchor\pgfutil@empty
     \let\sseq@edgetargetanchor\pgfutil@empty
 %
@@ -524,40 +895,34 @@
     \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
+    \csname sseq@collections@#3@hook\endcsname
+    \pgftransformshift{\pgfqpointxy{-\the\sseq@x}{-\the\sseq@y}}%
+    % puts results into \sseq@sourcecoord and \sseq@targetcoord
+    \sseq@drawedge@findsourcetarget{sseq{#1}}{\sseq@edgesourceanchor}{sseq{#2}}{\sseq@edgetargetanchor}
 %
     \tikz@options
     \tikz@mode
     \def\temparrowstartspec{}%
     \def\temparrowendspec{}%
-    \pgfcoordinate{tempa}{\tempaf}%
-    \pgfcoordinate{tempb}{\tempbf}%
+    \pgfcoordinate{tempa}{\sseq@sourcecoord}%
+    \pgfcoordinate{tempb}{\sseq@targetcoord}%
     \pgftransformreset
-    \sseq@ifinrange(#1){\sseq@ifinrange(#2){\sseq@outofrangefalse}{\sseq@outofrangetrue}}{\sseq@outofrangetrue}%
+    \sseq@outofrangefalse
+    \sseq@ifinrange(#1){}{
+        \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@#3@spec\endcsname}}
+        \sseq@outofrangetrue
+    }%
+    \sseq@ifinrange(#2){}{
+        \edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@#3@spec\endcsname}}
+        \sseq@outofrangetrue
+    }
     \ifsseq@outofrange
-        \sseq@handleoffpageedge{#1}{#2}{#3}%
+        \sseq@handleoffpageedge{#1}{#2}%
     \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}
+        \pgfpointdiff{\sseq@targetcoord}{\sseq@sourcecoord}
         \pgfmathveclen{\pgf@x}{\pgf@y}%
         \@xp\pgfmathint\@xp{\pgfmathresult}%
         \ifnum\pgfmathresult<10\relax%%17? % TODO: Fix this predicate
@@ -591,10 +956,10 @@
     \endpgfscope\endgroup
 }
 
-% TODO: this macro is super expensive. Make it faster (avoid
-\def\sseq@handleoffpageedge#1#2#3{
-    \pgfpathmoveto{\tempaf}%
-    \pgfpathlineto{\tempbf}%
+% TODO: this macro is super expensive. Make it faster
+\def\sseq@handleoffpageedge#1#2{
+    \pgfpathmoveto{\sseq@sourcecoord}%
+    \pgfpathlineto{\sseq@targetcoord}%
     \pgfgetpath\thispath
     \pgfusepath{discard}%
     \pgfintersectionofpaths{\pgfsetpath\sseq@theclippath}{\pgfsetpath\thispath}%
@@ -603,20 +968,16 @@
         \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
+            \sseq@ifinrange(#2){}{\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}
+            \def\sseq@targetcoord{\pgfpointintersectionsolution{1}}
+            \pgfcoordinate{tempb}{\sseq@targetcoord}
         }{%
             \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}%
+                \def\sseq@sourcecoord{\pgfpointintersectionsolution{1}}%
+                \pgfcoordinate{tempa}{\sseq@sourcecoord}%
             }{\sseq@drawedge@handletrickyedge}% Uh-oh, both ends are out of range.
         }
     \or% an orphan
@@ -653,26 +1014,33 @@
 
 
 \def\sseq@drawedge@handleorphan{%
-    \def\tempaf{\pgfpointintersectionsolution{1}}%
-    \def\tempbf{\pgfpointintersectionsolution{2}}%
+    \def\sseq@sourcecoord{\pgfpointintersectionsolution{1}}%
+    \def\sseq@targetcoord{\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}%
+    \pgfcoordinate{tempa}{\sseq@sourcecoord}%
+    \pgfcoordinate{tempb}{\sseq@targetcoord}%
 }
 
 
-%
-% #1 -- first coordinate
-% #2 -- second coordinate
-% #3 -- uid
+% #1 -- uid
+% #2 -- first coordinate
+% #3 -- second coordinate
 \def\sseq@circleclass@draw#1#2#3{
     \begingroup
+        % If either class is part of a family we aren't drawing, don't draw the fit either.
+        \expandafter\ifx\csname pgf@sh@pi@sseq{#2}\endcsname\pgfpictureid\else
+            \@xp\sseq@break
+        \fi
+        \expandafter\ifx\csname pgf@sh@pi@sseq{#3}\endcsname\pgfpictureid\else
+            \@xp\sseq@break
+        \fi
         \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
+        \sseq@options@secondpassmode
         \node[
             rotate fit=\tempangle,
             /utils/exec={\sseq@thesseqstyle\sseq@thecircleclassstyle\the\sseq@scope@toks\sseq@savedoptioncode
@@ -681,6 +1049,7 @@
                 \@xp\pgfkeysalso\@xp{\romannumeral0\sseq@obj{#1.tikzprimoptions}}
             }
         ] {};
+        \sseq@breakpoint
     \endgroup
 }
 % Modifies tikz commands \tikz@lib@fit@scan@handle from \pgf\frontendlayer\tikz\libraries\tikzlibraryfit.code.tex line 81 and
@@ -711,6 +1080,94 @@
 }
 
 
+%%
+%% Patch tikz coords
+%%
+
+\def\sseq@patchtikzcoords{
+    \let\sseq@tikz@scan@one@point@noshift\sseq@tikz@scan@one@point@noshift@active
+    \tikzoption{shift}{\sseq@tikzshift{##1}}
+    \let\tikz@@@parse@regular\sseq@tikz@@@parse@regular
+    \let\tikz@to@curve@path\sseq@tikz@to@curve@path
+    \let\tikz@@@to@compute@relative\sseq@tikz@@@to@compute@relative
+
+    \let\tikz@grid\sseq@tikz@grid
+    \let\tikz@scan@handle@options\sseq@tikz@scan@handle@options
+    \let\tikz@@@parse@polar\sseq@tikz@@@parse@polar
+}
+
+% Some of the stuff in tikzlibrarycalc will probably be broken, hopefully not too much
+\let\sseq@tikz@scan@one@point@noshift\tikz@scan@one@point
+\let\sseq@tikz@@@parse@regular@save\tikz@@@parse@regular
+
+\def\sseq@tikz@scan@one@point@noshift@active#1{%
+    \let\tikz@@@parse@regular\sseq@tikz@@@parse@regular@save
+    \def\sseq@scanonepoint@cmd{\let\tikz@@@parse@regular\sseq@tikz@@@parse@regular#1}
+    \tikz@scan@one@point\sseq@scanonepoint@cmd%
+}
+
+% Probably there are more places that shouldn't have shifts inserted.
+\def\sseq@tikzshift#1{\tikz@addtransform{\sseq@tikz@scan@one@point@noshift\pgftransformshift#1\relax}}
+
+
+\def\sseq@tikz@to@curve@path{%
+  [every curve to]
+  \pgfextra{
+    \let\tikz@@@parse@regular\sseq@tikz@@@parse@regular@save % I added this to prevent repeated offsets from screwing us up
+    %\let\sseq@tikz@scan@one@point@noshift\tikz@scan@one@point
+    \iftikz@to@relative\tikz@to@compute@relative\else\tikz@to@compute\fi
+  }
+  \tikz@computed@path
+  \tikztonodes%
+}
+
+\let\sseq@tikz@@@to@compute@relative\tikz@@@to@compute@relative
+
+
+\patchcmd\sseq@tikz@@@to@compute@relative{%
+    \let\tikz@second@point=\tikz@toto
+}{%
+    \pgf@process{\pgfpointadd{\tikz@toto}{\pgfqpointxy{\sseq@xoffset}{\sseq@yoffset}}}%
+    \edef\tikz@toto{\@nx\pgfpoint{\the\pgf@x}{\the\pgf@y}}%
+    \let\tikz@second@point=\tikz@toto
+}{}{\error}
+
+
+
+
+% \tikz@parse@splitxyz: we should set up an error to make this unreachable?
+\let\sseq@tikz@grid\tikz@grid % line 3158
+\let\sseq@tikz@scan@handle@options\tikz@scan@handle@options % 4959
+\let\sseq@tikz@@@parse@polar\tikz@@@parse@polar % 5063
+
+\def\sseq@tikz@@@parse@regular#1#2#3){%
+  \pgfutil@in@,{#3}%
+  \ifpgfutil@in@%
+    \tikz@parse@splitxyz{#1}{#2}#3,%
+  \else%
+    \tikz@checkunit{#2}%
+    \iftikz@isdimension%
+      \tikz@checkunit{#3}%
+      \iftikz@isdimension%
+        \def\@next{#1{\pgfpointxy{(#2)/1cm+\sseq@xoffset}{(#3)/1cm+\sseq@yoffset}}}%
+      \else%
+        \def\@next{#1{\pgfpointxy{(#2)/1cm+\sseq@xoffset}{#3+\sseq@yoffset}}}%
+      \fi%
+    \else%
+      \tikz@checkunit{#3}%
+      \iftikz@isdimension%
+        \def\@next{#1{\pgfpointxy{#2+\sseq@xoffset}{(#3)/1cm+\sseq@yoffset}}}%
+      \else%
+        \def\@next{#1{\pgfpointxy{#2+\sseq@xoffset}{#3+\sseq@yoffset}}}%
+      \fi%
+    \fi%
+  \fi%
+  \@next%
+}
+
+
+
+
 %% New shapes and arrows
 %% These use lots of keys with spaces so it's convenient to turn off ExplSyntax.
 
@@ -987,4 +1444,5 @@
         \pgfusepathqfill
     },
     defaults = { length = 0.3cm }
-} 
\ No newline at end of file
+}
+
-- 
cgit v1.2.3

