% graphical calculus for Frobenius algebras
% Clara L\"oh 12/2009
%
% 2do [will be added soon ... ]:
%  * better baseline for graphcalc-environment
%  * different backends
%  * hooks for labels of parts
%  * make style file and documentation CTAN-ready
\ProvidesPackage{frobeniusgraphcalc}[2009/12/29 LaTeX2e style file for graphical calculus for Frobenius algebras]

\RequirePackage{amsmath}
\RequirePackage{tikz}
\usetikzlibrary{calc}

%%% colour settings
\def\gcolour{black}
\def\gfillcolour{blue}
\def\gopacity{0.5}
\def\gidcolour{\gfillcolour}
\def\gmucolour{\gfillcolour}
\def\gdeltacolour{\gfillcolour}
\def\gepsiloncolour{\gfillcolour}
\def\gunitcolour{\gfillcolour}
\def\gbetacolour{\gfillcolour}
\def\ggammacolour{\gfillcolour}
\def\gtwistcolour{\gfillcolour}

%%% internal settings
\def\soneradius{0.25}
\def\soneradiusunit{0.25cm}
\def\gvsep{1}
\def\ghsep{1}
% S^1
\def\sonec@rve#1{#1 circle (0.5*\soneradius{} and \soneradius)}
\def\sone#1{\draw \sonec@rve{#1};}
\def\sonefr@nt#1{#1 arc (90:270:0.5*\soneradius{} and \soneradius)}
\def\sonefr@ntinv#1{#1 arc (270:90:0.5*\soneradius{} and \soneradius)}
\def\soneb@ck#1{}

\newcounter{vcorr}
\newcounter{targetvcorr}
\newcounter{voffset}
\newcounter{targetvoffset}
\newcounter{hoffset}

\newcounter{coutput}

% the "current" coordinate (incl all vertical and horizontal offsets)
\def\currentcoord#1{%
  ( \value{hoffset}*\ghsep
  , #1 * \gvsep+ \vcorrection-1*\value{voffset}*\gvsep)
}
\def\currentcoordtop#1{%
  ( \value{hoffset}*\ghsep
  ,  #1 * \gvsep+ \vcorrection-1*\value{voffset}*\gvsep
   + \soneradius)
}
\def\currentcoordbot#1{%
  ( \value{hoffset}*\ghsep
  ,  #1 * \gvsep+ \vcorrection-1*\value{voffset}*\gvsep
   - \soneradius)
}

% the "current" target coordinate
\def\targetcoord#1{%
  ( \value{hoffset}*\ghsep+\ghsep
  , #1 * \gvsep + \targetvcorrection-1*\value{targetvoffset}*\gvsep)
}
\def\targetcoordtop#1{%
  ( \value{hoffset}*\ghsep+\ghsep
  , #1 * \gvsep + \targetvcorrection-1*\value{targetvoffset}*\gvsep
   + \soneradius)
}
\def\targetcoordbot#1{%
  ( \value{hoffset}*\ghsep+\ghsep
  , #1 * \gvsep + \targetvcorrection-1*\value{targetvoffset}*\gvsep
   - \soneradius)
}
% for the smooth curves ...
\def\smoothfromto{%
  .. controls +(0:0.4) and +(180:0.4) ..
}
\def\smoothtofrom{%
  .. controls +(180:0.4) and +(0:0.4) .. 
}
\def\smoothleft#1{%
  .. controls +(180:#1) and +(180:#1) ..
}
\def\smoothright#1{%
  .. controls +(0:#1) and +(0:#1) ..
}

% identity
\def\gid{%
  \gdef\c@rrentop{%
    \gidgraphics
  }
}
\def\gidpath{%
  \sonefr@nt{\currentcoordtop0}
  \smoothfromto \sonefr@ntinv{\targetcoordbot0}
  \smoothtofrom \currentcoordtop0 
  -- cycle
}
\def\gidgraphics{%
  \sone{\currentcoord0}
  \sone{\targetcoord0}
  \draw\gidpath;
  \fill[opacity=\gopacity,color=\gidcolour]
    \gidpath;
}

% multiplication
\def\gmu{%
  \gdef\c@rrentop{%
    \gmugraphics
    \addtocounter{voffset}{1}
  }
  \addtocounter{coutput}{-1}
}
\def\gmupath{%
  \sonefr@nt{\currentcoordtop0}
  \smoothright{0.3} \sonefr@nt{\currentcoordtop{-1}}
  \smoothfromto \sonefr@ntinv{\targetcoordbot0}
  \smoothtofrom \currentcoordtop0
  -- cycle
}
\def\gmugraphics{%
  \sone{\currentcoord0}
  \sone{\currentcoord{-1}}
  \sone{\targetcoord0}
  \draw\gmupath;
  \fill[opacity=\gopacity,color=\gmucolour]
    \gmupath;
}

% comultiplication
\def\gdelta{%
  \gdef\c@rrentop{%
    \gdeltagraphics
    \addtocounter{targetvoffset}{1}
  }
  \addtocounter{coutput}{1}
}
\def\gdeltapath{%
  \sonefr@nt{\currentcoordtop0}
  \smoothfromto \sonefr@ntinv{\targetcoordbot{-1}}
  \smoothleft{0.3} \sonefr@ntinv{\targetcoordbot0}
  \smoothtofrom \currentcoordtop0
  -- cycle
}
\def\gdeltagraphics{%
  \sone{\currentcoord0}
  \sone{\targetcoord0}
  \sone{\targetcoord{-1}}
  \draw\gdeltapath;
  \fill[opacity=\gopacity,color=\gdeltacolour]
    \gdeltapath;
}

