diff options
Diffstat (limited to 'Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex')
-rw-r--r-- | Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex | 990 |
1 files changed, 990 insertions, 0 deletions
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 |