% pairing beta
\def\gbeta{%
  \gdef\c@rrentop{%
    \gbetagraphics
    \addtocounter{targetvoffset}{-1}
    \addtocounter{voffset}{1}
  }
  \addtocounter{coutput}{-2}
}
\def\gbetapath{%
  \sonefr@nt{\currentcoordtop0}
  \smoothright{0.3} \sonefr@nt{\currentcoordtop{-1}}
  \smoothright{0.7} \currentcoordtop0
  -- cycle
}
\def\gbetagraphics{%
  \sone{\currentcoord0}
  \sone{\currentcoord{-1}}
  \draw\gbetapath;
  \fill[opacity=\gopacity,color=\gbetacolour]
    \gbetapath;
}

% copairing gamma
\def\ggamma{%
  \gdef\c@rrentop{%
    \ggammagraphics
    \addtocounter{targetvoffset}{1}
    \addtocounter{voffset}{-1}
  }
  \addtocounter{coutput}{2}
}
\def\ggammapath{%
  \sonefr@ntinv{\targetcoordbot{-1}}
  \smoothleft{0.3} \sonefr@ntinv{\targetcoordbot0}
  \smoothleft{0.7} \targetcoordbot{-1}
}
\def\ggammagraphics{%
  \sone{\targetcoord0}
  \sone{\targetcoord{-1}}
  \draw\ggammapath;
  \fill[opacity=\gopacity,color=\ggammacolour]
    \ggammapath;
}

% Frobenius form
\def\gepsilon{%
  \gdef\c@rrentop{%
    \gepsilongraphics
    \addtocounter{targetvoffset}{-1}
  }
  \addtocounter{coutput}{-1}
}
\def\gepsilonpath{%
  \sonefr@nt{\currentcoordtop0}
  \smoothright{0.5} \currentcoordtop0
  -- cycle
}
\def\gepsilongraphics{%
  \sone{\currentcoord0}
  \draw\gepsilonpath;
  \fill[opacity=\gopacity,color=\gepsiloncolour]
    \gepsilonpath;
}

% unit (eta)
\def\gunit{%
  \gdef\c@rrentop{%
    \gunitgraphics
    \addtocounter{voffset}{-1}
  }
  \addtocounter{coutput}{1}
}
\def\gunitpath{%
  \sonefr@ntinv{\targetcoordbot0}
  \smoothleft{0.5} \targetcoordbot0
  -- cycle
}
\def\gunitgraphics{%
  \sone{\targetcoord0}
  \draw\gunitpath;
  \fill[opacity=\gopacity,color=\gunitcolour]
    \gunitpath;
}

% twist
\def\gtwist{%
  \gdef\c@rrentop{%
    \gtwistgraphics
    \addtocounter{targetvoffset}{1}
    \addtocounter{voffset}{1}
  }
}
\def\gtwistpathtop{%
  \sonefr@nt{\currentcoordtop0}
  \smoothfromto \sonefr@ntinv{\targetcoordbot{-1}}
  \smoothtofrom \currentcoordtop0
}
\def\gtwistpathbot{%
  \sonefr@nt{\currentcoordtop{-1}}
  \smoothfromto \sonefr@ntinv{\targetcoordbot0}
  \smoothtofrom \currentcoordtop{-1}
}
\def\gtwistgraphics{%
  \sone{\currentcoord0}
  \sone{\currentcoord{-1}}
  \sone{\targetcoord0}
  \sone{\targetcoord{-1}}
  \draw \gtwistpathtop;
  \draw \gtwistpathbot;
  \begin{scope}[opacity=\gopacity, transparency group]
    \fill[color=\gtwistcolour] \gtwistpathtop;
    \fill[color=\gtwistcolour] \gtwistpathbot;
  \end{scope}
}

% handle all the stuff via lists
% append function for lists
% (similar: \g@addto@macro (latex.ltx))
% TeX book, p 378
\def\listc@ns{\relax}
% token list registers for temp use
\toksdef\ta=0
\toksdef\tb=2
\long\def\append#1\to#2{%
  \ta={\listc@ns{#1}}%
  \tb=\expandafter{#2}%
  \xdef#2{\the\tb\the\ta}%
  }
% typeset one column
\def\typesetlistofops#1{%
  \def\listc@ns{%
    \addtocounter{voffset}{1}
    \addtocounter{targetvoffset}{1}
  }
  #1
}

% tensor product
\def\gtensor{%
  \expandafter\append\c@rrentop\to\list@fops
  }

% "inverse" composition
\def\gcomp{%
  \gtensor
  \resettargetd@ta
  \typesetlistofops\list@fops
  \resetdomaind@ta
}
\def\resetdomaind@ta{%
  \def\list@fops{\relax}
  \setcounter{voffset}{-1}
  \setcounter{vcorr}{\value{coutput}}
  \addtocounter{vcorr}{-1}
  \xdef\vcorrection{0.5*\value{vcorr}*\gvsep}
  \addtocounter{hoffset}{1}
  \setcounter{targetvoffset}{-1}
}
\def\resettargetd@ta{%
  \setcounter{targetvcorr}{\value{coutput}}
  \addtocounter{targetvcorr}{-1}
  \xdef\targetvcorrection{0.5*\value{targetvcorr}*\gvsep}
}
% domain vector space of dim #1
\def\gvec#1{%
  \setcounter{coutput}{#1}
  \setcounter{hoffset}{0}
  \resetdomaind@ta
}

% wrapper environment for graphical calculations
\newenvironment{graphcalc}[1][x=1cm,y=1cm]
  {\begin{tikzpicture}[#1,baseline=(current bounding box.center)
                      ,color=\gcolour]}
  {\gcomp\end{tikzpicture}}

